Search code examples
cmallocrealloc

Confusion with realloc in C language


I have a code like this :

void **array = (void**)malloc(sizeof(void*)*4);
array[0] = (void *)"Hello";
array[1] = (void *)"World";
array[2] = (void *)"My";
array[3] = (void *)"Example";
array = (void **)realloc(array,sizeof(void*)*3);

printf("%s\n",(char*)array[3]);
free(array);

Even though I reallocate the memory it is printing Example

Where am I wrong?


Solution

  • See this:

    $ cat test.cpp 
    #include <stdlib.h>
    #include <stdio.h>
    
    int main() {
            void **array = (void**)malloc(sizeof(void*)*4);
            array[0] = (void *)"Hello";
            array[1] = (void *)"World";
            array[2] = (void *)"My";
            array[3] = (void *)"Example";
            array = (void **)realloc(array,sizeof(void*)*3);
    
            printf("%s\n",(char*)array[3]);
            free(array);
    }
    $ g++ test.cpp -o a -fsanitize=address                                                                                    
    $ ./a                                                                                                                     
    =================================================================                                                                                           
    ==11051== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60060000efc8 at pc 0x400a3f bp 0x7fffafc0bf40 sp 0x7fffafc0bf38                        
    READ of size 8 at 0x60060000efc8 thread T0                                                                                                                  
        #0 0x400a3e (/tmp/a+0x400a3e)                                                                                                                           
        #1 0x7fe6d321aec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)                                                                                          
        #2 0x400868 (/tmp/a+0x400868)                                                                                                                           
    0x60060000efc8 is located 0 bytes to the right of 24-byte region [0x60060000efb0,0x60060000efc8)                                                            
    allocated by thread T0 here:                                                                                                                                
        #0 0x7fe6d35d355f (/usr/lib/x86_64-linux-gnu/libasan.so.0.0.0+0x1555f)                                                                                  
        #1 0x400a12 (/tmp/a+0x400a12)                                                                                                                           
        #2 0x7fe6d321aec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)                                                                                          
    Shadow bytes around the buggy address:                                                                                                                      
      0x0c013fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
    =>0x0c013fff9df0: fa fa fa fa fa fa 00 00 00[fa]fa fa fd fd fd fd                                                                                           
      0x0c013fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                           
      0x0c013fff9e40: 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 righ 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
      ASan internal:         fe
    ==11051== ABORTING
    

    So, actually these bytes of memory were freed, but you are just lucky (or not) that these bytes wasn't reused for anything else.

    The realloc call changes size of an allocated memory. In your case you lowered a size, so the system just cut off the bytes in contiguous region that were allocated previously. I.e. your pointer to the text is still there, just the system didn't yet reused these bytes for another thing. In my example I compiled your code with debug option -fsanitize=address that checks for buffer overflow and an usage of a freed memory, and terminates an app with an error message if something alike happened — and it happens in your case.