This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo/DWARF] - Do not hang when CFI are truncated.
ClosedPublic

Authored by grimar on Jun 17 2020, 7:55 AM.

Details

Summary

Currently when the .eh_frame section is truncated so that
CFI instructions can't be read, it is possible to enter
an infinite loop.

It happens because CFIProgram::parse does not handle errors properly.
This patch fixes the issue.

Diff Detail

Event Timeline

grimar created this revision.Jun 17 2020, 7:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 17 2020, 7:55 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
grimar retitled this revision from [DebugInfo/DWARF] - Do not hang when the CFI is truncated. to [DebugInfo/DWARF] - Do not hang when CFI are truncated..Jun 17 2020, 7:56 AM

Convert to using cursor instead?

MaskRay added inline comments.Jun 17 2020, 1:51 PM
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
79

clang-format may prefer /*SectionIndex=*/nullptr

llvm/test/DebugInfo/X86/eh-frame-truncated-cfi.s
2 ↗(On Diff #271374)

s/are //

4 ↗(On Diff #271374)

Drop -unknown-linux. This is a generic ELF behavior not specific to Linux.

jhenderson added inline comments.Jun 18 2020, 1:29 AM
llvm/test/DebugInfo/X86/eh-frame-truncated-cfi.s
4 ↗(On Diff #271374)

You've added several new error cases, but only one new test case. You need one for each individual new error check, I think. It may be better to write the testing as unit tests. See similar work I've been doing recently for .debug_line.

grimar updated this revision to Diff 271989.Jun 19 2020, 3:30 AM
  • Use DataExtractor::Cursor.
  • Use unit tests for testing.
jhenderson added inline comments.Jun 22 2020, 1:35 AM
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
138–139

What happens if the expression itself is truncated? I'd expect this to somehow report an error that can be detected here. Same goes below.

llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
178–182

Accidental duplicate test case?

185–188

Given that this and the next several cases are identical, barring the input value, (as indeed are many) have you considered changing to using a set of parameterised test cases? No idea how much extra complexity (if any) it would add, without actually trying it, so it might not be worth it, but in principle you could have a test body for each of the different possible error messages, and a list of parameters for each test body listing the opcodes that trigger that case.

grimar updated this revision to Diff 272421.Jun 22 2020, 7:19 AM
grimar marked 5 inline comments as done.
  • Addressed review comments.
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
138–139

A simple truncation is catched by StringRef Expression = Data.getBytes(C, ExprLength);.

So you are talking about the case when both expression length and expression data are truncated and
not reported here. It is probably a subject for another review. Perhaps it should be validated
at the place where it is actually dumped, i.e. not here:

I see we have DWARFExpression::verify(DWARFUnit *U) method, which seems already used to validate expressions.
I do not know how much complete it is (I guess it should be), but it might cause DWARFExpression::Operation::print to
report "<decoding error>" already. It is possible that everything is already done there.

llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
178–182

Yes, thanks!

185–188

Having a test body for each of the different possible error messages is perhaps too much, because there are many unique messages. I've grouped the identical messages together. Does it look OK for you?

jhenderson accepted this revision.Jun 23 2020, 12:50 AM

LGTM, thanks.

llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
255

Here and below, should Op1 be RegNum (that's what it was before)?

This revision is now accepted and ready to land.Jun 23 2020, 12:50 AM
grimar marked an inline comment as done.Jun 23 2020, 1:33 AM
grimar added inline comments.
llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
255

I think no, because now CheckOp_ULEB128_Expr is a generic lamda, that knows that
an instruction checked has 3 operands of known types, but probably it shouldn't do any assumptions
about their meanings.

This revision was automatically updated to reflect the committed changes.