zoukankan      html  css  js  c++  java
  • 【Valgrind】How to check buffer overflow/underflow in 10 mins

    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.

    1 # To get a precise source code line number by valgrind report, 
    2 # It's better to build debug version, such as '-O0' for GCC. 

    Example 1: heap overflow

     1 // head_overflow.c
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <math.h>
     5 int main(int argc, char** argv)
     6 {
     7   int i;
     8   int *a = malloc(sizeof(int) * 10);
     9   if (!a) return -1; /*malloc failed*/
    10   // init
    11   for (i = 0; i < 11; i++)
    12   {
    13     a[i] = i;
    14   }
    15   // square
    16   for(i=0; i<10; i++)
    17   {
    18     a[i] *= a[i];
    19   }
    20   free(a);
    21   printf("I am finished.
    ");
    22   return 0;
    23 }

    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 ***
    ") 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

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 int main(int argc, char** argv)
     5 {
     6   int i;
     7   int *a = malloc(sizeof(int) * 10);
     8   if (!a) return -1; /*malloc failed*/
     9   // init
    10   for (i = 0; i < 10; i++)
    11   {
    12     a[i] = i;
    13   }
    14   // sum
    15   for(i=0; i<10; i++)
    16   {
    17     a[i] += a[i-1];
    18   }
    19   free(a);
    20   printf("I am finished.
    ");
    21   return 0;
    22 }

    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.

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 int main(int argc, char** argv)
     5 {
     6   int i;
     7   int a[10];
     8   // init
     9   a[-1] = -1;
    10   a[11] = 11;
    11   printf(" a[-1]= = %d, a[11] = %d
    ", a[-1], a[11]);
    12   printf("I am finished.
    ");
    13   return a[-1];
    14 }

    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.
    
    
  • 相关阅读:
    Lesson 九、Eclipse中打jar包并使用jar包
    Lesson 八、eclipse开发中常用的快捷键
    Lesson 七、关键字final和多态,抽象类和接口
    Lesson 六、Java中的继承
    Lesson 五、Java中代码块和静态代码块的用法
    Lesson 四、Java工具类帮助文档的制作和帮助文档的使用
    Lesson 三、匿名对象的理解和使用
    Lesson 二:java.util.Scanner的使用
    Lesson 一:Windows 常见DOS命令的使用以及Java语言的环境配置
    插件新增
  • 原文地址:https://www.cnblogs.com/xjsxjtu/p/4539028.html
Copyright © 2011-2022 走看看