Skip to content

Commit

Permalink
[lldb] reject .debug_arange sections with nonzero segment size
Browse files Browse the repository at this point in the history
If a producer emits a nonzero segment size, `lldb` will silently read
incorrect values and crash, or do something worse later as the tuple
size is expected to be 2, rather than 3.

Neither LLVM, nor GCC produce segmented aranges, but this dangerous case
should still be checked and handled.

Reviewed by: clayborg, labath
Differential Revision: https://reviews.llvm.org/D75925
Subscribers: lldb-commits
Tags: #lldb
  • Loading branch information
ldrumm committed Mar 12, 2020
1 parent f1ac5d2 commit 0fa3320
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
Expand Up @@ -63,7 +63,8 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data,
// 1 - the version looks good
// 2 - the address byte size looks plausible
// 3 - the length seems to make sense
// size looks plausible
// 4 - size looks plausible
// 5 - the arange tuples do not contain a segment field
if (m_header.version < 2 || m_header.version > 5)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Invalid arange header version");
Expand All @@ -81,6 +82,10 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data,
return llvm::make_error<llvm::object::GenericBinaryError>(
"Invalid arange header length");

if (m_header.seg_size)
return llvm::make_error<llvm::object::GenericBinaryError>(
"segmented arange entries are not supported");

// The first tuple following the header in each set begins at an offset
// that is a multiple of the size of a single tuple (that is, twice the
// size of an address). The header is padded, if necessary, to the
Expand Down
36 changes: 36 additions & 0 deletions lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
Expand Up @@ -18,6 +18,7 @@
#include "Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h"
#include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
Expand Down Expand Up @@ -310,3 +311,38 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevMissingTerminator) {
EXPECT_EQ("abbreviation declaration attribute list not terminated with a "
"null entry", llvm::toString(std::move(error)));
}

TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) {
// This `.debug_aranges` table header is a valid 32bit big-endian section
// according to the DWARFv5 spec:6.2.1, but contains segment selectors which
// are not supported by lldb, and should be gracefully rejected
const unsigned char binary_data[] = {
0, 0, 0, 41, // unit_length (length field not including this field itself)
0, 2, // DWARF version number (half)
0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes
// of this test
4, // address size
1, // segment size
// alignment for the first tuple which "begins at an offset that is a
// multiple of the size of a single tuple". Tuples are nine bytes in this
// example.
0, 0, 0, 0, 0, 0,
// BEGIN TUPLES
1, 0, 0, 0, 4, 0, 0, 0,
1, // a 1byte object starting at address 4 in segment 1
0, 0, 0, 0, 4, 0, 0, 0,
1, // a 1byte object starting at address 4 in segment 0
// END TUPLES
0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator
};
DWARFDataExtractor data;
data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
lldb::ByteOrder::eByteOrderBig);
DWARFDebugArangeSet debug_aranges;
offset_t off = 0;
llvm::Error error = debug_aranges.extract(data, &off);
EXPECT_TRUE(bool(error));
EXPECT_EQ("segmented arange entries are not supported",
llvm::toString(std::move(error)));
EXPECT_EQ(off, 12); // Parser should read no further than the segment size
}

0 comments on commit 0fa3320

Please sign in to comment.