curl 如何在不经意间实现了九个月的图灵完备性
摘要
一篇技术文章展示了 curl 8.12 至 8.16 如何通过变量切片和无限制的配置文件包含意外地变得图灵完备,使得任意双计数器 Minsky 程序都可以被编译为配置文件,直到 curl 8.17 引入了五层包含上限,打破了这一归约。
<p><a href="https://lobste.rs/s/f4aqog/how_curl_was_accidentally_turing">评论</a></p>
查看缓存全文
缓存时间: 2026/10/30 09:11
# curl 意外成为图灵完备长达九个月
来源:https://seriot.ch/computation/curl.html
### Nicolas Seriot
#### 计算 (https://seriot.ch/computation/index.html) \> curl 意外成为图灵完备长达九个月
*2026年10月29日*
从 curl 8\.12 到 8\.16,配置文件可以对变量值进行切片,也可以在没有显式深度限制的情况下包含其他配置文件。结合这两个特性,curl 可以模拟任何双计数器 Minsky 程序。在通常的理想化假设下(无界字符串和资源),这个构造是图灵完备的。
curl 8\.17\.0 增加了五层包含上限,破坏了这种归约。
### Minsky 双计数器归约
计数器值 `n` 用 `n` 个 `x` 的副本表示。
每个指令状态使用一个或多个配置文件,文件名充当标签,`expand-config` 用于选择下一个文件。
语法:
- `{{b}}` 展开当前值
- `[0-0]` 仅保留第一个字节(`x` 或空)
- `[1-]` 去掉第一个字节后保留其余所有内容
- 空切片产生空字符串(文档:https://github.com/curl/curl/blob/curl-8_12_0/docs/cmdline-opts/variable.md)
| Minsky 指令 | Curl 配置 |
|---|---|
| 寄存器 `R` | 变量 `r`(`R` 为 `x` 字节的数量) |
| `INC(R)` | `expand-variable = "r={{r}}x"` |
| `DEC(R)` | `expand-variable = "r[1-]={{r}}"` |
| `JZ(R, _, _x)` | `expand-variable = "t[0-0]={{r}}"` |
| | `expand-config = "state_{{t}}.conf"` |
| `JMP(S)` | `expand-config = "S.conf"` |
| Halt | 不再调用 `expand-config` |
有了这些,我们就可以将任何双计数器程序编译为 curl 配置文件。
### PoC:计算 2 \+ 3
curl\_addition\.zip (https://seriot.ch/resources/curl_addition.zip) 中的四个文件可以计算 2 \+ 3。
如有需要,请先构建本地 curl 8\.12\.0 二进制文件:
```
mkdir -p /tmp/curl-tc-build
cd /tmp/curl-tc-build
curl -fsSLO https://curl.se/download/curl-8.12.0.tar.gz
tar -xzf curl-8.12.0.tar.gz
cd curl-8.12.0
./configure --without-ssl --disable-shared --disable-manual --disable-docs
make -j4
```
然后在 `addition/` 目录下运行:
```
/tmp/curl-tc-build/curl-8.12.0/src/curl -q -s -K main.conf
```
预期输出:
```
A=xxxxx B=
```
### 运行时边界
该归约假设计数器无界且步数无界。实际的二进制文件两者都有限制:
- **展开内容(curl 自身的限制)。**每次展开上限为 `MAX_EXPAND_CONTENT` = 10,000,000 字节(`src/var.c`:https://github.com/curl/curl/blob/curl-8_12_0/src/var.c#L42)。
- **步数。**没有循环:每一步都是一次嵌套的 `--config`,直到停机才返回。每一层都占用一个 C 栈帧,并在完成之前保持其配置文件处于打开状态。在 8\.12 上一个最小的倒计时循环中,8 MB 的栈在出现段错误之前允许执行 922 步。
- **保留的变量版本。**重新赋值会添加一个新条目(https://github.com/curl/curl/blob/curl-8_12_0/src/var.c#L347-L370),同时保留旧条目直到清理(https://github.com/curl/curl/blob/curl-8_12_0/src/var.c#L58-L78)。内存使用量和某些变量查找开销随步数增加而增长。
### 历史与版本支持
- curl 8\.3(2023年9月):变量展开
- curl 8\.12(2025年2月):字节范围赋值
- curl 8\.17(2025年11月):五层上限(https://github.com/curl/curl/blob/curl-8_17_0/src/tool_parsecfg.h#L28-L30)破坏了该归约
Pull request(https://github.com/curl/curl/pull/19168)称该上限可以防止配置文件无限地包含自身。其回归测试(https://github.com/curl/curl/blob/curl-8_17_0/tests/data/test774)确实执行了此操作,并期望得到错误。公开的解释并未讨论图灵完备性,也没有说明为什么上限是五层。
Bash 的 `while` 循环可以补充受限的 curl:每次调用执行一步配置,并在调用之间传递计数器和指令标签。此时重复来自 Bash,因此这是一种组合,而非仅凭 curl 实现图灵完备。
### 安全影响
无。
相似文章
两个针对 arm64 的编译器错误代码生成问题导致 curl 出现安全漏洞
发现两个针对 arm64 架构的编译器错误代码生成问题,导致 curl 出现安全漏洞。该问题凸显了特定架构下的代码生成缺陷可能如何传导到广泛使用的开源软件中,目前正被放在 Lobsters 上讨论。
Aisle 在 curl 中发现 6 个新 CVE,包括有史以来报告的最古老问题
AISLE 利用其模型无关的 AI 系统在 curl 中发现了 6 个新 CVE,其中包括有史以来报告的最古老漏洞(超过 25 年)。所有发现均在 curl 8.21.0 中修复。
curl 待修复的二十二个漏洞
curl 8.23.0 将于 2026 年 10 月 14 日提前发布,以修复一个高危漏洞(CVE-2026-92392)以及另外 21 个较不严重的安全缺陷。
OpenAI 和 Anthropic 未发现漏洞后,发现六个 curl CVE
AISLE 的自主人工智能系统在 OpenAI 和 Anthropic 的系统未发现任何漏洞后,发现了六个 curl CVE,展示了 AI 驱动网络安全的进步。这些低严重性漏洞已在 curl 8.22.0 中修复。
Curl 将在2026年7月暂停接受漏洞报告
curl 项目将在2026年7月暂时停止接受漏洞报告,以便维护者休息,并将下一个版本推迟至2026年9月2日发布。