llvm / llvm/llvm-project

[Clang][PowerPC] PPC min/max builtins with fewer than 4 arguments trigger Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.

Open
#217,023 2 comments 0 reactions 0 assignees View on GitHub
backend:PowerPC clang:codegen crash generated by fuzzer regression:15
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Reproducer:
A fuzzing tool generated the following test case:
https://godbolt.org/z/b4ajqabx4

```c++
void test_builtin_ppc_maxminfe(long double a, long double b, long double c, long double d) {

long double res;
res = __builtin_ppc_maxfe(a, b, c);

}
```
With Clang trunk and:

```
--target=powerpc64le-linux-gnu
```

Clang triggers:

```
clang++: /root/llvm-project/llvm/tools/clang/include/clang/AST/Expr.h:3163: const clang::Expr* clang::CallExpr::getArg(unsigned int) const: Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and dumped files.
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics --target=powerpc64le-linux-gnu
1. parser at end of file
2. :2:6: LLVM IR generation of declaration 'test_builtin_ppc_maxminfe'
3. :2:6: Generating code for declaration 'test_builtin_ppc_maxminfe'
#0 0x000000000448ebf8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448ebf8)
#1 0x000000000448baa4 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448baa4)
#2 0x000000000448c0dc llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448c0dc)
#3 0x00000000043ca9d8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#4 0x00007079df845330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#5 0x00007079df89ec0c pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x9ec0c)
#6 0x00007079df84527e raise (/lib/x86_64-linux-gnu/libc.so.6+0x4527e)
#7 0x00007079df8288ff abort (/lib/x86_64-linux-gnu/libc.so.6+0x288ff)
#8 0x00007079df82881b (/lib/x86_64-linux-gnu/libc.so.6+0x2881b)
#9 0x00007079df83b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#10 0x0000000004cc284a (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4cc284a)
#11 0x0000000004d39a6d clang::CodeGen::CodeGenFunction::EmitPPCBuiltinExpr(unsigned int, clang::CallExpr const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4d39a6d)
#12 0x0000000004e56ca5 clang::CodeGen::CodeGenFunction::EmitBuiltinExpr(clang::GlobalDecl, unsigned int, clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4e56ca5)
#13 0x0000000004981f5e clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot, llvm::CallBase**) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4981f5e)
#14 0x00000000049f134c (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) CGExprScalar.cpp:0:0
#15 0x00000000049e68a0 clang::StmtVisitorBase::Visit(clang::Stmt*) CGExprScalar.cpp:0:0
#16 0x00000000049ec34c clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x49ec34c)
#17 0x000000000495528e clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x495528e)
#18 0x000000000497df21 clang::CodeGen::CodeGenFunction::EmitBinaryOperatorLValue(clang::BinaryOperator const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x497df21)
#19 0x0000000004983597 clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4983597)
#20 0x0000000004983f07 void llvm::function_ref::callback_fn(long) CGExpr.cpp:0:0
#21 0x00000000088e0f41 clang::StackExhaustionHandler::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x88e0f41)
#22 0x000000000494804c clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*, clang::CodeGen::KnownNonNull_t) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x494804c)
#23 0x000000000497cd7e clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x497cd7e)
#24 0x0000000004b18a7b clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b18a7b)
#25 0x0000000004b20d4b clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b20d4b)
#26 0x0000000004b89846 clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b89846)
#27 0x0000000004b9f264 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4b9f264)
#28 0x0000000004c0fada clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c0fada)
#29 0x0000000004c08ec4 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c08ec4)
#30 0x0000000004c09c10 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c09c10)
#31 0x0000000004c16d21 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) (.part.0) CodeGenModule.cpp:0:0
#32 0x0000000004f95069 (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) ModuleBuilder.cpp:0:0
#33 0x0000000004f86114 clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4f86114)
#34 0x0000000006dac204 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dac204)
#35 0x0000000004f92ef8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4f92ef8)
#36 0x00000000052bd7b8 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x52bd7b8)
#37 0x000000000524baed clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x524baed)
#38 0x00000000053927ed clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x53927ed)
#39 0x0000000000dae91c cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdae91c)
#40 0x0000000000da553a ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#41 0x0000000000da56bd int llvm::function_ref&)>::callback_fn&)>(long, llvm::SmallVectorImpl&) driver.cpp:0:0
#42 0x000000000500bbc9 void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#43 0x00000000043cae14 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x43cae14)
#44 0x000000000500c735 clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0
#45 0x0000000004fc43e2 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fc43e2)
#46 0x0000000004fc8d47 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fc8d47)
#47 0x0000000004fd3415 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fd3415)
#48 0x0000000000daae1a clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdaae1a)
#49 0x0000000000cc6b4a main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xcc6b4a)
#50 0x00007079df82a1ca (/lib/x86_64-linux-gnu/libc.so.6+0x2a1ca)
#51 0x00007079df82a28b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28b)
#52 0x0000000000da4ee5 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xda4ee5)
clang++: error: clang frontend command failed due to signal (use -v to see invocation)
Compiler returned: 134
```

I traced this issue back to Clang 15.

After further investigation, I found that the following PPC builtins also trigger the same assertion when called with fewer than 4 arguments:
https://godbolt.org/z/6TvnePara

```c++
void test_maxfl(double a, double b, double c) {
__builtin_ppc_maxfl(a, b, c);
}

void test_maxfs(float a, float b, float c) {
__builtin_ppc_maxfs(a, b, c);
}

void test_minfe(long double a, long double b, long double c) {
__builtin_ppc_minfe(a, b, c);
}

void test_minfl(double a, double b, double c) {
__builtin_ppc_minfl(a, b, c);
}

void test_minfs(float a, float b, float c) {
__builtin_ppc_minfs(a, b, c);
}
```

Contributor guide

Open the contributing guide

Research direction

Start with the reproducer on Compiler Explorer using Clang trunk and --target=powerpc64le-linux-gnu, then inspect clang::CodeGen::CodeGenFunction::EmitPPCBuiltinExpr from the stack trace. Exercise the listed PPC max/min builtins with fewer than four arguments and verify compilation no longer triggers the Arg access out of range assertion.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.