本文共 1073 字,大约阅读时间需要 3 分钟。
本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第2章,建议14-1,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
在C语言中,如果在未知的有符号数上执行位操作,很可能会导致缓冲区溢出,从而在某些情况下导致攻击者执行任意代码,同时,还可能会出现出乎意料的行为或编译器定义的行为。
下面来看一个简单的示例,如代码清单2-3所示。代码清单2-3 在未知的有符号数上执行位操作示例#includeint main (void){ int x=0; int y=0x80000000; char buf[sizeof("128")]; x=sprintf(buf,"%u",y>>24); if(x==-1||x>=sizeof(buf)) { // 错误处理 } printf(buf); return 0;}
在代码清单2-3中,y>>24的执行结果为4294967168,而sizeof(buf)的结果为4。当我们将y>>24的结果值转换为字符串“4294967168”时,超出了buf范围,所以结果值无法完全存储在buf中。因此,在执行语句“x=sprintf(buf,"%u",y>>24)”时,sprintf方法在进行写操作时就会越过buf的边界,从而产生缓冲区溢出。
如果在编译器VC++中执行这段程序,将会产生如图2-4所示的错误报告。在C99中,要修正这样的错误,最好利用snprintf方法来代替sprintf方法。因为snprintf方法最多从源串中复制n-1个字符到目标串中,然后再从后面加一个0。因此,如果目标串的大小为n,将不会产生溢出。当然,如果将变量y声明成为无符号类型,那么这种缓冲区溢出错误将不会发生,如代码清单2-4所示。代码清单2-4 代码清单2-3的改进示例#includeint main (void){ int x=0; unsigned int y=0x80000000; char buf[sizeof("128")]; x=sprintf(buf,"%u",y>>24); if(x==-1||x>=sizeof(buf)) { // 错误处理 } printf(buf); return 0;}
转载地址:http://zdgma.baihongyu.com/