文章翻译:无双坏坏
信息来源:邪恶八进制信息安全团队(
www.eviloctal.com)
原文章连接:
http://groups.google.com/group/c ... ?tvc=2&hl=zh-CN 这在group上讨论的很激烈,翻译下大家看看: ),水平有限,错误难免 ,希望看官斧正
我们经常能在代码中发现隐藏着的,且完全无用的假设. 下列各项倚靠一个特别的例子, 假设在C语言中这个单词还必须打上括号 ,假设(assumptions),当然,这个假设由指断言(ASSERT)来假设
我希望借这个小论文,鼓励人们检查他们的代码中那些被制造出的隐藏的假定. 与往常一样,现在处理C的参考标准是国际标准化组织的标准. 它的文字版本,可以找到的有PDF格式的,您可以搜寻关键字n869和n1124. 后者没有全文版,而是更新.
/* Making fatal hidden assumptions */
/* Paul Hsiehs version of strlen.
http://www.azillionmonkeys.com/qed/asmexample.html
一些鬼祟的隐藏假定这里:
1. p= s- 1 是有效的。 不保证。 粗心的编码。
2. 演员阵容 (int) p 是意义深长的。 不保证。
3. 2 年代补足物算术的使用。
4. ints 没有圈套表现或隐藏的一点点。
5. 4 ==sizeof(int) 和 &8== CHAR_BIT.
6. size_t 实际上是 int 。
7. sizeof(int) 是 2 的力量。
8. int 对准仰赖被对准零位的一点点领域。
既然 strlen 正常地被系统供应,系统设计者能几乎保证项目 1 。 否则这不是手提式。 项目 1 或许被适当的密码改组打避免起始 p= s- 1. 这是一个 , 举例来说的严重蠕虫,能引起在许多系统上的 segfaults。 当 s 价值为 0, 而且是有意义的时候 , 它很有可能要出问题。
He fails to make the valid assumption: 1 == sizeof(char).
*/
#define hasNulByte(x) ((x - 0x01010101) & ~x & 0x80808080)
#define SW (sizeof (int) / sizeof (char))
int xstrlen (const char *s) {
const char *p; /* 5 */
int d;
p = s - 1;
do {
p++; /* 10 */
if ((((int) p) & (SW - 1)) == 0) {
do {
d = *((int *) p);
p += SW;
} while (!hasNulByte (d)); /* 15 */
p -= SW;
}
} while (*p != 0);
return p - s;
} /* 20 */
从第 1 行开始! 常数似乎需要 sizeof(int) 是 4, 而且 CHAR_BIT 精确地 8. 我没有太接近地真的看, 和它是可能的那 ~x 术语,考虑到较大的 sizeof(int) ,但是没考虑到较大的 CHAR_BIT. 一较进一步隐藏的假定是没有 int 的表现圈套价值。可疑的 sizeof(int)什么时候那 4. 在最少,它将会压迫晋级渴望,哪一将会严重地影响速度
这是在 int 里面发现零位元组的灵敏和快的方法, 提供先决条件被碰到。当它是有效的时候 , 它就没有什么问题,在第 2 行中有 sizeof(零碎工作) 的困惑使用,藉着定义是 1 。 正直的服务使事实阴暗 SW 实际上是 sizeof(int) 比较迟的。没有隐藏的假定被定义在这里,但是是帮助隐藏较迟的假定用法
第 4 行. 因为这预计代替系统 strlen() 功能,它会有利的使用适当的签字作为功能。 在特别的 strlen 中归还 size_t 而不是 int 。 size_t 总是被不签署。
在第 8 行中我们看到 biggie 。 标准是在一个物体下面明确地不保证指针的行动。 这一份陈述的唯一真正的目的要为第 10 行的起始增量偿还。可能被密码的再排列排斥,然后将会了解常式假定是有效的功能。 这是密码的唯一真正的错误
第 11 行中我们有一些隐藏的假定。 第一是 int 的指针演员阵容是有效的。 这从不被保证。 一个指针可能比 int 更加大, 而且可能有植入的所有非一样的完整事物数据,像是片段遗传素质。 如果 sizeof(int) 比 4 有效性更少甚至更没有可能。
要发现如果指针合适地被 int 排列。 由于一点点的 SW-1, 被隐藏的是 sizeof(int)-1. 如果确认 sizeof(int) 是被隐藏<3 或任何其他的非 poweroftwo>这就不是很有用。 除此之外,它承担一个被排列的指针让那些一点点零的。 虽然这最后的可能是在系统中,它仍然是一项假定。虽然属于系统设计者使用,但是使用者密码不是。
第 13 行再一次使用对 int 的指针未获保证的演员阵容。这使第 15 行的已经可疑的句集 hasNulByte 能够再次使用。
如果所有的这些假定是正确的, 第 19 行最后计算一种指针不同。 ( 是有效, 和类型 size_t 或 ssize_t, 但是将会合适的进入 size_t 之内) 进入 int 之内这做被隐藏的演员阵容, 会引起不明确的或如果价值超过将会进入 int 之内适合的东西 , 定义了行为。成功以后,自定义如 size_t 的回行类型,这一个也是不必要的。我没有提到 2 年代的假定补足物算术, 我相信正在 hasNulByte 句集中。
鬼祟的事物看起来是密码起先显得琐细正确。 这是 Heisenbugs 组成的东西。如果我们知道那些隐藏的假定,那么这样的密码使用就是安全的。
[1] The draft C standards can be found at:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/