以前的东西整理(3)

APR 3, 2014
第一次三明治课的收获

这次上课是讨论整数溢出,老师首先给出了第一段代码:

public class JavaTest{
public static void main(String[] args)
{
short a=(short)0xFFFF;
int b;
b=a;
System.out.printIn(b);
b=a & 0xFFFF;
System.out.printIn(b);
}
}

提问:两次输出的b是否相同?
然后分别分给3个班3段代码进行讨论.
示例代码(1):

void main(int argc, char* argv[])
{
unsigned short s;
int i;
char buf[80];
i=atoi(argv[1];
s=i;
if(s>=80)
return;
memcpy(buf,argv[2],i)
}

示例代码(2):

void CopyIntArray(int *array, int len)
{
int* myarray, i;
myarray = malloc(len * sizeof(int));
//堆空间申请失败
if(myarray == NULL)
return;
for(i=0; j<len; i++)
myarray[i] = array[i];
}

示例代码(3):

static char data[256];
int store_data(char *buf, int len)
{
if(len > 256)
return -1;
return memcpy(data, but, len);
}

注:以上讨论默认在32位机下
char:1byte
short:2bytes
int:4byte
Type conversion:
When assigning from a smaller-sized type to a larger, all of the source bytes are copied and the remaining upper bytes in the destination are filled using what is called sign extension–the sign bit is extended across the extra bytes.//即所占字节数少的数据类型转换为字节数较长的数据类型时,要进行标志位扩展,具体来说就是正数高位补0,负数高位补1。
由于这种转换符合数据在计算机中的表示形式(负数在计算机中的表示形式?),所以这种转换通常不会有副作用。
It is not so easy in the reverse direction: an integer can hold a value that is out of range for a short or char. An assignment like this will only copy the lower bytes and ignores the upper bytes.//字节数较长的数据类型转换为较短的数据类型时,只拷贝较低的几个字节,而较高的字节会被忽视。
这种转换通常会带来很多问题。下面与数据类型转换有关的问题通常都与它有关。

以上3段代码分别代表了3个类型的整数溢出问题:
代码(1):宽度溢出
可以看到,当用s=i;将4byte的i(int型)赋值给2byte的s(unsigned short型)时,只将i的低位的2byte赋值给了s,这段代码的问题就在于,用s(可以看作i的一部分)来进行溢出判断,却在memcpy中用i来确定拷贝的字节数,即用于检测的变量和用来实际操作的变量不一致,导致的漏洞。
错误举例:i=0000 0000|0000 0001|0000 0000|0000 0001 (左高右低)对应十进制数为2^16+1
则相应的s=0000 0000|0000 0001 对应的十进制数为1,显然没有超过buf数组的大小,于是调用memcpy函数从内存中拷贝数据,但是在memcpy中用的是i来确定要拷贝的字节数,显然i=2^16+1>80,即执行完memcpy之后从内存拷到buf中的字节数大于80,会发生溢出。

代码(2):运算溢出
void *malloc(size_t size);//size为字节数,所以要用len*sizeof(int),因为len是int型。
可以看到malloc的参数为unsigned int型,为4byte,而len(int型)也为4byte,sizeof(int)=4。
很明显可以看到:len*sizeof(int)的值有可能大于malloc的参数值的大小范围,导致数据高位丢失,造成实际申请的堆空间大小小于原本申请的大小,造成下面赋值的时候的溢出。
错误举例:len=2^30,则len*sizeof(int)=2^32+4,二进制表示为:1|0000 0000|0000 0000|0000 0000|0000 0100
当作为malloc的参数时,则变为了0000 0000|0000 0000|0000 0000|0000 0100,即只申请了4个字节的空间。
于是在赋值的时候,将2^30个字节的数组array[i] 赋值给其实只有4个字节的数组myarray[i],显然会发生溢出

代码(3):符号溢出
首先明确:static char data[256];是在数据段中。
这段代码的重点在于memcpy的参数的数据类型,len为unsigned int,这就带来了一个问题,前面if语句判断len的大小的时候,是将它当作有符号数处理的,后面memcpy中却是当作无符号数用的,也就是说存在两种可能执行到第二个return语句:
1.正常情况:len为正数且小于256
这种情况会得到正确的结果
2.非正常情况:len为负数,即最高位为0(负数在计算机中的表示方法)
这种情况下执行到memcpy时,len由于是被当作无符号数,即len>2^31,所以将buf中的len个字节长的值赋给只有256个字节长的data数组,很显然发生了溢出。(覆盖了哪个部分)

你可能感兴趣的:(以前的东西整理(3))