This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Do not crash on large output.
AbandonedPublic

Authored by grimar on Oct 5 2016, 7:22 AM.

Details

Summary

I found at least 2 possible situations when we may crash on large outputs:

Imagine we have large section sizes. It is simulated in a testcase by providing alignment of 0xFFFFFFFF for 32 bit target.
Then overflow may happen during assigning offsets.

Diff Detail

Event Timeline

grimar updated this revision to Diff 73644.Oct 5 2016, 7:22 AM
grimar retitled this revision from to [ELF] - Do not crash on large output..
grimar updated this object.
grimar added reviewers: ruiu, rafael, davide.
grimar updated this object.
grimar added subscribers: llvm-commits, grimar, evgeny777.
ruiu added inline comments.Oct 5 2016, 10:33 AM
ELF/Writer.cpp
1388–1389

You should consider the following four cases.

Host / Target
32/32 - This check will never fail and silently create broken file.
32/64 - This check will never fail but if you attempt to create a file larger than 4GB, the linker will crash at some point because we are using MMAP IO and the result won't fit in the memory space.
64/32 - This check can catch errors.
64/64 - This check will never fail and silently create broken files.

As you can see, it results in pretty inconsistent behavior.

If you really want to do something about it, please do this.

  • Change FileSize's type to uint64_t
  • and verify that FileSize < SIZE_MAX && FileSize < sizeof(uintX_t)*8.
grimar added inline comments.Oct 6 2016, 2:06 AM
ELF/Writer.cpp
1388–1389

Host / Target
32/32 - This check will never fail and silently create broken file.

Will never fail, but will never create broken file also I think. Unless you mean that overflow of FileSize can happen earlier ? That true and that is what I am trying to diagnose in setOffset(). Changing FileSize type to uint64_t probably can help here, but unfortunately not for 64/64 case below.

32/64 - This check will never fail but if you attempt to create a file larger than 4GB, the linker will crash at some point because we are using MMAP IO and the result won't fit in the memory space.

Agree.

64/32 - This check can catch errors.

Ok.

64/64 - This check will never fail and silently create broken files.

The same as 32/32 I think, but with one more detail.
Do I correctrly understand your idea that you want remove code from setOffset() and just do these 2 suggested changes ? If so I can imaging easy testcase that can break it: just x64 object with section alignment of 0xFFFFFFFFFFFFFFFF (similar to what I have for i386 now) will cause overflow in setOffset() and suggested check will not work :(

So do you think we should just ignore possible fail of 64/64 case and just stop on your suggested change ?

grimar added a comment.Oct 6 2016, 9:39 AM

I`ll try to update this tomorrow. Found that VA also may overflow in next assignAddresses():

template <class ELFT> void Writer<ELFT>::assignAddresses() {
  uintX_t VA = Config->ImageBase + getHeaderSize<ELFT>();
...

And VA affects on how we do calculate offsets.

rafael added inline comments.Oct 6 2016, 10:25 AM
ELF/Writer.cpp
1233

I wonder how many cases there can be where overflow and if there is a general solution.

How was this crashing before?

1388

Maybe move this to another patch?

test/ELF/invalid/too-large-output-i386.s
4

Can you create this with yaml2obj?

grimar added inline comments.Oct 6 2016, 1:24 PM
test/ELF/invalid/too-large-output-i386.s
4

Nope.
Actually I can, but result binary will be too large.

section-alignment.test creates file with big alignment:

Sections:
  - Name:            .text
    Type:            SHT_PROGBITS
    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
    AddressAlign:    0x1000000000000001
    Content:         "00000000"

But that works fine only because AddressAlign is casted to unsigned inside yaml2obj and truncated to 0 finally. So produced binary is little.
But 0xFFFFFFFF value will produce huge binary, what probably not good for testcase.

I noticed this behavior today, not sure how much it is correct.

grimar added inline comments.Oct 6 2016, 2:02 PM
ELF/Writer.cpp
1233

Yes, that is a problem, solution is not general :( Crash was because of overflow of Off that is used to calculate FileSize.
So file created was little and it then crashes in writeTo during writing output sections.
We do not check end of buffer there. Probably it can be a that "general solution". I`ll try to do domething tomorrow with that.

grimar updated this revision to Diff 73904.Oct 7 2016, 3:52 AM
grimar updated this object.
  • Addressed review comments.
grimar updated this revision to Diff 73908.Oct 7 2016, 4:11 AM
  • Restored testcase missing in latest diff.
  • Improved error diagnostic messages.
ruiu added inline comments.Oct 7 2016, 2:18 PM
ELF/Writer.cpp
1165

This is I think just too much. We shouldn't introduce this integer-ish class just to check for overflow.

grimar added inline comments.Oct 11 2016, 4:32 AM
ELF/Writer.cpp
1165

Posted different approach: D25467

grimar abandoned this revision.Dec 2 2016, 11:47 PM

Depricated.