llvm / llvm/llvm-project

[BUG] ICE in clang::Parser::ParseRHSOfBinaryExpression(clang::ActionResult<clang::Expr*, true>, clang::prec::Level)

Open
#204,763 1 comment 0 reactions 0 assignees View on GitHub
clang:frontend crash-on-invalid generated by fuzzer
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Bug Report: ICE in clang::Parser::ParseRHSOfBinaryExpression(clang::ActionResult, clang::prec::Level)

Clang crashes when compiling the following C code.

**Compiler**: clang-22 (LLVM 22.1.5, commit 5ea218a153f4d2f815b8244eab3e4b4ba5e00e6c)
**Compilation flags**: -O0
**Platform**: x86_64-linux-gnu
**Component**: frontend

This is a **frontend** crash (reproduces with `-emit-llvm -Xclang -disable-llvm-passes`).

## Reduced Test Case

> Minimized from the original fuzzer-generated input using `creduce`.

```sh
clang -O0 test.c -o /dev/null
```

```c
enum { a = b(bar) c = a + 0

```

## Crash Output

```
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:9:13: error: call to undeclared function 'offsetof'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
9 | E1 \= E0 \+ offsetfrom (int, char, c),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:2:52: note: expanded from macro 'offsetfrom'
2 | #define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:9:25: error: expected expression
9 | E1 \= E0 \+ offsetfrom (int, char, c),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:9:36: error: use of undeclared identifier 'c'
9 | E1 \= E0 \+ offsetfrom (int, char, c),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:10:35: error: use of undeclared identifier 'foo'
10 | E2 \= E1 \+ offsetfrom (struct S, foo, 8),
| ^\~\~
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:10:25: error: expected expression
10 | E2 \= E1 \+ offsetfrom (struct S, foo, 8),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:11:23: error: expected expression
11 | E3 \= E2 \+ offsetof (struct S, baz[8]),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:11:33: error: use of undeclared identifier 'baz'
11 | E3 \= E2 \+ offsetof (struct S, baz[8]),
| ^\~\~
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:12:23: error: expected expression
12 | E4 \= E3 \+ offsetof (struct S, quux),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:12:33: error: use of undeclared identifier 'quux'
12 | E4 \= E3 \+ offsetof (struct S, quux),
| ^\~\~\~
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:13:23: error: expected expression
13 | E5 \= E4 \+ offsetof (struct S, bar[5]),
| ^
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:13:33: error: use of undeclared identifier 'bar'
13 | E5 \= E4 \+ offsetof (struct S, bar[5]),
| ^\~\~
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:14:13: error: invalid application of 'sizeof' to an incomplete type 'struct S'
14 | E6 \= E5 \+ sizeof (struct S),
| ^ \~\~\~\~\~\~\~\~\~\~
/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:14:28: note: forward declaration of 'struct S'
14 | E6 \= E5 \+ sizeof (struct S),
| ^
clang-22: /root/compilers/llvm-project-release/clang/lib/Sema/SemaExpr.cpp:15890: clang::ExprResult clang::Sema::BuildBinOp(clang::Scope*, clang::SourceLocation, clang::BinaryOperatorKind, clang::Expr*, clang::Expr*, bool): Assertion \`(LHSExpr->containsErrors() || RHSExpr->containsErrors()) && "Should only occur in error-recovery path."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0\. Program arguments: /root/objects/llvm-project-release.obj/bin/clang-22 -cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-obj -dumpdir /dev/null- -disable-free -clear-ast-before-backend -main-file-name XmEJFAEsQwif_surfuzz_5.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/data -fcoverage-compilation-dir=/root/data -resource-dir /root/objects/llvm-project-release.obj/lib/clang/22 -internal-isystem /root/objects/llvm-project-release.obj/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -faddrsig -fdwarf2-cfi-asm -o /tmp/XmEJFAEsQwif_surfuzz_5-40ace2.o -x c /root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c
1\. /root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c:15:15: current parser token ','
#0 0x000056055940c2d2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/root/objects/llvm-project-release.obj/bin/clang-22+0x44f62d2)
#1 0x0000560559408caf llvm::sys::RunSignalHandlers() (/root/objects/llvm-project-release.obj/bin/clang-22+0x44f2caf)
#2 0x0000560559408dfc SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#3 0x00007fcba90de520 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007fcba9132a7c __pthread_kill_implementation ./nptl/./nptl/pthread_kill.c:44:76
#5 0x00007fcba9132a7c __pthread_kill_internal ./nptl/./nptl/pthread_kill.c:78:10
#6 0x00007fcba9132a7c pthread_kill ./nptl/./nptl/pthread_kill.c:89:10
#7 0x00007fcba90de476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
#8 0x00007fcba90c47f3 abort ./stdlib/./stdlib/abort.c:81:7
#9 0x00007fcba90c471b _nl_load_domain ./intl/./intl/loadmsgcat.c:1177:9
#10 0x00007fcba90d5e96 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000056055c1a5c38 clang::Sema::BuildBinOp(clang::Scope*, clang::SourceLocation, clang::BinaryOperatorKind, clang::Expr*, clang::Expr*, bool) (/root/objects/llvm-project-release.obj/bin/clang-22+0x728fc38)
#12 0x000056055c1a6041 clang::Sema::ActOnBinOp(clang::Scope*, clang::SourceLocation, clang::tok::TokenKind, clang::Expr*, clang::Expr*) (/root/objects/llvm-project-release.obj/bin/clang-22+0x7290041)
#13 0x000056055bcac97e clang::Parser::ParseRHSOfBinaryExpression(clang::ActionResult, clang::prec::Level) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d9697e)
#14 0x000056055bcb5372 clang::Parser::ParseConstantExpressionInExprEvalContext(clang::TypoCorrectionTypeBehavior) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d9f372)
#15 0x000056055bc69542 clang::Parser::ParseEnumBody(clang::SourceLocation, clang::Decl*, clang::SkipBodyInfo*) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d53542)
#16 0x000056055bc6ae44 clang::Parser::ParseEnumSpecifier(clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d54e44)
#17 0x000056055bc6e1ef clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*, clang::ImplicitTypenameContext) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d581ef)
#18 0x000056055bc33567 clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d1d567)
#19 0x000056055bc3400f clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d1e00f)
#20 0x000056055bc3c896 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d26896)
#21 0x000056055bc3d915 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d27915)
#22 0x000056055bc1d88a clang::ParseAST(clang::Sema&, bool, bool) (/root/objects/llvm-project-release.obj/bin/clang-22+0x6d0788a)
#23 0x000056055a095987 clang::FrontendAction::Execute() (/root/objects/llvm-project-release.obj/bin/clang-22+0x517f987)
#24 0x000056055a01d0e9 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/root/objects/llvm-project-release.obj/bin/clang-22+0x51070e9)
#25 0x000056055a19295e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/root/objects/llvm-project-release.obj/bin/clang-22+0x527c95e)
#26 0x0000560555e9d657 cc1_main(llvm::ArrayRef, char const*, void*) (/root/objects/llvm-project-release.obj/bin/clang-22+0xf87657)
#27 0x0000560555e92694 ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#28 0x0000560555e97907 clang_main(int, char**, llvm::ToolContext const&) (/root/objects/llvm-project-release.obj/bin/clang-22+0xf81907)
#29 0x0000560555d550ea main (/root/objects/llvm-project-release.obj/bin/clang-22+0xe3f0ea)
#30 0x00007fcba90c5d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#31 0x00007fcba90c5e40 call_init ./csu/../csu/libc-start.c:128:20
#32 0x00007fcba90c5e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#33 0x0000560555e91cb5 _start (/root/objects/llvm-project-release.obj/bin/clang-22+0xf7bcb5)
clang: error: unable to execute command: Aborted (core dumped)
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 22.1.5 (https://github.com/llvm/llvm-project.git 5ea218a153f4d2f815b8244eab3e4b4ba5e00e6c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /root/objects/llvm-project-release.obj/bin
Build config: \+assertions
clang: note: diagnostic msg:
********************
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/XmEJFAEsQwif_surfuzz_5-580d35.c
clang: note: diagnostic msg: /tmp/XmEJFAEsQwif_surfuzz_5-580d35.sh
clang: note: diagnostic msg:
********************
EXIT_CODE: 1
```

## Preprocessed Source & Run Script

**Preprocessed source** (`/tmp/XmEJFAEsQwif_surfuzz_5-580d35.c`):

```c
# 1 ""
# 1 "/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c"
#define offsetof(type, mem) __builtin_offsetof (type, mem)
#define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
typedef __SIZE_TYPE__ size_t;
extern void* memcpy (void*, const void*, size_t);
extern void* memset (void*, int, __SIZE_TYPE__);
#undef offsetof
enum En {
E0 = 0,
E1 = E0 + offsetfrom (int, char, c),
E2 = E1 + offsetfrom (struct S, foo, 8),
E3 = E2 + offsetof (struct S, baz[8]),
E4 = E3 + offsetof (struct S, quux),
E5 = E4 + offsetof (struct S, bar[5]),
E6 = E5 + sizeof (struct S),
E7 = E6 + 12,
E8 = E7 + (offsetfrom (ssize_t, intmax_t, value)),
E9 = E8,
};
extern short random_value (void);
extern short nondet_short (void);
extern int random_unsigned_value (void);
extern int nondet_int (void);
extern long random_long_value (void);
extern long nondet_long (void);
void test_offset_object_1 ()
{
char c;
struct S s;
int x;
if (random_value ())
return;
x = offsetfrom (int, char, c);
escape (&x
struct B { struct A a; char c, d; };
void escape (void*, ...);
size_t random_unsigned_value (void);
static inline size_t
range (size_t min, size_t max)
{
const size_t val = random_unsigned_value ();
return val < min || max < val ? min : val;
}
void test_memop_warn_object (const void *src)
{
unsigned n = range (17, 29);
struct A a[2];
memcpy (&a[0], src, n);
escape (a);
}
void test_memop_warn_subobject (const void *src)
{
unsigned n = range (17, 31);
struct B b[2];
memcpy (&b[0].a, src, n);
escape (b);
}
void test_memop_nowarn_subobject (void)
{
struct B b[2];
memset (&b[0].c, 0, sizeof b[0] - offsetof (struct B, c));
escape (b);
}
struct C { char a[3], b; };
struct D { struct C c; char d, e; };
extern char* strncpy (char*, const char*, __SIZE_TYPE__);
void test_stringop_warn_object (const char *str)
{
unsigned n = range (2 * sizeof (struct D), 32);
struct C c[2];
strncpy (c[0].a, "123", n);
escape (c);
strncpy (c[0].a, str, n);
escape (c);
}
void test_stringop_warn_subobject (const char *src)
{
unsigned n = range (2 * sizeof (struct D), 32);
struct D d[2];
strncpy (d[0].c.a, "123", n);
escape (d);
strncpy (d[0].c.a, src, n);
escape (d);
}

```

**Run script** (`/tmp/XmEJFAEsQwif_surfuzz_5-580d35.sh`):

```sh
# Crash reproducer for clang version 22.1.5 (https://github.com/llvm/llvm-project.git 5ea218a153f4d2f815b8244eab3e4b4ba5e00e6c)
# Driver args: "-O0" "/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c" "-o" "/dev/null"
# Original command: "/root/objects/llvm-project-release.obj/bin/clang-22" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-O0" "-emit-obj" "-dumpdir" "/dev/null-" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "XmEJFAEsQwif_surfuzz_5.c" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-debugger-tuning=gdb" "-fdebug-compilation-dir=/root/data" "-fcoverage-compilation-dir=/root/data" "-resource-dir" "/root/objects/llvm-project-release.obj/lib/clang/22" "-internal-isystem" "/root/objects/llvm-project-release.obj/lib/clang/22/include" "-internal-isystem" "/usr/local/include" "-internal-isystem" "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include" "-internal-externc-isystem" "/usr/include/x86_64-linux-gnu" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf" "-faddrsig" "-fdwarf2-cfi-asm" "-o" "/tmp/XmEJFAEsQwif_surfuzz_5-40ace2.o" "-x" "c" "/root/outputs/experiments-on-metamut/surfuzz,gcc,1/XmEJFAEsQwif_surfuzz_5.c"
"/root/objects/llvm-project-release.obj/bin/clang-22" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-O0" "-emit-obj" "-dumpdir" "/dev/null-" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "XmEJFAEsQwif_surfuzz_5.c" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-debugger-tuning=gdb" "-fdebug-compilation-dir=/root/data" "-fcoverage-compilation-dir=/root/data" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf" "-faddrsig" "-fdwarf2-cfi-asm" "-x" "c" "XmEJFAEsQwif_surfuzz_5-580d35.c"

```

* found via a fuzzer

[XmEJFAEsQwif_surfuzz_5-580d35.c](https://github.com/user-attachments/files/29128367/XmEJFAEsQwif_surfuzz_5-580d35.c)
[XmEJFAEsQwif_surfuzz_5-580d35.sh](https://github.com/user-attachments/files/29128368/XmEJFAEsQwif_surfuzz_5-580d35.sh)

Contributor guide

Open the contributing guide

Research direction

Reproduce the crash with the reduced enum test case and `clang -O0 test.c -o /dev/null`. Then inspect `clang::Sema::BuildBinOp` in `clang/lib/Sema/SemaExpr.cpp` and its caller `clang::Parser::ParseRHSOfBinaryExpression`; done means malformed input is diagnosed without triggering the assertion.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.