[clang] ca5fd06 - [clang] Fix crashes when passing VLA to va_arg (#119563)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 7 04:49:47 PST 2025
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, ...) {
More information about the cfe-commits
mailing list