c语言 - 代码限定 - libc qsort 中有符号值和无符号值之间的比较



在对安全至关重要的代码进行验证通过时,应该在嵌入式设备中执行 - 我看到了GCC和Clang发出的一些警告。警告很容易复制,因为所讨论的代码来自开源BSD LIBC:

$ wget https://raw.githubusercontent.com/freebsd/
freebsd/af3e10e5a78d3af8cef6088748978c6c612757f0/lib/libc/stdlib/qsort.c
$ gcc -c -Wall -Wsign-compare -DI_AM_QSORT_R -Wall qsort.c
qsort.c: In function 'qsort_r':
qsort.c:45:24: warning: comparison between signed and unsigned 
               integer expressions [-Wsign-compare]
#define MIN(a, b) ((a) < (b) ? a : b)
                        ^
qsort.c:186:6: note: in expansion of macro 'MIN'
  r = MIN(pd - pc, pn - pd - es);
      ^
qsort.c:45:34: warning: signed and unsigned type in conditional 
               expression [-Wsign-compare]
 #define MIN(a, b) ((a) < (b) ? a : b)
                                  ^
qsort.c:186:6: note: in expansion of macro 'MIN'
  r = MIN(pd - pc, pn - pd - es);

了解这些警告(从GCC和Clang发出)...

  • pdpcpn 是指
  • essize_t(即, unsigned

可以说,C可以充分表达签名实体和未签名实体之间比较的规则,因为不是上帝的爱[1]。

但是在这种情况下,qsort的BSD实现...

  • 减去两个指针的结果(具有签名类型,ptrdiff_t
  • 减去两个指针的结果,由 es降低 - 未签名。

为什么从ptrdiff_t一个(即签名的一个)中减去unsigned值会导致unsigned一个?这是您可以在上面引用的帖子中阅读的内容。可以说,对于单词大小的实体,signed OPERATOR unsigned的任何表达都会导致unsigned类型。

所以,要缩短长话短说,让海湾合作委员会和clang停止抱怨,必须从...

中更改这些线条
r = MIN(pd - pc, pn - pd - es);

to二:

r = MIN((unsigned)(pd - pc), pn - pd - es)

或:

r = MIN(pd - pc, (signed)(pn - pd - es));

问题是...什么是正确的补丁?

[1] "为什么不在c/c 中混合签名和无符号值?

显然我在这里一个人: - )

我对问题的回答来自一种非常简单的看东西的方式...

如果您在左侧应用未签名的铸件,然后重新编译,则对象文件不会更改(通过MD5总和进行了验证)。如果您改为施放右侧(要签名),则对象文件确实会更改 - 这意味着此更改偏离(至少在汇编级别 - 对于AMD64和SPARCS)与原始代码正在执行的操作。

简短答案:我继续铸造未签名(size_t)。这也是苹果似乎所做的(感谢指针,@alk)。

最新更新