A small program c causes "memory corruption",

I wrote a small program to print a complete permutation of a given set of alphabets. It works well when the set was less than 26, and failed for 26 or more. emergency log said:

*** Error in `./a.out': malloc(): memory corruption (fast): 0x0000000000cd56a0 *** 

The debugging hours worked, still do not know the reason.

PS: if I delete these 2 lines that will release tmp_done and tmp_todo, this will not work, but the result still looks strange, unexpected "!" occurs as a result.

 abcdefghijklmnopqtyuzxwr!sv abcdefghijklmnopqtyuzxwr!vs abcdefghijklmnopqtyuzxws!rv abcdefghijklmnopqtyuzxws!vr abcdefghijklmnopqtyuzxwv!rs 

Here is the source:

 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <memory.h> static void __permutation1(char * done, char * todo) { int i = 0; for(i=0; i<strlen(todo); i++) { if (1 == strlen(todo)) { printf("%s%s\n", done, todo); break; } char * tmp_todo = strdup(todo); char * tmp_done = strdup(done); char s[2] = {todo[i], 0}; strcat(tmp_done, s); memmove(tmp_todo+i, tmp_todo+i+1, strlen(tmp_todo)-i); // null termincated! __permutation1(tmp_done, tmp_todo); free((void*)tmp_done); # if i remove these 2 lines, it won't crash free((void*)tmp_todo); # if i remove these 2 lines, it won't crash } } void permutation1(char * str) { char * done = (char *)calloc(1, strlen(str)+1); char * todo = strdup(str); __permutation1(done, todo); free((void *)done); free((void *)todo); } int main(int argc, char const *argv[]) { permutation1("abcdefghijklmnopqrstuvwxyz"); return 0; } 

Here's the full crash log:

 [ xxxx@xxxx ]$ ./a.out abcdefghijklmnopqrstuvwx!yz abcdefghijklmnopqrstuvwx!zy *** Error in `./a.out': malloc(): memory corruption (fast): 0x0000000000cd56a0 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x7ada4)[0x7f4397621da4] /lib64/libc.so.6(+0x7ddc7)[0x7f4397624dc7] /lib64/libc.so.6(__libc_malloc+0x4c)[0x7f4397626fbc] /lib64/libc.so.6(__strdup+0x1a)[0x7f439762d88a] ./a.out[0x40078e] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x40081f] ./a.out[0x4008ad] ./a.out[0x4008ea] /lib64/libc.so.6(__libc_start_main+0xf5)[0x7f43975c8b35] ./a.out[0x400669] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 fd:02 268801967 /home/shello/workspace/oss/pincode/c_cpp/interview/a. out 00600000-00601000 r--p 00000000 fd:02 268801967 /home/shello/workspace/oss/pincode/c_cpp/interview/a. out 00601000-00602000 rw-p 00001000 fd:02 268801967 /home/shello/workspace/oss/pincode/c_cpp/interview/a. out 00cd5000-00cf6000 rw-p 00000000 00:00 0 [heap] 7f4390000000-7f4390021000 rw-p 00000000 00:00 0 7f4390021000-7f4394000000 ---p 00000000 00:00 0 7f4397391000-7f43973a6000 r-xp 00000000 fd:01 201330443 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f43973a6000-7f43975a5000 ---p 00015000 fd:01 201330443 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f43975a5000-7f43975a6000 r--p 00014000 fd:01 201330443 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f43975a6000-7f43975a7000 rw-p 00015000 fd:01 201330443 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 7f43975a7000-7f439775d000 r-xp 00000000 fd:01 201333865 /usr/lib64/libc-2.17.so 7f439775d000-7f439795d000 ---p 001b6000 fd:01 201333865 /usr/lib64/libc-2.17.so 7f439795d000-7f4397961000 r--p 001b6000 fd:01 201333865 /usr/lib64/libc-2.17.so 7f4397961000-7f4397963000 rw-p 001ba000 fd:01 201333865 /usr/lib64/libc-2.17.so 7f4397963000-7f4397968000 rw-p 00000000 00:00 0 7f4397968000-7f4397988000 r-xp 00000000 fd:01 201327199 /usr/lib64/ld-2.17.so 7f4397b66000-7f4397b69000 rw-p 00000000 00:00 0 7f4397b84000-7f4397b87000 rw-p 00000000 00:00 0 7f4397b87000-7f4397b88000 r--p 0001f000 fd:01 201327199 /usr/lib64/ld-2.17.so 7f4397b88000-7f4397b89000 rw-p 00020000 fd:01 201327199 /usr/lib64/ld-2.17.so 7f4397b89000-7f4397b8a000 rw-p 00000000 00:00 0 7ffca2b33000-7ffca2b54000 rw-p 00000000 00:00 0 [stack] 7ffca2bb3000-7ffca2bb5000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Aborted (core dumped) 
+5
source share
2 answers

strdup() problem. First you have:

 char * done = (char *)calloc(1, strlen(str)+1); 

This selects a string in your case of 27 bytes and sets them all to a null character, so you have \0\0\0...\0\0\0 .

Next you will do:

 char * tmp_done = strdup(done); 

This effectively reduces:

 char * tmp_done = malloc(strlen(done)+1); strcpy(tmp_done, done); 

Unfortunately, the strlen characters from 27 \0 are zero, not 27, so you get a single-byte memory allocation, and from there everything goes down.

+10
source

I spent 2 hours on __permutation1 ...

If you are looking for a way to find such problems faster, you can use clang or gcc ASan (address sanitizer).

Some of the results below may seem a bit noisy / foreign. But you can finally detect when ASan first detects the problem: strdup() is called on line # 18. So you don’t have to wonder why the free() message reports an error much later. If your computer does not have clang or gcc , you can download and install it .

 $ clang -g -fsanitize=address,undefined perm.c $ ./a.out ================================================================= ==15988==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff1 at pc 0x0000004a25e2 bp 0x7ffc33576490 sp 0x7ffc33575c18 WRITE of size 2 at 0x60200000eff1 thread T0 #0 0x4a25e1 in strcat /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:501:5 #1 0x4e4d86 in __permutation1 /home/brian/tmp/go2_/perm.c:21:9 #2 0x4e4978 in permutation1 /home/brian/tmp/go2_/perm.c:35:5 #3 0x4e4f47 in main /home/brian/tmp/go2_/perm.c:43:5 #4 0x7f82ec48582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #5 0x418dc8 in _start (/home/brian/tmp/go2_/a.out+0x418dc8) 0x60200000eff1 is located 0 bytes to the right of 1-byte region [0x60200000eff0,0x60200000eff1) allocated by thread T0 here: #0 0x4a3ea6 in strdup /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:562:3 #1 0x4e4bf1 in __permutation1 /home/brian/tmp/go2_/perm.c:18:27 #2 0x4e4978 in permutation1 /home/brian/tmp/go2_/perm.c:35:5 #3 0x4e4f47 in main /home/brian/tmp/go2_/perm.c:43:5 #4 0x7f82ec48582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) SUMMARY: AddressSanitizer: heap-buffer-overflow /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:501:5 in strcat Shadow bytes around the buggy address: 0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[01]fa 0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==15988==ABORTING 
+2
source

Source: https://habr.com/ru/post/1269352/


All Articles