diff options
author | 天音あめ <i@amane-a.me> | 2025-01-07 20:49:43 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-07 07:49:43 -0500 |
commit | ca5fd06366448c94e1da085984e9e69f8d6398c3 (patch) | |
tree | 6e03090a932ae91b90d509b4aaea0a99fe2f4523 /clang/lib | |
parent | a5e129ccdedf5c269a8e0fcad5e21381a7f0342c (diff) | |
download | llvm-ca5fd06366448c94e1da085984e9e69f8d6398c3.zip llvm-ca5fd06366448c94e1da085984e9e69f8d6398c3.tar.gz llvm-ca5fd06366448c94e1da085984e9e69f8d6398c3.tar.bz2 |
[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`.
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 |
3 files changed, 9 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 89e2eac..7b0ef4b 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 4b71bd7..b282d4e 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 562c98c..ae40895 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; |