assimp / assimp/assimp

Bug: Heap-buffer-overflow in Assimp::MDLImporter::GenerateOutputMeshes_3DGS_MDL7

Open
#6,631 0 comments 0 reactions 0 assignees View on GitHub
Bug Fuzzer MDL Sanitizer Security Risk
Dominant language
C++
Stars
13.2k
Forks
3.2k
Avg merge
2d 8h
Merged PRs (30d)
21

Description

**Describe the bug**

Heap-buffer-overflow in `Assimp::MDLImporter::GenerateOutputMeshes_3DGS_MDL7` function at `code/AssetLib/MDL/MDLLoader.cpp:1944` caused by out-of-bounds write to `pcMesh->mBones` when the loop index `iCurrent` exceeds the allocated array size.

**To Reproduce**
Steps to reproduce the behavior:

1. Clone the assimp repository and build it refer to oss-fuzz.

```shell
export CC=clang \
CXX=clang++ \
CFLAGS='-fsanitize=address -O0 -g' \
CXXFLAGS='-fsanitize=address -O0 -g' \
LIB_FUZZING_ENGINE='-fsanitize=fuzzer'
```

2. Run the PoC using assimp_fuzzer:

[poc.zip](https://github.com/user-attachments/files/27425495/poc.zip)

The PoC is provided as a zip archive. After extracting, run:

```shell
./assimp_fuzzer ./poc.mdl
```

**ASAN Report**

```
=================================================================
==2565==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5040000005c8 at pc 0x5fb05af47230 bp 0x7ffe51596b30 sp 0x7ffe51596b28
WRITE of size 8 at 0x5040000005c8 thread T0
#0 0x5fb05af4722f in Assimp::MDLImporter::GenerateOutputMeshes_3DGS_MDL7(Assimp::MDL::IntGroupData_MDL7&, Assimp::MDL::IntSplitGroupData_MDL7&) /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:1944:63
#1 0x5fb05af37cf8 in Assimp::MDLImporter::InternReadFile_3DGS_MDL7() /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:1552:9
#2 0x5fb05af2d498 in Assimp::MDLImporter::InternReadFile(std::__cxx11::basic_string, std::allocator> const&, aiScene*, Assimp::IOSystem*) /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:243:13
#3 0x5fb05ab3c98b in Assimp::BaseImporter::ReadFile(Assimp::Importer*, std::__cxx11::basic_string, std::allocator> const&, Assimp::IOSystem*) /home/hexijie/fuzz/project/assimp/code/Common/BaseImporter.cpp:131:9
#4 0x5fb05a6720cf in Assimp::Importer::ReadFile(char const*, unsigned int) /home/hexijie/fuzz/project/assimp/code/Common/Importer.cpp:709:30
#5 0x5fb05a66fa19 in Assimp::Importer::ReadFileFromMemory(void const*, unsigned long, unsigned int, char const*) /home/hexijie/fuzz/project/assimp/code/Common/Importer.cpp:507:9
#6 0x5fb05a66b705 in LLVMFuzzerTestOneInput /home/hexijie/fuzz/project/assimp/build/../fuzz/assimp_fuzzer.cc:62:34
#7 0x5fb05a576b24 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x313b24) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#8 0x5fb05a55fc56 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x2fcc56) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#9 0x5fb05a56570a in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x30270a) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#10 0x5fb05a58fec6 in main (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x32cec6) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#11 0x7da15e62a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#12 0x7da15e62a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#13 0x5fb05a55a824 in _start (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x2f7824) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)

0x5040000005c8 is located 8 bytes after 48-byte region [0x504000000590,0x5040000005c0)
allocated by thread T0 here:
#0 0x5fb05a669371 in operator new[](unsigned long) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x406371) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#1 0x5fb05af47070 in Assimp::MDLImporter::GenerateOutputMeshes_3DGS_MDL7(Assimp::MDL::IntGroupData_MDL7&, Assimp::MDL::IntSplitGroupData_MDL7&) /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:1937:34
#2 0x5fb05af37cf8 in Assimp::MDLImporter::InternReadFile_3DGS_MDL7() /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:1552:9
#3 0x5fb05af2d498 in Assimp::MDLImporter::InternReadFile(std::__cxx11::basic_string, std::allocator> const&, aiScene*, Assimp::IOSystem*) /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:243:13
#4 0x5fb05ab3c98b in Assimp::BaseImporter::ReadFile(Assimp::Importer*, std::__cxx11::basic_string, std::allocator> const&, Assimp::IOSystem*) /home/hexijie/fuzz/project/assimp/code/Common/BaseImporter.cpp:131:9
#5 0x5fb05a6720cf in Assimp::Importer::ReadFile(char const*, unsigned int) /home/hexijie/fuzz/project/assimp/code/Common/Importer.cpp:709:30
#6 0x5fb05a66fa19 in Assimp::Importer::ReadFileFromMemory(void const*, unsigned long, unsigned int, char const*) /home/hexijie/fuzz/project/assimp/code/Common/Importer.cpp:507:9
#7 0x5fb05a66b705 in LLVMFuzzerTestOneInput /home/hexijie/fuzz/project/assimp/build/../fuzz/assimp_fuzzer.cc:62:34
#8 0x5fb05a576b24 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x313b24) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#9 0x5fb05a55fc56 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x2fcc56) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#10 0x5fb05a56570a in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x30270a) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#11 0x5fb05a58fec6 in main (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x32cec6) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)
#12 0x7da15e62a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#13 0x7da15e62a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#14 0x5fb05a55a824 in _start (/home/hexijie/fuzz/fuzzers/assimp_fuzzer+0x2f7824) (BuildId: 3707c90bb983c84eac8c279d24589825b44e573a)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/hexijie/fuzz/project/assimp/code/AssetLib/MDL/MDLLoader.cpp:1944:63 in Assimp::MDLImporter::GenerateOutputMeshes_3DGS_MDL7(Assimp::MDL::IntGroupData_MDL7&, Assimp::MDL::IntSplitGroupData_MDL7&)
Shadow bytes around the buggy address:
0x504000000300: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x504000000380: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x504000000400: fa fa 00 00 00 00 00 01 fa fa 00 00 00 00 00 fa
0x504000000480: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x504000000500: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
=>0x504000000580: fa fa 00 00 00 00 00 00 fa[fa]fa fa fa fa fa fa
0x504000000600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==2565==ABORTING
```

**Screenshots**

Image

The vulnerability is in the bone initialization loop:

1. The array `pcMesh->mBones` is allocated with size `pcMesh->mNumBones = 6`
2. The loop iterates over `aaiVWeightList` and increments `iCurrent` without boundary validation
3. When `iCurrent = 7`, the code performs an out-of-bounds write to `pcMesh->mBones[iCurrent]`
4. ASAN detects the invalid write, and GDB confirms the index is out of the array bounds

**Platform (please complete the following information):**

- OS: Ubuntu 22.04 (x86_64)
- Version: commit 17c12da558d23d70e4c728b30958e95cd616cbcb

Contributor guide

Open the contributing guide

Research direction

Start in code/AssetLib/MDL/MDLLoader.cpp at GenerateOutputMeshes_3DGS_MDL7, especially the bone allocation and initialization loop around lines 1937-1944. Build the ASAN fuzzing setup described in the issue and run assimp_fuzzer with the extracted poc.mdl. Done means the PoC no longer produces a heap-buffer-overflow and the affected MDL path remains functional.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.