Skip to content

Commit d680d2f

Browse files
jh7370memfrob
authored and
memfrob
committed
[DebugInfo] Don't error for zero-length arange entries
Although the DWARF specification states that .debug_aranges entries can't have length zero, these can occur in the wild. There's no particular reason to enforce this part of the spec, since functionally they have no impact. The patch removes the error and introduces a new warning for premature terminator entries which does not stop parsing. Fixes https://bugs.llvm.org/show_bug.cgi?id=46805. See also https://reviews.llvm.org/D71932 which originally introduced the error. Reviewed by: ikudrin, dblaikie Differential Revision: https://reviews.llvm.org/D85313
1 parent 4b7745a commit d680d2f

File tree

5 files changed

+106
-19
lines changed

5 files changed

+106
-19
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class DWARFDebugArangeSet {
6060
DWARFDebugArangeSet() { clear(); }
6161

6262
void clear();
63-
Error extract(DWARFDataExtractor data, uint64_t *offset_ptr);
63+
Error extract(DWARFDataExtractor data, uint64_t *offset_ptr,
64+
function_ref<void(Error)> WarningHandler);
6465
void dump(raw_ostream &OS) const;
6566

6667
uint64_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ void DWARFContext::dump(
502502
0);
503503
DWARFDebugArangeSet set;
504504
while (arangesData.isValidOffset(offset)) {
505-
if (Error E = set.extract(arangesData, &offset)) {
505+
if (Error E =
506+
set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
506507
RecoverableErrorHandler(std::move(E));
507508
break;
508509
}

llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ void DWARFDebugArangeSet::clear() {
3232
}
3333

3434
Error DWARFDebugArangeSet::extract(DWARFDataExtractor data,
35-
uint64_t *offset_ptr) {
35+
uint64_t *offset_ptr,
36+
function_ref<void(Error)> WarningHandler) {
3637
assert(data.isValidOffset(*offset_ptr));
3738
ArangeDescriptors.clear();
3839
Offset = *offset_ptr;
@@ -132,19 +133,20 @@ Error DWARFDebugArangeSet::extract(DWARFDataExtractor data,
132133

133134
uint64_t end_offset = Offset + full_length;
134135
while (*offset_ptr < end_offset) {
136+
uint64_t EntryOffset = *offset_ptr;
135137
arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
136138
arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
137139

138-
if (arangeDescriptor.Length == 0) {
139-
// Each set of tuples is terminated by a 0 for the address and 0
140-
// for the length.
141-
if (arangeDescriptor.Address == 0 && *offset_ptr == end_offset)
140+
// Each set of tuples is terminated by a 0 for the address and 0
141+
// for the length.
142+
if (arangeDescriptor.Length == 0 && arangeDescriptor.Address == 0) {
143+
if (*offset_ptr == end_offset)
142144
return ErrorSuccess();
143-
return createStringError(
145+
WarningHandler(createStringError(
144146
errc::invalid_argument,
145147
"address range table at offset 0x%" PRIx64
146-
" has an invalid tuple (length = 0) at offset 0x%" PRIx64,
147-
Offset, *offset_ptr - tuple_size);
148+
" has a premature terminator entry at offset 0x%" PRIx64,
149+
Offset, EntryOffset));
148150
}
149151

150152
ArangeDescriptors.push_back(arangeDescriptor);

llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ void DWARFDebugAranges::extract(
2828
DWARFDebugArangeSet Set;
2929

3030
while (DebugArangesData.isValidOffset(Offset)) {
31-
if (Error E = Set.extract(DebugArangesData, &Offset)) {
31+
if (Error E =
32+
Set.extract(DebugArangesData, &Offset, RecoverableErrorHandler)) {
3233
RecoverableErrorHandler(std::move(E));
3334
return;
3435
}

llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,23 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
10+
#include "llvm/Testing/Support/Error.h"
1011
#include "gtest/gtest.h"
1112

1213
using namespace llvm;
1314

1415
namespace {
1516

17+
struct WarningHandler {
18+
~WarningHandler() { EXPECT_THAT_ERROR(std::move(Err), Succeeded()); }
19+
20+
void operator()(Error E) { Err = joinErrors(std::move(Err), std::move(E)); }
21+
22+
Error getWarning() { return std::move(Err); }
23+
24+
Error Err = Error::success();
25+
};
26+
1627
template <size_t SecSize>
1728
void ExpectExtractError(const char (&SecDataRaw)[SecSize],
1829
const char *ErrorMessage) {
@@ -21,7 +32,8 @@ void ExpectExtractError(const char (&SecDataRaw)[SecSize],
2132
/* AddressSize = */ 4);
2233
DWARFDebugArangeSet Set;
2334
uint64_t Offset = 0;
24-
Error E = Set.extract(Extractor, &Offset);
35+
WarningHandler Warnings;
36+
Error E = Set.extract(Extractor, &Offset, Warnings);
2537
ASSERT_TRUE(E.operator bool());
2638
EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
2739
}
@@ -166,24 +178,94 @@ TEST(DWARFDebugArangeSet, UnevenLength) {
166178
"of the tuple size");
167179
}
168180

169-
TEST(DWARFDebugArangeSet, ZeroLengthEntry) {
181+
TEST(DWARFDebugArangeSet, ZeroAddressEntry) {
170182
static const char DebugArangesSecRaw[] =
171-
"\x24\x00\x00\x00" // Length
183+
"\x1c\x00\x00\x00" // Length
172184
"\x02\x00" // Version
173185
"\x00\x00\x00\x00" // Debug Info Offset
174186
"\x04" // Address Size
175187
"\x00" // Segment Selector Size
176188
"\x00\x00\x00\x00" // Padding
177189
"\x00\x00\x00\x00" // Entry1: Address
178190
"\x01\x00\x00\x00" // Length
191+
"\x00\x00\x00\x00" // Termination tuple
192+
"\x00\x00\x00\x00";
193+
DWARFDataExtractor Extractor(
194+
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
195+
/*IsLittleEndian=*/true,
196+
/*AddressSize=*/4);
197+
DWARFDebugArangeSet Set;
198+
uint64_t Offset = 0;
199+
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
200+
Succeeded());
201+
auto Range = Set.descriptors();
202+
auto Iter = Range.begin();
203+
ASSERT_EQ(std::distance(Iter, Range.end()), 1u);
204+
EXPECT_EQ(Iter->Address, 0u);
205+
EXPECT_EQ(Iter->Length, 1u);
206+
}
207+
208+
TEST(DWARFDebugArangeSet, ZeroLengthEntry) {
209+
static const char DebugArangesSecRaw[] =
210+
"\x1c\x00\x00\x00" // Length
211+
"\x02\x00" // Version
212+
"\x00\x00\x00\x00" // Debug Info Offset
213+
"\x04" // Address Size
214+
"\x00" // Segment Selector Size
215+
"\x00\x00\x00\x00" // Padding
216+
"\x01\x00\x00\x00" // Entry1: Address
217+
"\x00\x00\x00\x00" // Length
218+
"\x00\x00\x00\x00" // Termination tuple
219+
"\x00\x00\x00\x00";
220+
DWARFDataExtractor Extractor(
221+
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
222+
/*IsLittleEndian=*/true,
223+
/*AddressSize=*/4);
224+
DWARFDebugArangeSet Set;
225+
uint64_t Offset = 0;
226+
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
227+
Succeeded());
228+
auto Range = Set.descriptors();
229+
auto Iter = Range.begin();
230+
ASSERT_EQ(std::distance(Iter, Range.end()), 1u);
231+
EXPECT_EQ(Iter->Address, 1u);
232+
EXPECT_EQ(Iter->Length, 0u);
233+
}
234+
235+
TEST(DWARFDebugArangesSet, PrematureTerminator) {
236+
static const char DebugArangesSecRaw[] =
237+
"\x24\x00\x00\x00" // Length
238+
"\x02\x00" // Version
239+
"\x00\x00\x00\x00" // Debug Info Offset
240+
"\x04" // Address Size
241+
"\x00" // Segment Selector Size
242+
"\x00\x00\x00\x00" // Padding
243+
"\x00\x00\x00\x00" // Entry1: Premature
244+
"\x00\x00\x00\x00" // terminator
179245
"\x01\x00\x00\x00" // Entry2: Address
180-
"\x00\x00\x00\x00" // Length (invalid)
246+
"\x01\x00\x00\x00" // Length
181247
"\x00\x00\x00\x00" // Termination tuple
182248
"\x00\x00\x00\x00";
183-
ExpectExtractError(
184-
DebugArangesSecRaw,
185-
"address range table at offset 0x0 has an invalid tuple (length = 0) "
186-
"at offset 0x18");
249+
DWARFDataExtractor Extractor(
250+
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
251+
/*IsLittleEndian=*/true,
252+
/*AddressSize=*/4);
253+
DWARFDebugArangeSet Set;
254+
uint64_t Offset = 0;
255+
WarningHandler Warnings;
256+
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, Warnings), Succeeded());
257+
auto Range = Set.descriptors();
258+
auto Iter = Range.begin();
259+
ASSERT_EQ(std::distance(Iter, Range.end()), 2u);
260+
EXPECT_EQ(Iter->Address, 0u);
261+
EXPECT_EQ(Iter->Length, 0u);
262+
++Iter;
263+
EXPECT_EQ(Iter->Address, 1u);
264+
EXPECT_EQ(Iter->Length, 1u);
265+
EXPECT_THAT_ERROR(
266+
Warnings.getWarning(),
267+
FailedWithMessage("address range table at offset 0x0 has a premature "
268+
"terminator entry at offset 0x10"));
187269
}
188270

189271
} // end anonymous namespace

0 commit comments

Comments
 (0)