| タイトル | cmake 4.1.20250725-gb5cce23 and other recent versions of the 4.x series. assertion failure |
|---|
| 説明 | # CMake ForEach 断言失败漏洞
## 漏洞总结
在对 CMake 4.1.20250725-gb5cce23 进行模糊测试期间,在 CMake foreach 命令处理中发现了一个严重的断言失败漏洞。该漏洞发生在第 112 行“cmForEachCommand.cxx”中的“cmForEachFunctionBlocker::ReplayItems”函数中,其中断言检查由于意外迭代变量计数而失败,导致程序通过“SIGABRT”终止。
## 技术细节
- **漏洞类型**:断言失败
- **受影响的函数**: 'cmForEachFunctionBlocker::ReplayItems'
- **源文件**: 'cmForEachCommand.cxx'
- **行号**:112
- **信号**:SIGABRT (6)
- **组件**:CMake Core
## 漏洞机制及根本原因
此断言失败漏洞是由 foreach 命令处理逻辑中迭代变量计数验证不当引起的。根本问题在于“cmForEachFunctionBlocker::ReplayItems”函数,其中断言只需要一个迭代变量,但遇到不同的计数。
在以下情况下会出现此漏洞:
1. CMake 处理包含 foreach 构造的格式错误的CMakeLists.txt文件
2. foreach 命令解析器遇到语法错误或参数格式错误
3. 解析器创建一个具有意外迭代变量计数的 foreach 函数阻塞器
4. 当调用“ReplayItems”时,断言“”Unexpected number of iteration variables“ &; &; this->IterationVarsCount == 1' 失败
5. 程序立即终止 SIGABRT
这会产生拒绝服务条件,其中 CMake 无法处理输入文件并因断言失败而崩溃。该漏洞影响 CMake 解析和处理包含格式错误的 foreach 构造的CMakeLists.txt文件的能力。
## GDB 调试报告
```
程序接收信号 SIGABRT,中止。
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737348078528) 在 ./nptl/pthread_kill.c:44
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737348078528) 在 ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=140737348078528) 在 ./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=140737348078528, signo=signo@entry=6) 在 ./nptl/pthread_kill.c:89
#3 0x00007ffff7a7f476 在 __GI_raise (sig=sig@entry=6) 处。/sysdeps/posix/raise.c:26
#4 __GI_abort () 中的 #79 0x00007ffff7a657f3 ./stdlib/abort.c:79
#5 __assert_fail_base中的0x00007ffff7a6571b (fmt=0x7ffff7c1a130 “%s%s%s:%u: %s%s断言 '%s' 失败。\n%n“, assertion=0x5555557dbb80 <str.32> ”\“意外的迭代变量数\” &&;this->IterationVarsCount == 1“, file=0x5555557db540 <str.8> ”/workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmForEachCommand.cxx“, line=112, function=<optimized out>) at ./assert/assert.c:94
#6 __GI___assert_fail中的0x00007ffff7a76e96 (assertion=0x5555557dbb80 <str.32> “\”意外的迭代变量数量\“ &&; this->IterationVarsCount == 1”, file=0x5555557db540 <str.8> “/workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmForEachCommand.cxx”, line=112, function=0x5555557dbc00 <__PRETTY_FUNCTION__._ZN12_GLOBAL__N_124cmForEachFunctionBlocker11ReplayItemsERKSt6vectorI18cmListFileFunctionSaIS2_EER17cmExecutionStatus> ”bool(匿名命名空间)::cmForEachFunctionBlocker::ReplayItems(const std::vector<cmListFileFunction> &, cmExecutionStatus &)“) 在 ./assert/assert.c:103
#70x00005555563aaa06 in (anonymous namespace)::cmForEachFunctionBlocker::ReplayItems (this=0x611000002ac0, functions=std::vector of length 8, capacity 8 = {...}, inStatus=...) 位于 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmForEachCommand.cxx:111
#8 (匿名命名空间)::cmForEachFunctionBlocker::Replay (this=0x611000002ac0, functions=std::vector of length -6648609374956, capacity -6648609374956 = {...}, inStatus=...) 位于 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmForEachCommand.cxx:104
#9 在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmFunctionBlocker.cxx:52 的 cmFunctionBlocker::IsFunctionBlocked (this=<optimized out>, lff=..., status=...) 中的 0x00005555563be471
#10 在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmMakefile.cxx:2896 的 cmMakefile::IsFunctionBlocked (this=0x7ffff6007160, lff=..., status=...) 中的 cmMakefile::IsFunctionBlocked 中的 #10 0x0000555556e3a3b4
#11 cmMakefile::ExecuteCommand (this=0x7ffff6007160, lff=..., status=..., deferId=std::optional<std::string> = {...}) 位于 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmMakefile.cxx:542
#12 在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmMakefile.cxx:869 的 cmMakefile::RunListFile (this=0x7ffff6007160, listFile=..., filenametoread=..., defer=<optimized out>) 中的0x0000555556e494e2
#13 0x0000555556e50723在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmMakefile.cxx:823 的 cmMakefile::ReadListFile (this=0x7ffff6007160, filename=“POC_cmake_foreach_assertion_failure”) 中
#14 在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmake.cxx:811 的 cmake::ReadListFile (this=<optimized out>, args=..., 路径=...) 中的0x00005555573fa78b
#1 0x00005555573e0e35 5 cmake::SetCacheArgs(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)::$_3::operator()(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cmake*) const (this=0x619000009908, path=“POC_cmake_foreach_assertion_failure”, state=0x7ffff6201bd0) 在 /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmake.cxx:666
cmake: /workspace/program/cmake-4.1.20250725-gb5cce23/Source/cmForEachCommand.cxx:112: bool (anonymous namespace)::cmForEachFunctionBlocker::ReplayItems(const std::vector<cmListFileFunction> &, cmExecutionStatus &): 断言“”意外的迭代变量数“ &&;this->IterationVarsCount == 1' 失败。
```
## 概念验证
可以通过处理作为“POC_cmake_foreach_assertion_failure”提供的格式错误的CMakeLists.txt文件来触发该漏洞。此文件包含特定的 foreach 构造,其语法格式错误,会导致断言失败。
**POC 下载**:[POC_cmake_foreach_assertion_failure](https://drive.google.com/file/d/1TerUqQB8_lzJTwIBCBmE94zn7n-gOz4f/view?usp=sharing)
## 复制步骤
1. 在启用调试断言的情况下编译 CMake(或使用提供的二进制文件)
2. 执行: 'cmake -P POC_cmake_foreach_assertion_failure'
3. 程序将在 cmForEachCommand.cxx:112 处崩溃并断言失败
## 受影响的版本
CMake 版本 4.1.20250725-gb5cce23 以及可能的其他最新版本的 4.x 系列。
**信用**
- 曹旭东(UCAS)
- 旭孟(威斯康星大学) |
|---|
| ソース | ⚠️ https://gitlab.kitware.com/cmake/cmake/-/issues/27135 |
|---|
| ユーザー | xdcao (UID 88377) |
|---|
| 送信 | 2025年08月12日 09:32 (9 月 ago) |
|---|
| モデレーション | 2025年08月21日 07:28 (9 days later) |
|---|
| ステータス | 承諾済み |
|---|
| VulDBエントリ | 320906 [cmake 4.1.20250725-gb5cce23 cmForEachCommand.cxx ReplayItems サービス拒否] |
|---|
| ポイント | 20 |
|---|