hphp/runtime/vm/verifier/check_func.cpp
/**
 * Make sure all offsets are in-bounds.  Offset 0 is unit->m_bc,
 * for all functions.  Jump instructions use an Offset relative to
 * the start of the jump instruction.
 */
Make sure all offsets are in-bounds.  Offset 0 is unit->m_bc,
for all functions.  Jump instructions use an Offset relative to
the start of the jump instruction.
Make sure all offsets are in - bounds . Offset 0 is unit - > m_bc for all functions . Jump instructions use an Offset relative to the start of the jump instruction .
bool FuncChecker::checkOffsets() {
  bool ok = true;
  assert(unit()->bclen() >= 0);
  PC bc = unit()->entry();
  Offset base = m_func->base();
  Offset past = m_func->past();
  checkRegion("func", base, past, "unit", 0, unit()->bclen(), false);
  SectionMap sections;
  for (Range<FixedVector<EHEnt> > i(m_func->ehtab()); !i.empty(); ) {
    const EHEnt& eh = i.popFront();
    if (eh.m_type == EHEnt::Type::Fault) {
      ok &= checkOffset("fault funclet", eh.m_fault, "func bytecode", base,
                        past, false);
      sections[eh.m_fault] = 0;
    }
  }
  Offset funclets = !sections.empty() ? sections.begin()->first : past;
  sections[base] = funclets; 
  for (Range<SectionMap> i(sections); !i.empty(); ) {
    Offset section_base = i.popFront().first;
    Offset section_past = i.empty() ? past : i.front().first;
    sections[section_base] = section_past;
    ok &= checkSection(section_base == base,
                       section_base == base ? "primary body" : "funclet body",
                       section_base, section_past);
  }
  for (Range<FixedVector<Func::ParamInfo> > p(m_func->params()); !p.empty(); ) {
    const Func::ParamInfo& param = p.popFront();
    if (param.hasDefaultValue()) {
      ok &= checkOffset("dv-entry", param.funcletOff(), "func body", base,
                        funclets);
    }
  }
   or one fault funclet
  for (Range<FixedVector<FPIEnt> > i(m_func->fpitab()); !i.empty(); ) {
    const FPIEnt& fpi = i.popFront();
    Offset fpi_base = fpiBase(fpi, bc);
    Offset fpi_past = fpiPast(fpi, bc);
    if (checkRegion("fpi", fpi_base, fpi_past, "func", base, past)) {
      Offset section_base = findSection(sections, fpi_base);
      Offset section_past = sections[section_base];
      ok &= checkRegion("fpi", fpi_base, fpi_past,
                        section_base == base ?  "func body" : "funclet",
                        section_base, section_past);
    } else {
      ok = false;
    }
  }
  for (Range<FixedVector<EHEnt> > i(m_func->ehtab()); !i.empty(); ) {
    const EHEnt& eh = i.popFront();
    if (eh.m_type == EHEnt::Type::Fault) {
      ok &= checkOffset("fault", eh.m_fault, "funclets", funclets, past);
    }
  }
  return ok;
}
bool FuncChecker :: checkOffsets ( ) { bool ok = true ; assert ( unit ( ) -> bclen ( ) >= 0 ) ; PC bc = unit ( ) -> entry ( ) ; Offset base = m_func -> base ( ) ; Offset past = m_func -> past ( ) ; checkRegion ( " " , base , past , " " , 0 , unit ( ) -> bclen ( ) , false ) ; SectionMap sections ; for ( Range < FixedVector < EHEnt > > i ( m_func -> ehtab ( ) ) ; ! i . empty ( ) ; ) { const EHEnt & eh = i . popFront ( ) ; if ( eh . m_type == EHEnt :: Type :: Fault ) { ok &= checkOffset ( " " , eh . m_fault , " " , base , past , false ) ; sections [ eh . m_fault ] = 0 ; } } Offset funclets = ! sections . empty ( ) ? sections . begin ( ) -> first : past ; sections [ base ] = funclets ; for ( Range < SectionMap > i ( sections ) ; ! i . empty ( ) ; ) { Offset section_base = i . popFront ( ) . first ; Offset section_past = i . empty ( ) ? past : i . front ( ) . first ; sections [ section_base ] = section_past ; ok &= checkSection ( section_base == base , section_base == base ? " " : " " , section_base , section_past ) ; } for ( Range < FixedVector < Func :: ParamInfo > > p ( m_func -> params ( ) ) ; ! p . empty ( ) ; ) { const Func :: ParamInfo & param = p . popFront ( ) ; if ( param . hasDefaultValue ( ) ) { ok &= checkOffset ( " " , param . funcletOff ( ) , " " , base , funclets ) ; } } for ( Range < FixedVector < FPIEnt > > i ( m_func -> fpitab ( ) ) ; ! i . empty ( ) ; ) { const FPIEnt & fpi = i . popFront ( ) ; Offset fpi_base = fpiBase ( fpi , bc ) ; Offset fpi_past = fpiPast ( fpi , bc ) ; if ( checkRegion ( " " , fpi_base , fpi_past , " " , base , past ) ) { Offset section_base = findSection ( sections , fpi_base ) ; Offset section_past = sections [ section_base ] ; ok &= checkRegion ( " " , fpi_base , fpi_past , section_base == base ? " " : " " , section_base , section_past ) ; } else { ok = false ; } } for ( Range < FixedVector < EHEnt > > i ( m_func -> ehtab ( ) ) ; ! i . empty ( ) ; ) { const EHEnt & eh = i . popFront ( ) ; if ( eh . m_type == EHEnt :: Type :: Fault ) { ok &= checkOffset ( " " , eh . m_fault , " " , funclets , past ) ; } } return ok ; }
Make sure all offsets are in-bounds.
Make sure all offsets are in - bounds .
// find instruction boundaries and make sure no branches escape // primary body // Get instruction boundaries and check branches within primary body // and each faultlet. // DV entry points must be in the primary function body // Every FPI region must be contained within one section, either the // primary body or one fault funclet // FPI is within whole func, but we also need to check within the section // check EH regions and targets