roger 发表于 2020-9-2 09:29:04

整数溢出

1.原理每种数据类型都有各自的大小范围add 0x7fff, 1 == 0x8000,这种上界溢出对无符号整型就没有影响,但是在有符号短整型中,0x7fff 表示的是 32767,但是 0x8000 表示的是 -32768,用数学表达式来表示就是在有符号短整型中 32767+1 == -32768比如上面的有符号型加法的汇编代码是 add eax, 1,因为 eax=0xffff,所以 add eax, 1 == 0x10000,但是无符号的汇编代码是对内存进行加法运算 add word ptr , 1 == 0x0000。再从数字层面看看这种溢出的结果,在有符号短整型中,0xffff==-1,-1 + 1 == 0,从有符号看这种计算没问题。但是在无符号短整型中,0xffff == 65535, 65535 + 1 == 0。2.例子#include
  int main(void)
  {
  int len;
  int data_len;
  int header_len;
  char *buf;
  header_len = 0x10;
  scanf("%uld", &data_len);
  len = data_len+header_len
  buf = malloc(len);
  read(0, buf, data_len);
  return 0;
  }
只申请 0x20 大小(0xf+0x10+0x1)的堆(实测0x21,可能是对齐之类的原因),但是却能输入 0xffffffff 长度的数据,从整型溢出到堆溢出
$ cat test3.c
  int main(void)
  {
  int len, l;
  char buf;
  scanf("%d", &len);
  if (len < 10) {
  l = read(0, buf, len);
  *(buf+l) = 0;
  puts(buf);
  } else
  printf("Please len < 10");
  }
  $ gcc test3.c
  $ ./a.out
  -1
  aaaaaaaaaaaa
  aaaaaaaaaaaa
从表面上看,我们对变量 len 进行了限制,但是仔细思考可以发现,len 是有符号整型,所以 len 的长度可以为负数,但是在 read 函数中,第三个参数的类型是 size_t,该类型相当于 unsigned long int,属于无符号长整型

页: [1]
查看完整版本: 整数溢出