整数运算
无符号乘法:C语言中的无符号乘法被定义为产生w位的值
补码乘法:,C语言中的有符号乘法是通过将2w位的乘积截断为w位的方式实现的。
我们认为对于无符号和补码乘法来说,乘法运算的位级表示都是一样的,机器可以用一种乘法指令来进行有符号和无符号整数的乘法。
XDR库中的安全漏洞
包含安全漏洞的代码与下面所示类似:
/*
* Illustration of code vulnerability similar to that found in
* Sun's XDR library.
*/
void* copy.elements(void *ele_src □ , int element, size_t ele_size) {
/*
* Allocate buffer for element objects, each of ele_size bytes
* and copy from locations designated by ele_src
*/ •
void *result = malloc (ele_cnt * ele_size);
if (result == NULL)
/* malloc failed */
return NULL;
void *next = result;
int i;
for (i = 0; i < element; i++) {
/* Copy object i to destination */
memcpy(next, ele_src[i], ele_size);
/* Move pointer to next memory region */
next += ele_size;
}
return result;
}
程序员用参ele_cnt等于1 048 577 (220+ 1)、 ele_size等 于4 096 (212)来调用这个函数。然后第10行上的乘法会溢出,导致只会分配4096个字节,而不 是装下这些数据所需要的4294 971 392个字节。从第16行开始的循环会试图复制所有的字节,超 越已分配的缓冲区的界限,因而破坏了其他的数据结构。这会导致程序崩清或者行为异常。
乘以常数:在大多数机器上,整数乘法指令相当慢,需要10个或者更多的时钟周期,我们会考虑乘以2的幂的情况,然后再概括成乘以任意常数。无论是无符号运算还是补码运算,乘以2的帯都可能会导致溢出。乘法比移位和加法的代价要大得多,许多C语言编译器试图以移位、加法和减法的组合来消除很多整数乘以常数的情况。
除以2的幂:在大多数机器上,整数除法要比整数乘法更慢——需要30个或者更多的时钟周期,整数除法总是舍入到零,移位总是舍入到零,这一结果与整数除法的规则一样。
算术右移不同位数,当需要进行舍人时,移位导致结果向下舍人,而不是像规则需要的那样向零舍入。例如,表达式-7/2应该得到-3,而不是-4。我们可以在移位之前“偏置”(biasing) 这个值,通过这种方法修正这种不合适的舍人,当y整除x时,我们得到k,否则,就得到k+1。
练习:
答案:
10100 10100 | [100]4 [100]-4 |
1110 1110 | [110]6 [110]-2 |
100100 100100 | [100]4 [100]-4 |
答案:
答案:
int tmult_ok(int x,int y){
int res1=x*y;
long long res2 = x*y;
return (int)res2==res1;
}
答案:
A.没有帮助,因为malloc的参数未改变,溢出的问题并没有根本解决。
B.当函数发生溢出时,则放弃缓冲区的分配。
long unsigned asize = ele_cnt*(long long unsigned)ele_size;
if(asize==(size_t)(ele_cnt*ele_size)) {
void *result = malloc(asize);
}else{
return nullptr;
}
答案:可以计算2n+1(n为0,1,2,3)或2n
答案:-(x<<m)
答案:
K | 移位 | 加法/减法 | 表达式 |
6 | 2 | 1 | (x<<2)+(x<<1) |
31 | 1 | 1 | x<<5-x |
-6 | 2 | 1 | (x<<1)-(x<<3) |
55 | 2 | 2 | (x<<7)-(x<<3)-x |
答案:如果n-m>1选B,n-m=1任选,否则选A
答案:
int div16(int x){
int bias=x>>31&0xf;
return (x+bias)>>4;
}
答案:M为31,N为8
答案:
A:×,设x等于-2147483 648 (TMinz2)。 那么,有x-1等于2147483647 (TMaxz2).
B:√,若(x&7)!=7不成立,当且仅当x&7==7,此时x<<29后为E0000000<0成立。
C:×,x为非零成立,x为0时成立,若不成立,当且仅当x*x的最高位为1,即x*x必须溢出且第32位上的值为1则不成立。
D:√,当x为负成立,当x为正,-x恒为负,当x=0时成立
E:×,当x为-232不成立
F:√,补码和无符号位级操作相同
G:√,-y=~y+1