Skip to content

Commit ca5fd06

Browse files
authored
[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`.
1 parent a5e129c commit ca5fd06

File tree

7 files changed

+31
-6
lines changed

7 files changed

+31
-6
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,16 @@ Improvements to Clang's diagnostics
704704
return ptr + index < ptr; // warning
705705
}
706706
707+
- Clang now emits a ``-Wvarargs`` diagnostic when the second argument
708+
to ``va_arg`` is of array type, which is an undefined behavior (#GH119360).
709+
710+
.. code-block:: c++
711+
712+
void test() {
713+
va_list va;
714+
va_arg(va, int[10]); // warning
715+
}
716+
707717
- Fix -Wdangling false positives on conditional operators (#120206).
708718

709719
- Fixed a bug where Clang hung on an unsupported optional scope specifier ``::`` when parsing
@@ -754,6 +764,7 @@ Bug Fixes in This Version
754764
the unsupported type instead of the ``register`` keyword (#GH109776).
755765
- Fixed a crash when emit ctor for global variant with flexible array init (#GH113187).
756766
- Fixed a crash when GNU statement expression contains invalid statement (#GH113468).
767+
- Fixed a crash when passing the variable length array type to ``va_arg`` (#GH119360).
757768
- Fixed a failed assertion when using ``__attribute__((noderef))`` on an
758769
``_Atomic``-qualified type (#GH116124).
759770
- No longer return ``false`` for ``noexcept`` expressions involving a

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10512,6 +10512,10 @@ def warn_second_parameter_to_va_arg_ownership_qualified : Warning<
1051210512
def warn_second_parameter_to_va_arg_never_compatible : Warning<
1051310513
"second argument to 'va_arg' is of promotable type %0; this va_arg has "
1051410514
"undefined behavior because arguments will be promoted to %1">, InGroup<Varargs>;
10515+
def warn_second_parameter_to_va_arg_array : Warning<
10516+
"second argument to 'va_arg' is of array type %0; "
10517+
"this va_arg has undefined behavior because arguments "
10518+
"will never be compatible with array type">, InGroup<Varargs>;
1051510519

1051610520
def warn_return_missing_expr : Warning<
1051710521
"non-void %select{function|method}1 %0 should return a value">, DefaultError,

clang/lib/CodeGen/CGCall.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6090,6 +6090,8 @@ RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
60906090
VAListAddr = VE->isMicrosoftABI() ? EmitMSVAListRef(VE->getSubExpr())
60916091
: EmitVAListRef(VE->getSubExpr());
60926092
QualType Ty = VE->getType();
6093+
if (Ty->isVariablyModifiedType())
6094+
EmitVariablyModifiedType(Ty);
60936095
if (VE->isMicrosoftABI())
60946096
return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot);
60956097
return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot);

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5448,11 +5448,6 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
54485448
}
54495449

54505450
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
5451-
QualType Ty = VE->getType();
5452-
5453-
if (Ty->isVariablyModifiedType())
5454-
CGF.EmitVariablyModifiedType(Ty);
5455-
54565451
Address ArgValue = Address::invalid();
54575452
RValue ArgPtr = CGF.EmitVAArg(VE, ArgValue);
54585453

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16592,6 +16592,13 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
1659216592
<< TInfo->getTypeLoc().getSourceRange();
1659316593
}
1659416594

16595+
if (TInfo->getType()->isArrayType()) {
16596+
DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E,
16597+
PDiag(diag::warn_second_parameter_to_va_arg_array)
16598+
<< TInfo->getType()
16599+
<< TInfo->getTypeLoc().getSourceRange());
16600+
}
16601+
1659516602
// Check for va_arg where arguments of the given type will be promoted
1659616603
// (i.e. this va_arg is guaranteed to have undefined behavior).
1659716604
QualType PromoteType;

clang/test/CodeGen/xcore-abi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ void testva (int n, ...) {
7676
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[V5]], ptr align 4 [[P]], i32 20, i1 false)
7777
// CHECK: call void @f(ptr noundef [[V5]])
7878

79-
int* v6 = va_arg (ap, int[4]); // an unusual aggregate type
79+
// an unusual aggregate type
80+
int* v6 = va_arg (ap, int[4]); // expected-warning{{second argument to 'va_arg' is of array type 'int[4]'}}
8081
f(v6);
8182
// CHECK: [[I:%[a-z0-9]+]] = load ptr, ptr [[AP]]
8283
// CHECK: [[P:%[a-z0-9]+]] = load ptr, ptr [[I]]

clang/test/Sema/varargs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ void f9(__builtin_va_list args)
7575
(void)__builtin_va_arg(args, enum E); // Don't warn here in C
7676
(void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}}
7777
(void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}}
78+
// Don't crash on some undefined behaviors.
79+
int n;
80+
(void)__builtin_va_arg(args, int[10]); // expected-warning{{second argument to 'va_arg' is of array type 'int[10]'}}
81+
(void)__builtin_va_arg(args, int[++n]); // expected-warning{{second argument to 'va_arg' is of array type 'int[++n]'}}
82+
(void)__builtin_va_arg(args, int[n][n]); // expected-warning{{second argument to 'va_arg' is of array type 'int[n][n]'}}
7883
}
7984

8085
void f10(int a, ...) {

0 commit comments

Comments
 (0)