Author: 天音あめ Date: 2025-01-07T07:49:43-05:00 New Revision: ca5fd06366448c94e1da085984e9e69f8d6398c3
URL: https://github.com/llvm/llvm-project/commit/ca5fd06366448c94e1da085984e9e69f8d6398c3 DIFF: https://github.com/llvm/llvm-project/commit/ca5fd06366448c94e1da085984e9e69f8d6398c3.diff LOG: [clang] Fix crashes when passing VLA to va_arg (#119563) Closes #119360. This bug occurs when passing a VLA to `va_arg`. Since the return value is inferred to be an array, it triggers `ScalarExprEmitter::VisitCastExpr`, which converts it to a pointer and subsequently calls `CodeGenFunction::EmitAggExpr`. At this point, because the inferred type is an `AggExpr` instead of a `ScalarExpr`, `ScalarExprEmitter::VisitVAArgExpr` is not invoked, and as a result, `CodeGenFunction::EmitVariablyModifiedType` is also not called, leading to the size of the VLA not being retrieved. The solution is to move the call to `CodeGenFunction::EmitVariablyModifiedType` into `CodeGenFunction::EmitVAArg`, ensuring that the size of the VLA is correctly obtained regardless of whether the expression is an `AggExpr` or a `ScalarExpr`. Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/lib/Sema/SemaExpr.cpp clang/test/CodeGen/xcore-abi.c clang/test/Sema/varargs.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8a48a9e3e1f693..93915e5db7d131 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -704,6 +704,16 @@ Improvements to Clang's diagnostics return ptr + index < ptr; // warning } +- Clang now emits a ``-Wvarargs`` diagnostic when the second argument + to ``va_arg`` is of array type, which is an undefined behavior (#GH119360). + + .. code-block:: c++ + + void test() { + va_list va; + va_arg(va, int[10]); // warning + } + - Fix -Wdangling false positives on conditional operators (#120206). - Fixed a bug where Clang hung on an unsupported optional scope specifier ``::`` when parsing @@ -754,6 +764,7 @@ Bug Fixes in This Version the unsupported type instead of the ``register`` keyword (#GH109776). - Fixed a crash when emit ctor for global variant with flexible array init (#GH113187). - Fixed a crash when GNU statement expression contains invalid statement (#GH113468). +- Fixed a crash when passing the variable length array type to ``va_arg`` (#GH119360). - Fixed a failed assertion when using ``__attribute__((noderef))`` on an ``_Atomic``-qualified type (#GH116124). - No longer return ``false`` for ``noexcept`` expressions involving a diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 03fb7ca9bc3c3b..1a5541591a1608 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10512,6 +10512,10 @@ def warn_second_parameter_to_va_arg_ownership_qualified : Warning< def warn_second_parameter_to_va_arg_never_compatible : Warning< "second argument to 'va_arg' is of promotable type %0; this va_arg has " "undefined behavior because arguments will be promoted to %1">, InGroup<Varargs>; +def warn_second_parameter_to_va_arg_array : Warning< + "second argument to 'va_arg' is of array type %0; " + "this va_arg has undefined behavior because arguments " + "will never be compatible with array type">, InGroup<Varargs>; def warn_return_missing_expr : Warning< "non-void %select{function|method}1 %0 should return a value">, DefaultError, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 89e2eace9120bf..7b0ef4be986193 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -6090,6 +6090,8 @@ RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr, VAListAddr = VE->isMicrosoftABI() ? EmitMSVAListRef(VE->getSubExpr()) : EmitVAListRef(VE->getSubExpr()); QualType Ty = VE->getType(); + if (Ty->isVariablyModifiedType()) + EmitVariablyModifiedType(Ty); if (VE->isMicrosoftABI()) return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot); return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 4b71bd730ce12c..b282d4e0b32f05 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -5448,11 +5448,6 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) { } Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { - QualType Ty = VE->getType(); - - if (Ty->isVariablyModifiedType()) - CGF.EmitVariablyModifiedType(Ty); - Address ArgValue = Address::invalid(); RValue ArgPtr = CGF.EmitVAArg(VE, ArgValue); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 562c98c6babe04..ae40895980d90a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16592,6 +16592,13 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, << TInfo->getTypeLoc().getSourceRange(); } + if (TInfo->getType()->isArrayType()) { + DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E, + PDiag(diag::warn_second_parameter_to_va_arg_array) + << TInfo->getType() + << TInfo->getTypeLoc().getSourceRange()); + } + // Check for va_arg where arguments of the given type will be promoted // (i.e. this va_arg is guaranteed to have undefined behavior). QualType PromoteType; diff --git a/clang/test/CodeGen/xcore-abi.c b/clang/test/CodeGen/xcore-abi.c index bb8d2fec46bdb2..40e2f418f73047 100644 --- a/clang/test/CodeGen/xcore-abi.c +++ b/clang/test/CodeGen/xcore-abi.c @@ -76,7 +76,8 @@ void testva (int n, ...) { // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[V5]], ptr align 4 [[P]], i32 20, i1 false) // CHECK: call void @f(ptr noundef [[V5]]) - int* v6 = va_arg (ap, int[4]); // an unusual aggregate type + // an unusual aggregate type + int* v6 = va_arg (ap, int[4]); // expected-warning{{second argument to 'va_arg' is of array type 'int[4]'}} f(v6); // CHECK: [[I:%[a-z0-9]+]] = load ptr, ptr [[AP]] // CHECK: [[P:%[a-z0-9]+]] = load ptr, ptr [[I]] diff --git a/clang/test/Sema/varargs.c b/clang/test/Sema/varargs.c index 2cb7270f604a0f..bec41dda65d571 100644 --- a/clang/test/Sema/varargs.c +++ b/clang/test/Sema/varargs.c @@ -75,6 +75,11 @@ void f9(__builtin_va_list args) (void)__builtin_va_arg(args, enum E); // Don't warn here in C (void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}} (void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}} + // Don't crash on some undefined behaviors. + int n; + (void)__builtin_va_arg(args, int[10]); // expected-warning{{second argument to 'va_arg' is of array type 'int[10]'}} + (void)__builtin_va_arg(args, int[++n]); // expected-warning{{second argument to 'va_arg' is of array type 'int[++n]'}} + (void)__builtin_va_arg(args, int[n][n]); // expected-warning{{second argument to 'va_arg' is of array type 'int[n][n]'}} } void f10(int a, ...) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits