
SQLite 是目前被运行的最为广泛(没有之一)的数据库引擎,几乎每一个 iOS App / Android App / Chrome / Firefox 都带了一个 SQLite 的引擎用以解决自身的关系型数据存取。CovenantSQL 也是使用 SQLite3 作为单机的存储引擎。我粗略的统计了一下我电脑里的 SQLite3 相关的文件就多达 3701
个。
$ locate sqlite3 | wc -l
3701
SQLite 应该是目前大型开源项目里,测试代码 / 功能代码
比例最大的,也因此达到了惊人的 100% 行覆盖率。
关于 SQLite3 是如何测试的: https://www. sqlite.org/testing.html
但即使如此也难免有严重 bug 产生,2018 年 11 月,腾讯安全 Blade Team 发现了一个 SQLite 3.25.3 版本的 RCE(Remote Code Execution)漏洞:
- 2018年11月1日 报告漏洞给 Google
- 2018年11月1日 漏洞由谷歌确认
- 2018年11月3日 漏洞通知到 SQLite
- 2018年11月5日 SQLite 发布 3.25.3,修复漏洞
- 2018年11月28日 谷歌修复漏洞
- 2018年12月1日 SQLite 发布 3.26.0,引入纵深防御机制
- 2018年12月3日 谷歌发布正式版 71.0.3578.80
- 2018年12月20日 谷歌确定奖金为 $10337
- 2018年12月21日 CVE编号确定为 CVE-2018-20346、CVE-2018-20505、CVE-2018-20506
事后,SQLite 的作者 Dr. D. Richard Hipp 在 Hacker News 讨论了自己对于 SQLite 测试相关的看法,下面由小编翻译并分享给大家:
Dr. D. Richard Hipp:
关于测试覆盖度,最常见的标准称为 “modified condition/decison coverage” 或 MC / DC。在像 C语言中,MC / DC 和分支覆盖虽然不完全相同,但非常接近。
达成 100% MC / DC 并不能证明你总能得到正确的答案。这意味着你的测试非常完善,以至于你设法让每个机器代码分支至少在两个方向上进行。这是一个高标准,很难实现。这并不意味着该软件是完美的。
但它确实有帮助,而且很大。当我年轻的时候,我曾经认为我可以完美无瑕的代码。然后我写了 SQLite,它被许多应用程序拾起并使用。当你的代码在数十亿台设备上的数百万应用程序中运行时,会出现多少问题。
SQLite 获得源源不断的错误报告。然后我花了 10个月(2008-09-25 到 2009-07-25)为 SQLite 编写了 100% 的 MC / DC 测试。之后,错误报告的数量减慢到了涓涓细流。还有 bug。但是 bug 的数量大大减少了。100% MC / DC 最初是在 2009-07-25 达成的,但是工作并没有就此结束。我花费了大部分开发时间来添加和增强测试用例,以跟上可交付的 SQLite 代码的变化。
100%MC / DC只是一个阈值,一个很高的阈值,一个易于测量且难以作弊的门槛。但它只是我们说“足够”的门槛。你可以轻松选择不同的阈值,例如 100% 行覆盖率。阈值越高,错误越少。但只要项目足够的大,它总会有错误。
我的经验是,你最终必须编写的奇怪测试只是为了让一些不起眼的分支以某种方式走向最终在系统中完全不相关的部分并发现问题。 100%MC / DC 的主要好处之一并不是每个分支都经过测试,而是你必须编写如此多的测试:随机的、古怪的、错综复杂的……然后你就可以发现问题,并修复了许多你从未想过的问题。
100%MC / DC 的另一大优势是,一旦它们到位,你可以在代码中的任何地方进行任何更改,如果测试仍然通过,你就会非常自信地没有破坏任何东西。这使我们能够以相对较少的逐行检查,更快地演进 SQLite 代码。
100%MC / DC 的另一个优点是你真的在测试编译的机器代码,而不是源代码。所以你不用担心编译器错误。UB(Undefined Behavior)是 C 的一个大问题。即使官方的 C 语言规范不强制要求没有 UB,我们仍然避免使用 UB。据我们所知,SQLite目前不包含任何 UB,这也就给了我们信心编译器的结果一定是我们想要的结果。如果你发现了 SQLite 的 UB,请一定告诉我们 :-)
作者呓语
年轻的时候写代码,心底里总是有种幼稚的自信,我觉得这段代码肯定没问题。夜路走的多了,总会遇到鬼。就会让你变得「机械唯物主义」更加相信的是数字 & 工具。