Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Crash when applying va_arg to VLA type #47268

Open Quuxplusone opened 3 years ago

Quuxplusone commented 3 years ago
Bugzilla Link PR48299
Status CONFIRMED
Importance P normal
Reported by Pascal Cuoq (cuoq@trust-in-soft.com)
Reported on 2020-11-25 07:06:23 -0800
Last modified on 2020-12-09 11:36:30 -0800
Version 11.0
Hardware PC All
CC blitzrakete@gmail.com, dgregor@apple.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, miod@online.fr, nigelp@xmos.com, richard-llvm@metafoo.co.uk
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
(C program courtesy of Miod Vallat)

Clang 11 crashes when va_arg is applied to a VLA type, as in the example
(Compiler Explorer link: https://gcc.godbolt.org/z/zhcTsn ):

#include <stdarg.h>

int sum(int n, ...)
{
    va_list ap;
    va_start(ap, n);
    int *input = va_arg(ap, int[n]);
    int rc = 0;
    for (int i = 0; i < n; i++)
        rc += input[i];
    return rc;
}

Result:

PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash
backtrace, preprocessed source, and associated run script.
Stack dump:
0.  Program arguments: /opt/compiler-explorer/clang-11.0.0/bin/clang -g -o
./output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-10.2.0 -fcolor-
diagnostics -fno-crash-diagnostics <source>
1.  <eof> parser at end of file
2.  <source>:3:5: LLVM IR generation of declaration 'sum'
3.  <source>:3:5: Generating code for declaration 'sum'
 #0 0x000055648b04d47a llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2cab47a)
 #1 0x000055648b04b224 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2ca9224)
 #2 0x000055648b04b495 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2ca9495)
 #3 0x000055648afbfcc0 CrashRecoverySignalHandler(int) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2c1dcc0)
 #4 0x00007fe7a196e3c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
 #5 0x000055648b58c784 clang::CodeGen::CodeGenFunction::EmitAggregateCopy(clang::CodeGen::LValue, clang::CodeGen::LValue, clang::QualType, clang::CodeGen::AggValueSlot::Overlap_t, bool) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31ea784)
 #6 0x000055648b58ca7a (anonymous namespace)::AggExprEmitter::EmitCopy(clang::QualType, clang::CodeGen::AggValueSlot const&, clang::CodeGen::AggValueSlot const&) (.isra.459) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31eaa7a)
 #7 0x000055648b58cbee (anonymous namespace)::AggExprEmitter::EmitFinalDestCopy(clang::QualType, clang::CodeGen::LValue const&, (anonymous namespace)::AggExprEmitter::ExprValueKind) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31eabee)
 #8 0x000055648b58e5b7 clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::AggExprEmitter, void>::Visit(clang::Stmt*) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31ec5b7)
 #9 0x000055648b58fce5 clang::CodeGen::CodeGenFunction::EmitAggExpr(clang::Expr const*, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31edce5)
#10 0x000055648b590ddb
clang::CodeGen::CodeGenFunction::EmitAggExprToLValue(clang::Expr const*)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31eeddb)
#11 0x000055648b56f66d
clang::CodeGen::CodeGenFunction::EmitVAArgExprLValue(clang::VAArgExpr const*)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31cd66d)
#12 0x000055648b57f5ce clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr
const*) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31dd5ce)
#13 0x000055648b58158e
clang::CodeGen::CodeGenFunction::EmitArrayToPointerDecay(clang::Expr const*,
clang::CodeGen::LValueBaseInfo*, clang::CodeGen::TBAAAccessInfo*)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31df58e)
#14 0x000055648b5bce27 (anonymous
namespace)::ScalarExprEmitter::VisitCastExpr(clang::CastExpr*) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x321ae27)
#15 0x000055648b5b5dbc (anonymous
namespace)::ScalarExprEmitter::Visit(clang::Expr*) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3213dbc)
#16 0x000055648b5b7873
clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x3215873)
#17 0x000055648b54eedf
clang::CodeGen::CodeGenFunction::EmitScalarInit(clang::Expr const*,
clang::ValueDecl const*, clang::CodeGen::LValue, bool) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x31acedf)
#18 0x000055648b54f89e
clang::CodeGen::CodeGenFunction::EmitExprAsInit(clang::Expr const*,
clang::ValueDecl const*, clang::CodeGen::LValue, bool) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x31ad89e)
#19 0x000055648b55736e
clang::CodeGen::CodeGenFunction::EmitAutoVarInit(clang::CodeGen::CodeGenFunction::AutoVarEmission
const&) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31b536e)
#20 0x000055648b558425
clang::CodeGen::CodeGenFunction::EmitAutoVarDecl(clang::VarDecl const&)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31b6425)
#21 0x000055648b558675 clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl
const&) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x31b6675)
#22 0x000055648b30b597
clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2f69597)
#23 0x000055648b318835
clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2f76835)
#24 0x000055648b31484c clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt
const*, llvm::ArrayRef<clang::Attr const*>) (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0x2f7284c)
#25 0x000055648b314f0c
clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt
const&, bool, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0x2f72f0c)
#26 0x000055648b35da71
clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2fbba71)
#27 0x000055648b36722e
clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl,
llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x2fc522e)
#28 0x000055648b3a6fda
clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl,
llvm::GlobalValue*) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x3004fda)
#29 0x000055648b3a4f15
clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl,
llvm::GlobalValue*) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0x3002f15)
#30 0x000055648b3a5623
clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3003623)
#31 0x000055648b3aa8c1
clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) (.part.4907)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x30088c1)
#32 0x000055648be15341 (anonymous
namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x3a73341)
#33 0x000055648be08276
clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3a66276)
#34 0x000055648cb84d04 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x47e2d04)
#35 0x000055648b839479 clang::FrontendAction::Execute() (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3497479)
#36 0x000055648b7f2f9b
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3450f9b)
#37 0x000055648b8ffb2b
clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x355db2b)
#38 0x000055648922814c cc1_main(llvm::ArrayRef<char const*>, char const*,
void*) (/opt/compiler-explorer/clang-11.0.0/bin/clang+0xe8614c)
#39 0x0000556489224c4d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0xe82c4d)
#40 0x000055648b6cac45 void llvm::function_ref<void
()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>
>, std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >*, bool*) const::'lambda'()>(long) (/opt/compiler-
explorer/clang-11.0.0/bin/clang+0x3328c45)
#41 0x000055648afbfda3
llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x2c1dda3)
#42 0x000055648b6cb720
clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>
>, std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >*, bool*) const (.part.148) (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0x3329720)
#43 0x000055648b6a58f5
clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&,
clang::driver::Command const*&) const (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0x33038f5)
#44 0x000055648b6a633f
clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&,
llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) const
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x330433f)
#45 0x000055648b6aeed5
clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&,
llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&)
(/opt/compiler-explorer/clang-11.0.0/bin/clang+0x330ced5)
#46 0x0000556489164dc1 main (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0xdc2dc1)
#47 0x00007fe7a141f0b3 __libc_start_main (/lib/x86_64-linux-
gnu/libc.so.6+0x270b3)
#48 0x00005564892247ca _start (/opt/compiler-explorer/clang-
11.0.0/bin/clang+0xe827ca)
clang-11: error: clang frontend command failed due to signal (use -v to see
invocation)
Compiler returned: 254
Quuxplusone commented 3 years ago

_Bug 48300 has been marked as a duplicate of this bug._

Quuxplusone commented 3 years ago

Use of any array type as the type in va_arg always results in undefined behavior (when evaluated) because the corresponding argument cannot possibly have a compatible type. So we should warn on this by default.

It doesn't really matter what code we generate given the UB, but we obviously shouldn't crash. Perhaps the most friendly thing would be to perform the usual function parameter decay on the argument (replacing "array of T" or function type T with "pointer to T").

Quuxplusone commented 3 years ago

Note that clangs' test/CodeGen/xcore-abi.c uses such an incorrect construct, but not variable-length (grep for v6), so it would be nice to adapt this test to stop doing nonsensical as well.