This is an archive of the discontinued LLVM Phabricator instance.

[Support] Fix UB in BumpPtrAllocator when first allocation is zero.
ClosedPublic

Authored by sammccall on May 5 2022, 1:54 PM.

Details

Summary

BumpPtrAllocator::Allocate() is marked attribute((returns_nonnull)) when the
compiler supports it, which makes it UB to return null.

When there have been no allocations yet, the current slab is [nullptr, nullptr).
A zero-sized allocation fits in this range, and so Allocate(0, 1) returns null.

There's no explicit docs whether Allocate(0) is valid. I think we have to assume
that it is:

  • the implementation tries to support it (e.g. >= tests instead of >)
  • malloc(0) is allowed
  • requiring each callsite to do a check is bug-prone
  • I found real LLVM code that makes zero-sized allocations

Diff Detail

Event Timeline

sammccall created this revision.May 5 2022, 1:54 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 5 2022, 1:55 PM
sammccall requested review of this revision.May 5 2022, 1:55 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 5 2022, 1:55 PM

Here's an example of an innocuous-looking Allocate() that can be zero-sized: https://github.com/llvm/llvm-project/blob/16dcbb53dc7968a3752661aac731172ebe0faf64/clang-tools-extra/pseudo/lib/Forest.cpp#L130

Found this by running a fuzzer on clang-pseudo, in an environment that instruments returns_nonnull functions (probably it's UBSan)

hokein accepted this revision.May 5 2022, 10:16 PM
hokein added inline comments.
llvm/include/llvm/Support/Allocator.h
142–145

mention this specific behavior of Allocate(0) in the doc: Allocate(0) returns a non-NULL zero-sized pointer (Dereferencing this pointer is UB).

This revision is now accepted and ready to land.May 5 2022, 10:16 PM
This revision was landed with ongoing or failed builds.May 5 2022, 11:57 PM
This revision was automatically updated to reflect the committed changes.
sammccall marked an inline comment as done.