编程与软件工程daniel.haxx.se
curl 就是 C
Curl is C
2017 — 2021,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
这篇文章是 curl 作者 Daniel Stenberg 对“curl 为什么用 C 写”的回应,说明项目选择 C 的工程理由,并主张过去多数安全漏洞来自逻辑错误而非语言本身。它也讨论重写成熟代码库的风险,因此成为 C 与内存安全语言之争中的经典文本。
为什么经久不衰:它把“要不要用 Rust 重写 C 项目”从语言偏好拉回漏洞归因、维护成本和工程现实,今天仍是这类争论的必读参考。
HN 评论精选
用具体安全公告反驳“漏洞与语言无关”,认为 Rust 的错误处理和默认检查能避免部分问题。
我对 curl 用 C 没意见(经过实战检验的 C 好过实验性的 Rust),但文章这一点让我觉得奇怪:它说“C 不是我们过去漏洞的主因”。于是我去看了 curl 安全页面:#61 是未初始化随机值,内部函数实现不佳,覆盖了指针而不是把值写入缓冲区;#60 是 printf 浮点缓冲区溢出;#57 是 cookie 注入,用 fgets() 逐行读入固定大小缓冲区时,行太长会被截断;#55 是未检查乘法导致越界写。最后一条不完全是 C 本身的失败,但我认为 Rust 通过 Option/Result 鼓励更稳健的错误处理,而 C 常用 -1 和 NULL 返回值,需要小心检查且编译器通常无法强制。Rust 在 debug 构建默认检查乘法。
simias查看英文原文
I have no problem with Curl being written in C (I'll take battle-tested C over experimental Rust) but this point seemed odd to me: >C is not the primary reason for our past vulnerabilities >There. The simple fact is that most of our past vulnerabilities happened because of logical mistakes in the code. Logical mistakes that aren’t really language bound and they would not be fixed simply by changing language. So I looked at https://curl.haxx.se/docs/security.html #61 -> uninitialized random : libcurl's (new) internal function that returns a good 32bit random value was implemented poorly and overwrote the pointer instead of writing the value into the buffer the pointer pointed to. #60 -> printf floating point buffer overflow #57 -> cookie injection for other servers : The issue pertains to the function that loads cookies into memory, which reads the specified file into a fixed-size buffer in a line-by-line manner using the fgets() function. If an invocation of fgets() cannot read the whole line into the destination buffer due to it being too small, it truncates the output This one is arguably not really a failure of C itself, but I'd argue that Rust encourages a more robust error handling through its Options and Results when C tends to abuse "-1" and NULL return types that need careful checking and can't usually be enforced by the compiler. #55 -> OOB write via unchecked multiplication Rust has checked multiplication enabled by default in debug builds, and regardless of that the OOB wouldn't be possible. #54 -> Double free in curl_maprintf #53 -> Double free in krb5 code #52 -> glob parser write/read out of bound And I'll stop here, so far 7 out of 11 vulnerabilities would probably have been avoided with a safer language. Looks like the vast majority of these issues wouldn't have been possible in safe Rust.
尊重 curl 的现状,但主张网络代码应使用内存安全语言,并改变行业文化。
我有点纠结。一方面,curl 是优秀软件,安全记录比大多数项目好,迄今的工程选择很有效,开发者认为重写有风险且没必要也很合理。另一方面,互联网安全现状很糟,要改善就得让“用非内存安全语言写网络代码”被视为专业失职;因为在不靠编译器检查的情况下可靠地不引入内存破坏漏洞,超出了程序员现实可被要求的标准,而网络代码里这类漏洞常立即造成严重安全后果。我们需要让严肃程序员不这么做,就像不写 BASIC 或用 tar 包做版本控制一样。现有大量高知名度网络软件用 C 写,让这更难,因为大家会想“那些项目都这么做,所以没问题”。
ameliaquining查看英文原文
I'm kind of torn on this. On the one hand, Curl is a great piece of software with a better security record than most, the engineering choices it's made thus far have served it just fine, and its developers quite reasonably view rewriting it as risky and unnecessary. On the other hand, the state of internet security is really terrible, and the only way it'll ever get fixed is if we somehow get to the point where writing networking code in a non-memory-safe language is considered professional malpractice. Because it should be; reliably not introducing memory corruption bugs without a compiler checking your work is a higher standard than programmers can realistically be held to, and in networking code such bugs often have immediate and dramatic security consequences. We need to somehow create a culture where serious programmers don't try to do this, the same way serious programmers don't write in BASIC or use tarball backups as version control. That so much existing high-profile networking software is written in C makes this a lot harder, because everyone thinks "well all those projects do it so it must be okay".
提出用安全语言生成 C 代码的折中方案,兼顾最终用户部署和开发安全。
虽然不完全适用于 libcurl,但除了“全用 C 写”和“全用更安全语言写”,还有第三种选择:用更安全的语言生成 C 代码。最终用户即使从源码编译也只需要 C 编译器,只有开发者需要安装更安全的语言(curl 开发者本来也要装 valgrind 跑完整测试)。生成代码可用于非 C 语言绑定、描述 API 并生成头文件/函数原型/包装、对 API 参数做类型检查,以及任何需要单一事实来源的地方。我们在两个项目里成功用了 OCaml 生成器生成大部分 C 代码。
rwmj查看英文原文
While this doesn't so much apply to libcurl (but see below), there is a third alternative to "write everything in C" or "write everything in <some other safer language>". That is: use a safer language to generate C code. End users, even those compiling from source, will still only need a C compiler. Only developers need to install the safer language (even Curl developers must install valgrind to run the full tests). Where can you use generated code? - For non-C language bindings (this could apply to the Curl project, but libcurl is a bit unusual in that it doesn't include other bindings, they are supplied by third parties). - To describe the API and generate header files, function prototypes, and wrappers. - To enforce type checking on API parameters (eg. all the CURL_EASY_... options could be described in the generator and then that can be turned into some kind of type checking code). - Any other time you want a single source of truth in your codebase. We use a generator (written in OCaml, generating mostly C) successfully in two projects: https://github.com/libguestfs/libguestfs/tree/master/generator https://github.com/libguestfs/hivex/tree/master/generator
文章观点已有后续变化,curl 后来引入 Rust 后端。
建议标题加上“(2017)”。因为 Daniel 后来重新思考了这篇文章,现在正在为 curl 写 Rust 后端:https://daniel.haxx.se/blog/2020/10/09/rust-in-curl-with-hyper/
erickt查看英文原文
Could (2017) be added to the title? Since then, Daniel has since rethought this post and is now writing a Rust backend for curl: https://daniel.haxx.se/blog/2020/10/09/rust-in-curl-with-hyper/
历次讨论
同类还值得读
开源应用架构
The Architecture of Open Source Applications
《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。
编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选编程语言简史:简短、不完整且多半错误
A Brief, Incomplete, and Mostly Wrong History of Programming Languages
一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。
编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.comSQLite 是如何测试的
How SQLite is tested
SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…
编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选高级编程语言(2009)
Advanced programming languages (2009)
Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…
编程与软件工程上首页 8 次 · 2009–2022matt.might.net我的 Forth 与栈机器经历
Yosefk - My history with Forth & stack machines
作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。
编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选