This is an archive of the discontinued LLVM Phabricator instance.

[Bitstream] Fix UB in left-shift in ReadVBR
ClosedPublic

Authored by jkorous on Feb 8 2022, 6:15 PM.

Details

Summary

This patch aims to address: https://reviews.llvm.org/D119182

This commit from today improves the situation but doesn't fix the UB.
https://github.com/llvm/llvm-project/commit/67348c8acfc205785996f2aea21b442f4b76f2c2

I am trying to prevent the UB in a mechanical fashion. Possibly there's a better solution and the error messages can very likely be worded better. I am not familiar with the code - open to suggestions!

When running the test against ubsanitized build (-fsanitize=integer) it still triggers couple issues but not the one that lead to the test getting disabled in https://reviews.llvm.org/D119182

> bin/llvm-lit -v ../repo.git/llvm/test/Bitcode/invalid-no-ubsan.test
/tmp/llvm-project/include/llvm/Support/DJB.h:23:12: runtime error: left shift of 4042302735 by 5 places cannot be represented in type 'uint32_t' (aka 'unsigned int')
/tmp/llvm-project/include/llvm/Support/DJB.h:23:18: runtime error: unsigned integer overflow: 504668640 + 4042302735 cannot be represented in type 'unsigned int'
/tmp/llvm-project/include/llvm/Option/ArgList.h:135:42: runtime error: negation of 1 cannot be represented in type 'unsigned int'
/tmp/llvm-project/include/llvm/ADT/DenseMap.h:807:86: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
/tmp/llvm-project/lib/Option/ArgList.cpp:68:18: runtime error: negation of 1 cannot be represented in type 'unsigned int'
/tmp/llvm-project/lib/Support/StringRef.cpp:299:45: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned long'
/tmp/llvm-project/include/llvm/ADT/StringRef.h:864:74: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'unsigned long'

Diff Detail

Event Timeline

jkorous requested review of this revision.Feb 8 2022, 6:15 PM
jkorous created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptFeb 8 2022, 6:15 PM

Thanks for following up on D119182!

llvm/include/llvm/Bitstream/BitstreamReader.h
230

nit: Consider improving the error message for this test by adding some context (i.e, it is the size which has invalid numbits) to the error, at the caller - here.

237

nit: Provide the bad value of NumBits in the error message?

246–247

Why not simpler condition?

if (NextBit >= 32) { ... }

And move later in the loop for a little less overhead (the first iteration will always be NextBit==0).

llvm/test/Bitcode/invalid-no-ubsan.test
7 ↗(On Diff #407021)

With these tests fixed, there is no reason for a separate file (separate file is so UNSUPPORTED: ubsan only applies to these, and not the rest).

These tests should be moved back to invalid.test.

nikic added a comment.Feb 9 2022, 12:27 AM

Can you please rebase this on main and clarify which UB this addresses that is not covered by either https://github.com/llvm/llvm-project/commit/67348c8acfc205785996f2aea21b442f4b76f2c2 or https://github.com/llvm/llvm-project/commit/bf17cb294af422512b522575f3f74ab7964bf911? Please note that -fsanitize=integer includes a number of checks that are not actually undefined behavior. Some of the warnings quoted in the summary definitely cannot be fixed (e.g. DJB overflow is expected).

I believe a correct NumBits value is supposed to be a caller invariant (though this should probably be at least an assertion), which previously was not enforced in some cases due to an incorrect MaxChunkSize value.

jkorous updated this revision to Diff 408112.Feb 11 2022, 5:08 PM

rebased + improved error messages

jkorous updated this revision to Diff 408122.Feb 11 2022, 5:20 PM
jkorous updated this revision to Diff 408123.
jkorous marked an inline comment as done.
jkorous marked an inline comment as done.

clang-format

jkorous marked an inline comment as done.Feb 11 2022, 5:22 PM
jkorous added inline comments.
llvm/include/llvm/Bitstream/BitstreamReader.h
246–247

You're absolutely right.

jkorous marked an inline comment as done.Feb 11 2022, 5:33 PM

@nikic Sorry, my statement was incorrect. What I meant is that the method doesn't prevent UB via assert or runtime check of NumBits value.
I'm happy to go with assert if that'd be a better fit.

browneee accepted this revision.Feb 11 2022, 5:43 PM

LGTM. Improves error message, and the new local variables are also an improvement.

This revision is now accepted and ready to land.Feb 11 2022, 5:43 PM

@nikic Sorry, my statement was incorrect. What I meant is that the method doesn't prevent UB via assert or runtime check of NumBits value.
I'm happy to go with assert if that'd be a better fit.

Yes, I think an assert would be a better fit here semantically.

jkorous updated this revision to Diff 408681.Feb 14 2022, 6:24 PM

switched to assert
added the assert also to ReadVBR64

I noticed ReadVBR64 method below does the same arithmetics and keeping the implementation in sync seems like a no-brainer.

Ultimately the error message propagation is unrelated to the assert but it does seem like a minor improvement - I'll just land it as a separate commit.

I plan to land this tomorrow unless there's some additional feedback.

Thank you both for the opportunity to learn a bit about this part of llvm-project! :)

This revision was landed with ongoing or failed builds.Feb 15 2022, 5:12 PM
This revision was automatically updated to reflect the committed changes.