[llvm] [llvm] Fix __builtin_object_size interaction between Negative Offset … (PR #111827)

Harald van Dijk via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 28 09:39:23 PDT 2024


================
@@ -686,10 +686,23 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL,
 
 SizeOffsetAPInt ObjectSizeOffsetVisitor::compute(Value *V) {
   InstructionsVisited = 0;
-  return computeImpl(V);
+  OffsetSpan Span = computeImpl(V);
+
+  // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow
+  // us to overwrite it if needs be.
+  if (Span.knownAfter() && !Span.knownBefore() &&
+      Options.EvalMode == ObjectSizeOpts::Mode::ExactSizeFromOffset)
+    Span.Before = APInt::getZero(Span.After.getBitWidth());
+
+  if (!Span.bothKnown())
+    return {};
+  if (Span.Before.isNegative() || Span.After.isNegative())
+    return {};
----------------
hvdijk wrote:

That may be right at the C++ level, but I think it's wrong at the LLVM IR level. At the LLVM IR level, we may generate `getelementptr` without the `inbounds` attribute, do pointer arithmetic that takes us outside of an object, and then do more pointer arithmetic to take us back in, think the equivalent of `(array + 8) - 6`. If we do nothing special, we will return that `array + 8` is 32 bytes after the start of an object of size 16. We can then compute that `(array + 8) - 6` is 8 bytes into an object of size 16, and allows 8 bytes to be accessed. If we instead return that `array + 8` is zero bytes after the start of an object of size zero, `(array + 8) - 6` would be considered out of bounds.

It may take some effort to come up with a concrete test case demonstrating this though.

https://github.com/llvm/llvm-project/pull/111827


More information about the llvm-commits mailing list