hphp/runtime/vm/verifier/check_func.cpp
/**
 * Verify stack depth along all control flow paths
 */
Verify stack depth along all control flow paths
Verify stack depth along all control flow paths
bool FuncChecker::checkFlow() {
  bool ok = true;
  GraphBuilder builder(m_arena, m_func);
  m_graph = builder.build();
  m_info = new (m_arena) BlockInfo[m_graph->block_count];
  memset(m_info, 0, sizeof(BlockInfo) * m_graph->block_count);
  m_tmp_sig = new (m_arena) FlavorDesc[maxStack()];
  sortRpo(m_graph);
  State cur;
  initState(&cur);
  for (BlockPtrRange i = entryBlocks(m_graph); !i.empty();) {
    ok &= checkEdge(0, cur, i.popFront());
  }
  for (Block* b = m_graph->first_rpo; b; b = b->next_rpo) {
    copyState(&cur, &m_info[b->id].state_in);
    if (m_verbose) {
      std::cout << blockToString(b, m_graph, unit()) << std::endl;
    }
    for (InstrRange i = blockInstrs(b); !i.empty(); ) {
      PC pc = i.popFront();
      if (m_verbose) {
        std::cout << "  " << std::setw(5) << offset(pc) << ":" <<
                     stateToString(cur) << " " <<
                     instrToString((Op*)pc, unit()) << std::endl;
      }
      ok &= checkInputs(&cur, pc, b);
      if (isTF(pc)) ok &= checkTerminal(&cur, pc);
      if (isFF(pc)) ok &= checkFpi(&cur, pc, b);
      if (isIter(pc)) ok &= checkIter(&cur, pc);
      ok &= checkOutputs(&cur, pc, b);
    }
    ok &= checkSuccEdges(b, &cur);
  }
  for (Range<FixedVector<EHEnt> > i(m_func->ehtab()); !i.empty(); ) {
    const EHEnt& handler = i.popFront();
    if (handler.m_type == EHEnt::Type::Catch) {
      ok &= checkEHStack(handler, builder.at(handler.m_base));
    }
  }
  return ok;
}
bool FuncChecker :: checkFlow ( ) { bool ok = true ; GraphBuilder builder ( m_arena , m_func ) ; m_graph = builder . build ( ) ; m_info = new ( m_arena ) BlockInfo [ m_graph -> block_count ] ; memset ( m_info , 0 , sizeof ( BlockInfo ) * m_graph -> block_count ) ; m_tmp_sig = new ( m_arena ) FlavorDesc [ maxStack ( ) ] ; sortRpo ( m_graph ) ; State cur ; initState ( & cur ) ; for ( BlockPtrRange i = entryBlocks ( m_graph ) ; ! i . empty ( ) ; ) { ok &= checkEdge ( 0 , cur , i . popFront ( ) ) ; } for ( Block * b = m_graph -> first_rpo ; b ; b = b -> next_rpo ) { copyState ( & cur , & m_info [ b -> id ] . state_in ) ; if ( m_verbose ) { std :: cout << blockToString ( b , m_graph , unit ( ) ) << std :: endl ; } for ( InstrRange i = blockInstrs ( b ) ; ! i . empty ( ) ; ) { PC pc = i . popFront ( ) ; if ( m_verbose ) { std :: cout << " " << std :: setw ( 5 ) << offset ( pc ) << " " << stateToString ( cur ) << " " << instrToString ( ( Op * ) pc , unit ( ) ) << std :: endl ; } ok &= checkInputs ( & cur , pc , b ) ; if ( isTF ( pc ) ) ok &= checkTerminal ( & cur , pc ) ; if ( isFF ( pc ) ) ok &= checkFpi ( & cur , pc , b ) ; if ( isIter ( pc ) ) ok &= checkIter ( & cur , pc ) ; ok &= checkOutputs ( & cur , pc , b ) ; } ok &= checkSuccEdges ( b , & cur ) ; } for ( Range < FixedVector < EHEnt > > i ( m_func -> ehtab ( ) ) ; ! i . empty ( ) ; ) { const EHEnt & handler = i . popFront ( ) ; if ( handler . m_type == EHEnt :: Type :: Catch ) { ok &= checkEHStack ( handler , builder . at ( handler . m_base ) ) ; } } return ok ; }
Verify stack depth along all control flow paths
Verify stack depth along all control flow paths
// initialize state at all entry points // Make sure eval stack is correct at start of each try region