https://github.com/keepyixiao created 
https://github.com/llvm/llvm-project/pull/230979

Out-of-range type arguments to __builtin_object_size and 
__builtin_dynamic_object_size could trigger assertions during constant 
evaluation.

Replace the assertions in both constant evaluators with range diagnostics.

Add regression tests for negative and too-large type arguments, covering both 
builtins and both constant evaluators.

Assisted-by: AI

Fixes https://github.com/llvm/llvm-project/issues/225041

>From e5c90d74f61df50d51d624dba52bf8a864e3df22 Mon Sep 17 00:00:00 2001
From: nudt_yixiao <[email protected]>
Date: Sun, 11 Oct 2026 20:40:45 +0800
Subject: [PATCH] [Clang] Diagnose invalid object size kinds during constant
 evaluation

Out-of-range type arguments to __builtin_object_size and
__builtin_dynamic_object_size could trigger assertions during constant
evaluation.

Replace the assertions in both constant evaluators with range diagnostics.

Add regression tests for negative and too-large type arguments, covering both
builtins and both constant evaluators.
---
 clang/docs/ReleaseNotes.md                     |  3 +++
 .../include/clang/Basic/DiagnosticASTKinds.td  |  2 ++
 clang/lib/AST/ByteCode/InterpBuiltin.cpp       | 18 ++++++++++++------
 clang/lib/AST/ExprConstant.cpp                 | 11 +++++++----
 clang/test/Sema/builtin-object-size.c          |  7 +++++++
 5 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 77a1e73bc8af6..87744e6d9b4b5 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -693,6 +693,9 @@ features cannot lower the translation-unit ABI level;
   or `__builtin_is_aligned` with pointers without an underlying object. Null 
pointers
   are handled as aligned values, while other base-less pointers are rejected 
during constant
   evaluation.
+- Fixed an assertion failure when `__builtin_object_size` or
+  `__builtin_dynamic_object_size` is called with an out-of-range type argument
+  during constant evaluation. (#GH225041)
 
 #### Bug Fixes to Attribute Support
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 0aca1f75428f8..dedb1ff2f503b 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -29,6 +29,8 @@ def note_constexpr_invalid_downcast : Note<
   "cannot cast object of dynamic type %0 to type %1">;
 def note_constexpr_overflow : Note<
   "value %0 is outside the range of representable values of type %1">;
+def note_constexpr_builtin_arg_out_of_range : Note<
+  "argument value %0 is outside the valid range [%1, %2]">;
 def note_constexpr_offsetof_overflow : Note<
   "overflow in offsetof">;
 def note_constexpr_negative_shift : Note<"negative shift count %0">;
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 4a5c691d390a7..7020c73f4bb98 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2449,13 +2449,18 @@ static bool interp__builtin_object_size(InterpState &S, 
CodePtr OpPC,
   // clear, objects are whole variables. If it is set, a closest surrounding
   // subobject is considered the object a pointer points to. The second bit
   // determines if maximum or minimum of remaining bytes is computed.
-  uint64_t Kind;
-  if (!popToUInt64(S, Call->getArg(1), Kind))
+  APSInt Kind;
+  if (!popToAPSInt(S, Call->getArg(1), Kind))
     return false;
-  assert(Kind <= 3 && "unexpected kind");
+  if (Kind < 0 || Kind > 3) {
+    S.FFDiag(Call->getArg(1), diag::note_constexpr_builtin_arg_out_of_range)
+        << Kind << 0 << 3;
+    return false;
+  }
+  unsigned KindValue = Kind.getZExtValue();
   Pointer Ptr = S.Stk.pop<Pointer>();
 
-  if (auto Result = evaluateBuiltinObjectSize(ASTCtx, Kind, Ptr,
+  if (auto Result = evaluateBuiltinObjectSize(ASTCtx, KindValue, Ptr,
                                               Call->getArg(0), IsDynamic)) {
     pushInteger(S, *Result, Call->getType());
     return true;
@@ -2464,7 +2469,7 @@ static bool interp__builtin_object_size(InterpState &S, 
CodePtr OpPC,
   if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
     // "If there are any side effects in them, it returns (size_t) -1
     // for type 0 or 1 and (size_t) 0 for type 2 or 3."
-    pushInteger(S, Kind <= 1 ? (size_t)-1 : (size_t)0, Call->getType());
+    pushInteger(S, KindValue <= 1 ? (size_t)-1 : (size_t)0, Call->getType());
     return true;
   }
 
@@ -2476,7 +2481,8 @@ static bool interp__builtin_object_size(InterpState &S, 
CodePtr OpPC,
     return Invalid(S, OpPC);
   case EvaluationMode::ConstantExpressionUnevaluated:
     // Reduce it to a constant now.
-    pushInteger(S, ((Kind & 2u) ? (size_t)0 : (size_t)-1), Call->getType());
+    pushInteger(S, ((KindValue & 2u) ? (size_t)0 : (size_t)-1),
+                Call->getType());
     return true;
   }
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8551f4c9ae279..cf450699aee99 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17176,10 +17176,13 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const 
CallExpr *E,
 
   case Builtin::BI__builtin_dynamic_object_size:
   case Builtin::BI__builtin_object_size: {
-    // The type was checked when we built the expression.
-    unsigned Type =
-        E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
-    assert(Type <= 3 && "unexpected type");
+    APSInt TypeValue = E->getArg(1)->EvaluateKnownConstInt(Info.Ctx);
+    if (TypeValue < 0 || TypeValue > 3) {
+      Info.FFDiag(E->getArg(1), diag::note_constexpr_builtin_arg_out_of_range)
+          << TypeValue << 0 << 3;
+      return false;
+    }
+    unsigned Type = TypeValue.getZExtValue();
 
     bool IsDynamic = BuiltinOp == Builtin::BI__builtin_dynamic_object_size;
     if (std::optional<uint64_t> Size =
diff --git a/clang/test/Sema/builtin-object-size.c 
b/clang/test/Sema/builtin-object-size.c
index 8d48d3f569d91..45d9cb24df1b9 100644
--- a/clang/test/Sema/builtin-object-size.c
+++ b/clang/test/Sema/builtin-object-size.c
@@ -30,6 +30,13 @@ int f3(void) {
   return OBJECT_SIZE_BUILTIN(&a, 4); // expected-error {{argument value 4 is 
outside the valid range [0, 3]}}
 }
 
+// expected-error@+2 {{static assertion expression is not an integral constant 
expression}}
+// expected-note@+1 {{argument value -1 is outside the valid range [0, 3]}}
+_Static_assert(OBJECT_SIZE_BUILTIN((void *)0, -1), "");
+
+// expected-error@+2 {{static assertion expression is not an integral constant 
expression}}
+// expected-note@+1 {{argument value 4 is outside the valid range [0, 3]}}
+_Static_assert(OBJECT_SIZE_BUILTIN((void *)0, 4), "");
 
 // cannot call vsnprintf with va_list on x86_64
 void f4(const char *fmt, ...) {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to