Heap Use-After-Free in VLA Size Emission via DenseMap Reference Invalidation
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
**Bug summary**
A heap use-after-free write exists in Clang's code generation for variable-length arrays (VLAs). When compiling C code containing a VLA whose size expression is a statement expression (`({...})`) that itself contains VLA declarations, the `EmitVariablyModifiedType` function holds a C++ reference into the `VLASizeMap` DenseMap while recursively processing inner VLAs. The recursive insertions cause the DenseMap to grow, freeing the old bucket storage. The stale reference is then written through, causing an 8-byte write to freed heap memory. The bug requires compiling a crafted C source file with deeply nested VLA-in-statement-expression constructs.
**PoC / reproduction**
- Entrypoint: `clang-fuzzer`
Reproduce via OSS-Fuzz (uses `reproduce.py`, which reads the PoC file above):
```bash
export OSS_FUZZ_DIR=~/oss-fuzz
python3 reproduce.py poc.c
```
PoC contents:
```c
void test(int n) {
int pre0[n+0];
(void)pre0;
int pre1[n+1];
(void)pre1;
int pre2[n+2];
(void)pre2;
int pre3[n+3];
(void)pre3;
int pre4[n+4];
(void)pre4;
int pre5[n+5];
(void)pre5;
int pre6[n+6];
(void)pre6;
int pre7[n+7];
(void)pre7;
int pre8[n+8];
(void)pre8;
int pre9[n+9];
(void)pre9;
int pre10[n+10];
(void)pre10;
int pre11[n+11];
(void)pre11;
int pre12[n+12];
(void)pre12;
int pre13[n+13];
(void)pre13;
int pre14[n+14];
(void)pre14;
int pre15[n+15];
(void)pre15;
int pre16[n+16];
(void)pre16;
int pre17[n+17];
(void)pre17;
int pre18[n+18];
(void)pre18;
int pre19[n+19];
(void)pre19;
int pre20[n+20];
(void)pre20;
int pre21[n+21];
(void)pre21;
int pre22[n+22];
(void)pre22;
int pre23[n+23];
(void)pre23;
int pre24[n+24];
(void)pre24;
int pre25[n+25];
(void)pre25;
int pre26[n+26];
(void)pre26;
int pre27[n+27];
(void)pre27;
int pre28[n+28];
(void)pre28;
int pre29[n+29];
(void)pre29;
int pre30[n+30];
(void)pre30;
int pre31[n+31];
(void)pre31;
int pre32[n+32];
(void)pre32;
int pre33[n+33];
(void)pre33;
int pre34[n+34];
(void)pre34;
int pre35[n+35];
(void)pre35;
int pre36[n+36];
(void)pre36;
int pre37[n+37];
(void)pre37;
int pre38[n+38];
(void)pre38;
int pre39[n+39];
(void)pre39;
int pre40[n+40];
(void)pre40;
int pre41[n+41];
(void)pre41;
int pre42[n+42];
(void)pre42;
int pre43[n+43];
(void)pre43;
int pre44[n+44];
(void)pre44;
int pre45[n+45];
(void)pre45;
int trig[({int in0[n+46]; (void)in0; int in1[n+47]; (void)in1; n;})];
(void)trig;
}
```
**ASAN backtrace**
```text
+ FUZZER=clang-fuzzer
+ shift
+ '[' '!' -v TESTCASE ']'
+ TESTCASE=/testcase
+ '[' '!' -f /testcase ']'
+ export RUN_FUZZER_MODE=interactive
+ RUN_FUZZER_MODE=interactive
+ export FUZZING_ENGINE=libfuzzer
+ FUZZING_ENGINE=libfuzzer
+ export SKIP_SEED_CORPUS=1
+ SKIP_SEED_CORPUS=1
+ run_fuzzer clang-fuzzer -runs=100 /testcase
vm.mmap_rnd_bits = 28
/out/clang-fuzzer -- -rss_limit_mb=2560 -timeout=25 -runs=100 /testcase -dict=clang-fuzzer.dict < /dev/null
INFO: libFuzzer ignores flags that start with '--'
Dictionary: 551 entries
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1408679553
INFO: Loaded 1 modules (2841577 inline 8-bit counters): 2841577 [0x55556d64d530, 0x55556d903119),
INFO: Loaded 1 PC tables (2841577 PCs): 2841577 [0x55556d903120,0x55557045efb0),
/out/clang-fuzzer: Running 1 inputs 100 time(s) each.
Running: /testcase
=================================================================
[1m[31m==14==ERROR: AddressSanitizer: heap-use-after-free on address 0x7d8ff6c08bf8 at pc 0x55555fe85b1c bp 0x7fffffffcd50 sp 0x7fffffffcd48
[1m[0m[1m[34mWRITE of size 8 at 0x7d8ff6c08bf8 thread T0[1m[0m
SCARINESS: 52 (8-byte-write-heap-use-after-free)
#0 0x55555fe85b1b in clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:2641:17
#1 0x55555f99e9b4 in clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1497:5
#2 0x55555f98f89f in EmitAutoVarDecl /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1349:30
#3 0x55555f98f89f in clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:230:10
#4 0x55555f98eabc in clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&, bool) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:171:5
#5 0x55555f7f7180 in clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:1686:5
#6 0x55555f7d9bce in clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:518:5
#7 0x55555f7d80ba in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:63:7
#8 0x55555f7fb6c1 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:576:5
#9 0x55555fe896e2 in EmitFunctionBody /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1371:5
#10 0x55555fe896e2 in clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1620:5
#11 0x55555ff1c7f7 in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:6723:26
#12 0x55555ff01af6 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4743:12
#13 0x55555ff12155 in clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4454:5
#14 0x55555fefd5ed in clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:7630:5
#15 0x5555602ea989 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp:195:18
#16 0x55555f3d4e35 in clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:169:8
#17 0x555564d88cff in clang::ParseAST(clang::Sema&, bool, bool) /src/llvm-project/clang/lib/Parse/ParseAST.cpp:174:31
#18 0x55555f3e72ad in clang::CodeGenAction::ExecuteAction() /src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:1107:30
#19 0x5555643f3a51 in clang::FrontendAction::Execute() /src/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1326:3
#20 0x55556426b41f in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:990:33
#21 0x555563c50191 in clang::tooling::FrontendActionFactory::runInvocation(std::__1::shared_ptr, clang::FileManager*, std::__1::shared_ptr, clang::DiagnosticConsumer*) /src/llvm-project/clang/lib/Tooling/Tooling.cpp:459:33
#22 0x55555f3aeed7 in clang_fuzzer::HandleCXX(std::__1::basic_string, std::__1::allocator> const&, char const*, std::__1::vector> const&) /src/llvm-project/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp:48:11
#23 0x55555f3ad9e8 in LLVMFuzzerTestOneInput /src/llvm-project/clang/tools/clang-fuzzer/ClangFuzzer.cpp:23:3
#24 0x55555f24ae2d in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
#25 0x55555f234b42 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:329:6
#26 0x55555f23aa10 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:865:9
#27 0x55555f2675a2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#28 0x7ffff7c1d082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d)
#29 0x55555f22dc2d in _start (/out/clang-fuzzer+0x9cd9c2d)
DEDUP_TOKEN: clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType)--clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&)--EmitAutoVarDecl
[1m[32m0x7d8ff6c08bf8 is located 376 bytes inside of 1024-byte region [0x7d8ff6c08a80,0x7d8ff6c08e80)
[1m[0m[1m[35mfreed by thread T0 here:[1m[0m
#0 0x55555f3ad6e7 in operator delete(void*, unsigned long, std::align_val_t) /src/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:216:3
#1 0x55555f80ee50 in deallocateBuckets /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:826:5
#2 0x55555f80ee50 in kill /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:843:5
#3 0x55555f80ee50 in llvm::DenseMapBase, llvm::detail::DenseMapPair>, clang::Expr const*, llvm::Value*, llvm::DenseMapInfo, llvm::detail::DenseMapPair>::moveFrom(llvm::DenseMap, llvm::detail::DenseMapPair>&) /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:458:21
#4 0x55555f80e9d5 in llvm::DenseMapBase, llvm::detail::DenseMapPair>, clang::Expr const*, llvm::Value*, llvm::DenseMapInfo, llvm::detail::DenseMapPair>::grow(unsigned int) /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:570:9
#5 0x55555f80e5f0 in llvm::detail::DenseMapPair* llvm::DenseMapBase, llvm::detail::DenseMapPair>, clang::Expr const*, llvm::Value*, llvm::DenseMapInfo, llvm::detail::DenseMapPair>::findBucketForInsertion(clang::Expr const* const&, llvm::detail::DenseMapPair*) /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h
#6 0x55555fe85089 in lookupOrInsertIntoBucket /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:510:17
#7 0x55555fe85089 in operator[] /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:350:12
#8 0x55555fe85089 in clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:2613:31
#9 0x55555f99e9b4 in clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1497:5
#10 0x55555f98f89f in EmitAutoVarDecl /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1349:30
#11 0x55555f98f89f in clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:230:10
#12 0x55555f98eabc in clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&, bool) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:171:5
#13 0x55555f7f7180 in clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:1686:5
#14 0x55555f7d9bce in clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:518:5
#15 0x55555f7d80ba in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:63:7
#16 0x55555f7fb6c1 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:576:5
#17 0x55555f7f6ed3 in clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:565:10
#18 0x55555f5cd2d2 in (anonymous namespace)::ScalarExprEmitter::VisitStmtExpr(clang::StmtExpr const*) /src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp:3200:27
#19 0x55555f599424 in Visit /src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp:491:52
#20 0x55555f599424 in clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) /src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp:6154:8
#21 0x55555fe8510e in clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:2615:31
#22 0x55555f99e9b4 in clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1497:5
#23 0x55555f98f89f in EmitAutoVarDecl /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1349:30
#24 0x55555f98f89f in clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:230:10
#25 0x55555f98eabc in clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&, bool) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:171:5
#26 0x55555f7f7180 in clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:1686:5
#27 0x55555f7d9bce in clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:518:5
#28 0x55555f7d80ba in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:63:7
#29 0x55555f7fb6c1 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:576:5
#30 0x55555fe896e2 in EmitFunctionBody /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1371:5
#31 0x55555fe896e2 in clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1620:5
#32 0x55555ff1c7f7 in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:6723:26
#33 0x55555ff01af6 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4743:12
#34 0x55555ff12155 in clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4454:5
#35 0x55555fefd5ed in clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:7630:5
#36 0x5555602ea989 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp:195:18
#37 0x55555f3d4e35 in clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:169:8
DEDUP_TOKEN: operator delete(void*, unsigned long, std::align_val_t)--deallocateBuckets--kill
[1m[35mpreviously allocated by thread T0 here:[1m[0m
#0 0x55555f3acb22 in operator new(unsigned long, std::align_val_t, std::nothrow_t const&) /src/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:131:3
#1 0x55556cec8a82 in llvm::allocate_buffer(unsigned long, unsigned long) /src/llvm-project/llvm/lib/Support/MemAlloc.cpp:16:18
#2 0x55555f80e76b in allocateBuckets /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:837:9
#3 0x55555f80e76b in initWithExactBucketCount /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:383:19
#4 0x55555f80e76b in DenseMap /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:760:11
#5 0x55555f80e76b in llvm::DenseMapBase, llvm::detail::DenseMapPair>, clang::Expr const*, llvm::Value*, llvm::DenseMapInfo, llvm::detail::DenseMapPair>::grow(unsigned int) /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:569:14
#6 0x55555f80e5f0 in llvm::detail::DenseMapPair* llvm::DenseMapBase, llvm::detail::DenseMapPair>, clang::Expr const*, llvm::Value*, llvm::DenseMapInfo, llvm::detail::DenseMapPair>::findBucketForInsertion(clang::Expr const* const&, llvm::detail::DenseMapPair*) /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h
#7 0x55555fe85089 in lookupOrInsertIntoBucket /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:510:17
#8 0x55555fe85089 in operator[] /src/llvm-project/llvm/include/llvm/ADT/DenseMap.h:350:12
#9 0x55555fe85089 in clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:2613:31
#10 0x55555f99e9b4 in clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1497:5
#11 0x55555f98f89f in EmitAutoVarDecl /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:1349:30
#12 0x55555f98f89f in clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:230:10
#13 0x55555f98eabc in clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&, bool) /src/llvm-project/clang/lib/CodeGen/CGDecl.cpp:171:5
#14 0x55555f7f7180 in clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:1686:5
#15 0x55555f7d9bce in clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:518:5
#16 0x55555f7d80ba in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:63:7
#17 0x55555f7fb6c1 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) /src/llvm-project/clang/lib/CodeGen/CGStmt.cpp:576:5
#18 0x55555fe896e2 in EmitFunctionBody /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1371:5
#19 0x55555fe896e2 in clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:1620:5
#20 0x55555ff1c7f7 in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:6723:26
#21 0x55555ff01af6 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4743:12
#22 0x55555ff12155 in clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:4454:5
#23 0x55555fefd5ed in clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) /src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp:7630:5
#24 0x5555602ea989 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp:195:18
#25 0x55555f3d4e35 in clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) /src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:169:8
#26 0x555564d88cff in clang::ParseAST(clang::Sema&, bool, bool) /src/llvm-project/clang/lib/Parse/ParseAST.cpp:174:31
#27 0x55555f3e72ad in clang::CodeGenAction::ExecuteAction() /src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:1107:30
#28 0x5555643f3a51 in clang::FrontendAction::Execute() /src/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1326:3
#29 0x55556426b41f in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:990:33
#30 0x555563c50191 in clang::tooling::FrontendActionFactory::runInvocation(std::__1::shared_ptr, clang::FileManager*, std::__1::shared_ptr, clang::DiagnosticConsumer*) /src/llvm-project/clang/lib/Tooling/Tooling.cpp:459:33
#31 0x55555f3aeed7 in clang_fuzzer::HandleCXX(std::__1::basic_string, std::__1::allocator> const&, char const*, std::__1::vector> const&) /src/llvm-project/clang/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp:48:11
#32 0x55555f3ad9e8 in LLVMFuzzerTestOneInput /src/llvm-project/clang/tools/clang-fuzzer/ClangFuzzer.cpp:23:3
#33 0x55555f24ae2d in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
#34 0x55555f234b42 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:329:6
#35 0x55555f23aa10 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:865:9
#36 0x55555f2675a2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
DEDUP_TOKEN: operator new(unsigned long, std::align_val_t, std::nothrow_t const&)--llvm::allocate_buffer(unsigned long, unsigned long)--allocateBuckets
SUMMARY: AddressSanitizer: heap-use-after-free /src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp:2641:17 in clang::CodeGen::CodeGenFunction::EmitVariablyModifiedType(clang::QualType)
Shadow bytes around the buggy address:
0x7d8ff6c08900: [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m [1m[0m00[1m[0m
0x7d8ff6c08980: [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m
0x7d8ff6c08a00: [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m [1m[31mfa[1m[0m
0x7d8ff6c08a80: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
0x7d8ff6c08b00: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
=>0x7d8ff6c08b80: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m[[1m[35mfd[1m[0m]
0x7d8ff6c08c00: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
0x7d8ff6c08c80: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
0x7d8ff6c08d00: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
0x7d8ff6c08d80: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
0x7d8ff6c08e00: [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m [1m[35mfd[1m[0m
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: [1m[0m00[1m[0m
Partially addressable: [1m[0m01[1m[0m [1m[0m02[1m[0m [1m[0m03[1m[0m [1m[0m04[1m[0m [1m[0m05[1m[0m [1m[0m06[1m[0m [1m[0m07[1m[0m
Heap left redzone: [1m[31mfa[1m[0m
Freed heap region: [1m[35mfd[1m[0m
Stack left redzone: [1m[31mf1[1m[0m
Stack mid redzone: [1m[31mf2[1m[0m
Stack right redzone: [1m[31mf3[1m[0m
Stack after return: [1m[35mf5[1m[0m
Stack use after scope: [1m[35mf8[1m[0m
Global redzone: [1m[31mf9[1m[0m
Global init order: [1m[36mf6[1m[0m
Poisoned by user: [1m[34mf7[1m[0m
Container overflow: [1m[34mfc[1m[0m
Array cookie: [1m[31mac[1m[0m
Intra object redzone: [1m[33mbb[1m[0m
ASan internal: [1m[33mfe[1m[0m
Left alloca redzone: [1m[34mca[1m[0m
Right alloca redzone: [1m[34mcb[1m[0m
==14==ABORTING
```
**Fix (diff)**
```diff
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index fb0d5e450..edeb76681 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2610,8 +2610,9 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
if (const Expr *sizeExpr = vat->getSizeExpr()) {
// It's possible that we might have emitted this already,
// e.g. with a typedef and a pointer to it.
- llvm::Value *&entry = VLASizeMap[sizeExpr];
- if (!entry) {
+ // Note: don't hold a reference into VLASizeMap across EmitScalarExpr
+ // (which may recursively emit VLA sizes and grow the map).
+ if (!VLASizeMap.lookup(sizeExpr)) {
llvm::Value *size = EmitScalarExpr(sizeExpr);
// C11 6.7.6.2p5:
@@ -2638,7 +2639,8 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
// Always zexting here would be wrong if it weren't
// undefined behavior to have a negative bound.
// FIXME: What about when size's type is larger than size_t?
- entry = Builder.CreateIntCast(size, SizeTy, /*signed*/ false);
+ VLASizeMap[sizeExpr] =
+ Builder.CreateIntCast(size, SizeTy, /*signed*/ false);
}
}
type = vat->getElementType();
```
**Background of that issue**
This bug was found as a part of an Anthropic research into the use of large language models for automated vulnerability discovery in open source software. Anthropic then engaged Trail of Bits to independently triage and validate those issues.
Contributor guide
Assessment
This issue has not been assessed yet.