码迷,mamicode.com
首页 > 其他好文 > 详细

【Valgrind】How to check buffer overflow/underflow in 10 mins

时间:2015-05-29 19:58:32      阅读:442      评论:0      收藏:0      [点我收藏+]

标签:

Introduction

Buffer overflow/underflow frequently happens when we did something wrong with the array index, no matter the array is heap or stack, no matter you are reading the memory or writing the memory.

Example 1: heap overflow

// head_overflow.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char** argv)
{
  int i;
  int *a = malloc(sizeof(int) * 10);
  if (!a) return -1; /*malloc failed*/
  // init
  for (i = 0; i < 11; i++)
  {
    a[i] = i;
  }
  // square
  for(i=0; i<10; i++)
  {
    a[i] *= a[i];
  }
  free(a);
  printf("I am finished.\n");
  return 0;
}

Let‘s build and run this file:

$ gcc -O3 -g -o heap_overflow heap_overflow.c
$ ./heap_overflow
*** Error in `./heap_overflow‘: free(): invalid next size (fast): 0x0000000001653010 ***
Aborted (core dumped)

Oops, Aborted while invoking free(). What‘s wrong?? Let‘s try gdb:

$ gdb ./heap_overflow
(gdb) r
Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_overflow
*** Error in `/home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_overflow‘: free(): invalid next size (fast): 0x0000000000602010 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7a4af79 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) 
(gdb) bt
#0  0x00007ffff7a4af79 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff7a4e388 in __GI_abort () at abort.c:89
#2  0x00007ffff7a881d4 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff7b96a10 "*** Error in `%s‘: %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff7a944ae in malloc_printerr (ptr=<optimized out>, str=0x7ffff7b96bb0 "free(): invalid next size (fast)", action=1) at malloc.c:4996
#4  _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3840
#5  0x000000000040062c in main (argc=<optimized out>, argv=<optimized out>) at heap_overflow.c:21
(gdb)

We still can only get the same err msg that crach in free(), which is line 21. But if we try valgrind:

$ valgrind ./heap_overflow
==31634== Memcheck, a memory error detector
==31634== Copyright (C) 2002-2013, and GNU GPL‘d, by Julian Seward et al.
==31634== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==31634== Command: ./heap_overflow
==31634==
==31634== Invalid write of size 4
==31634==    at 0x40053C: main (heap_overflow.c:14)
==31634==  Address 0x51fd068 is 0 bytes after a block of size 40 alloc‘d
==31634==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==31634==    by 0x4004DD: main (heap_overflow.c:8)
==31634==
I am finished.
==31634==
==31634== HEAP SUMMARY:
==31634==     in use at exit: 0 bytes in 0 blocks
==31634==   total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==31634==
==31634== All heap blocks were freed -- no leaks are possible
==31634==
==31634== For counts of detected and suppressed errors, rerun with: -v
==31634== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Valgrind tells exactly where is the problem:

  • Invalid write of size 4 at 0x40053C: main (heap_overflow.c:14)

 

Example 2: heap underflow

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char** argv)
{
  int i;
  int *a = malloc(sizeof(int) * 10);
  if (!a) return -1; /*malloc failed*/
  // init
  for (i = 0; i < 10; i++)
  {
    a[i] = i;
  }
  // sum
  for(i=0; i<10; i++)
  {
    a[i] += a[i-1];
  }
  free(a);
  printf("I am finished.\n");
  return 0;
}

Also build and run:

$ gcc -O3 -g -o heap_underflow heap_underflow.c
$ ./heap_underflow
I am finished.

Oh my GOD, it‘s finished. It means everything seems OK.

Really?

Let‘s try gdb:

$ gdb ./heap_underflow
(gdb) r
Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/heap_underflow
I am finished.
[Inferior 1 (process 32307) exited normally]
(gdb) bt
No stack.
(gdb)

Everything seems to be OK. Let‘s try Valgrind:

$ valgrind ./heap_underflow
==32275== Memcheck, a memory error detector
==32275== Copyright (C) 2002-2013, and GNU GPL‘d, by Julian Seward et al.
==32275== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==32275== Command: ./heap_underflow
==32275==
==32275== Invalid read of size 4
==32275==    at 0x4004E3: main (heap_underflow.c:19)
==32275==  Address 0x51fd03c is 4 bytes before a block of size 40 alloc‘d
==32275==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32275==    by 0x4004DD: main (heap_underflow.c:8)
==32275==
I am finished.
==32275==
==32275== HEAP SUMMARY:
==32275==     in use at exit: 0 bytes in 0 blocks
==32275==   total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==32275==
==32275== All heap blocks were freed -- no leaks are possible
==32275==
==32275== For counts of detected and suppressed errors, rerun with: -v
==32275== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Ooops, we find an error here:

  • Invalid read of size 4 at 0x4004E3: main (heap_underflow.c:19)

That‘s because we read data from a[-1] in line 19 !!

OS and gdb either didn‘t find this error, while Valgrind check it out.

Example 3: Stack overflow/underflow, none of OS/GDB/Valgrind realize the issue

It‘s weird that no matter OS/GDB/Valgrind, they cannot realize these issues.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char** argv)
{
  int i;
  int a[10];
  // init
  a[-1] = -1;
  a[11] = 11;
  printf(" a[-1]= = %d, a[11] = %d\n", a[-1], a[11]);
  printf("I am finished.\n");
  return a[-1];
}

build and run:

$ gcc -O0 -g -o stack_overflow stack_overflow.c
$ ./stack_overflow
 a[-1]= = -1, a[11] = 11
I am finished.

$ valgrind ./stack_overflow
==3705== Memcheck, a memory error detector
==3705== Copyright (C) 2002-2013, and GNU GPL‘d, by Julian Seward et al.
==3705== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==3705== Command: ./stack_overflow
==3705==
 a[-1]= = -1, a[11] = 11
I am finished.
==3705==
==3705== HEAP SUMMARY:
==3705==     in use at exit: 0 bytes in 0 blocks
==3705==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3705==
==3705== All heap blocks were freed -- no leaks are possible
==3705==
==3705== For counts of detected and suppressed errors, rerun with: -v
==3705== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

$ gdb ./stack_overflow
(gdb) r
Starting program: /home/jxion/jp4/depot/lechin/users/jxion/test_toys/test_valgrind/stack_overflow
 a[-1]= = -1, a[11] = 11
I am finished.
[Inferior 1 (process 3714) exited with code 0377]
(gdb) bt
No stack.

【Valgrind】How to check buffer overflow/underflow in 10 mins

标签:

原文地址:http://www.cnblogs.com/xjsxjtu/p/4539028.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!