@@ -851,6 +851,86 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
851851 }
852852 break ;
853853 }
854+ case DW_AT_LLVM_stmt_sequence: {
855+ // Make sure the offset in the DW_AT_LLVM_stmt_sequence attribute is valid
856+ // and points to a valid sequence offset in the line table.
857+ auto SectionOffset = AttrValue.Value .getAsSectionOffset ();
858+ if (!SectionOffset) {
859+ ReportError (" Invalid DW_AT_LLVM_stmt_sequence encoding" ,
860+ " DIE has invalid DW_AT_LLVM_stmt_sequence encoding" );
861+ break ;
862+ }
863+ if (*SectionOffset >= U->getLineSection ().Data .size ()) {
864+ ReportError (
865+ " DW_AT_LLVM_stmt_sequence offset out of bounds" ,
866+ " DW_AT_LLVM_stmt_sequence offset is beyond .debug_line bounds: " +
867+ llvm::formatv (" {0:x8}" , *SectionOffset));
868+ break ;
869+ }
870+
871+ // Get the line table for this unit to validate bounds
872+ const auto *LineTable = DCtx.getLineTableForUnit (U);
873+ if (!LineTable) {
874+ ReportError (" DW_AT_LLVM_stmt_sequence without line table" ,
875+ " DIE has DW_AT_LLVM_stmt_sequence but compile unit has no "
876+ " line table" );
877+ break ;
878+ }
879+
880+ // Get the DW_AT_stmt_list offset from the compile unit DIE
881+ DWARFDie CUDie = U->getUnitDIE ();
882+ auto StmtListOffset = toSectionOffset (CUDie.find (DW_AT_stmt_list));
883+ if (!StmtListOffset) {
884+ ReportError (" DW_AT_LLVM_stmt_sequence without DW_AT_stmt_list" ,
885+ " DIE has DW_AT_LLVM_stmt_sequence but compile unit has no "
886+ " DW_AT_stmt_list" );
887+ break ;
888+ }
889+
890+ const int8_t DwarfOffset =
891+ LineTable->Prologue .getFormParams ().getDwarfOffsetByteSize ();
892+ // Calculate the bounds of this specific line table
893+ uint64_t LineTableStart = *StmtListOffset;
894+ uint64_t PrologueLength = LineTable->Prologue .PrologueLength ;
895+ uint64_t TotalLength = LineTable->Prologue .TotalLength ;
896+ uint64_t LineTableEnd = LineTableStart + TotalLength + DwarfOffset;
897+
898+ // See DWARF definition for this, the following three do not
899+ // count toward prologue length. Calculate SequencesStart correctly
900+ // according to DWARF specification:
901+ uint64_t InitialLengthSize = DwarfOffset;
902+ // Version field is always 2 bytes
903+ uint64_t VersionSize = 2 ;
904+ uint64_t PrologueLengthSize = DwarfOffset;
905+ uint64_t SequencesStart = LineTableStart + InitialLengthSize + VersionSize +
906+ PrologueLengthSize + PrologueLength;
907+
908+ // Check if the offset is within the bounds of this specific line table
909+ if (*SectionOffset < SequencesStart || *SectionOffset >= LineTableEnd) {
910+ ReportError (" DW_AT_LLVM_stmt_sequence offset out of line table bounds" ,
911+ " DW_AT_LLVM_stmt_sequence offset " +
912+ llvm::formatv (" {0:x8}" , *SectionOffset) +
913+ " is not within the line table bounds [" +
914+ llvm::formatv (" {0:x8}" , SequencesStart) + " , " +
915+ llvm::formatv (" {0:x8}" , LineTableEnd) + " )" );
916+ break ;
917+ }
918+
919+ // Check if the offset matches any of the sequence offset.
920+ auto It =
921+ std::find_if (LineTable->Sequences .begin (), LineTable->Sequences .end (),
922+ [SectionOffset](const auto &Sequence) {
923+ return Sequence.StmtSeqOffset == *SectionOffset;
924+ });
925+
926+ if (It == LineTable->Sequences .end ())
927+ ReportError (
928+ " Invalid DW_AT_LLVM_stmt_sequence offset" ,
929+ " DW_AT_LLVM_stmt_sequence offset " +
930+ llvm::formatv (" {0:x8}" , *SectionOffset) +
931+ " does not point to a valid sequence offset in the line table" );
932+ break ;
933+ }
854934 default :
855935 break ;
856936 }
0 commit comments