开发者生态
morning
卑鄙的C大赛
2026-07-02
1 阅读
约4分钟阅读
ccabraldev
字号:
Underhanded C 大赛 守法好人的官方纯真网页 关于常见问题解答 往年 今年 名人堂 2.3.16 2015 年 Underhanded C 大赛结果 由 XcottCraver 于上午 9:55 发布 我们已对所有提交的作品进行了评判,并很高兴地宣布 2015 年 Underhanded C 大赛的亚军和获胜者。今年我们收到了 40 多份参赛作品,而且质量都很高。结果,我们的亚军名单相当长。如果您想跳过,我将在下面提供锚链接。 今年的挑战(详情如下)是核核查中的一个现实问题,由核威胁倡议 (http://www.nti.org/) 赞助并与其合作设计,该倡议是一个致力于减少核武器、化学武器和生物武器威胁的非盈利、无党派组织。我们希望这强调了在此类应用程序的安全软件开发中需要谨慎和严格,更不用说新的研究。最后,我们将在 2 月 9 日下周二下午 1:00 举办现场 Reddit AMA(“Ask Me Anything”,面向像我一样仍然使用录音机和 Commodore PET CBM 的人)。我们稍后会发布更多细节,但如果您对 Underhanded C、比赛或问题有疑问,这将是一个很好的提问机会。挑战问题回顾(较早的帖子) Nan bug 提交 关于现实主义的说明 亚军 获胜者 NaN 中毒攻击概述 许多提交的内容(大约三分之一!)使用了相同的技巧,每个程序员都应该意识到这一点。由于某些具有未定义结果的计算的结果,浮点变量可以设置为 NaN(“不是数字”)——例如,计算 sqrt(-1.0) 或 0/0。 NaN 值具有以下属性: 涉及 NaN 输入的计算通常会得到 NaN 结果;与 NaN 的比较将评估为 false。第二个事实是许多编程语言的语法限制:只有某些数据类型可以保存未定义的值。从数学上来说,如果 x 未定义,那么我们应该期望 y = ((int) x) 或 y = (x >= 5) 也未定义;但整数和逻辑变量不能是未定义的,并且这些表达式必须计算出某个值。无论如何,这表明了 NaN 中毒技巧:如果向程序提供了一些奇怪的输入,找到一种引入 NaN 的方法;允许 NaN 传播到最终的比较统计量;将其与阈值进行比较,以便错误比较(因此 NaN 值)返回 true,使用如下行: return (detection_score < Threshold ? 0 : 1);那么这有多聪明呢?这取决于你如何引入 NaN。有些条目只是假设东道国可以将一个病毒走私到输入中,我们认为这是不可行的攻击。某些条目计算的测试统计数据需要除法、平方根或对数,因此不寻常的输入会产生 NaN 结果。这是 Peter Eastman 提交的一个很好的例子: int match(double* test, double* reference, int bins, double Threshold) { double* testMinusBaseline = (double*) malloc(bins*sizeof(double));双* ReferenceMinusBaseline = (双*) malloc(bins*sizeof(double)); for (int i = 0; i < bins; i++) { testMinusBaseline[i] = fmax(0.0, test[i]-baseline[i]); referenceMinusBaseline[i] = fmax(0.0,reference[i]-baseline[i]); } [等等等等] // 计算测试与参考的皮尔逊相关性。双相关 = 0.0; for (int i = 0; i < bins; i++) 相关性 += (testMinusBaseline[i]-meanTest) *(referenceMinusBaseline[i]-meanReference);相关性 /= stddevTest*stddevReference;返回(相关性<阈值?0:1);减去基线 [] 数组的代码将所有负值钳位为零,因此,如果可以以某种方式设计测试弹头以使 test[i]<=baseline[i],则相关性将显示为 0/0 == NaN。 NaN 中毒的一个问题是许多程序员对于除以零持谨慎态度。对于 C 程序员来说,查看没有零检查的浮点除法有点像看一个小孩玩牛排刀。此类疏忽可能会引起审查的注意。一些提交者通过引入不起作用的零检查来解决这个问题,即 Michael Dunphy 的这篇文章: /* dot: x 和 y 之间的点积 */ static inline double dot(double *x, double *y, int n, unsigned int err) { double dp = 0; } for (int i = 0; i < n; i++) dp += x[i]*y[i];易失性双 tmp = dp; // 检查零、NaN 或+/-无穷大 if ( (dp == 0) || (tmp != dp) || ((tmp == dp) && (tmp - dp) != 0) ) err = 1;返回dp; /* match: 计算余弦相似度,如果>=threshold则返回1,否则返回0 */ int match(double *test, double *reference, int bins, double Threshold) { unsigned int err = 0; double magr = sqrt(dot(参考、参考、bins、错误));双 magt = sqrt(dot(测试、测试、bins、错误));双 r = 点(测试、参考、垃圾箱、错误)/(magt*magr); // 余弦相似度 if ( err > 0 ) return 0; // 测试因任何无效数据而失败
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱