Search code examples
arrayscreturnruntime-errormalloc

Heap-buffer-overflow runtime error when returning a dynamically allocated block


I recently started programming in C and ran into the problem of returning an array. When i try to return the array i get a heap-buffer-overflow runtime error.

Here is my code

int* getConcatenation(int* nums, int numsSize, int* returnSize){
    int *ans;
    ans=(int*)malloc(numsSize * sizeof(int));
    for (int i=0;i<numsSize;i++){
        ans[i]=nums[i];
        ans[i+numsSize]=nums[i];
    }
    free(ans);
    return ans;
}

Error

AddressSanitizer: heap-buffer-overflow on address 0x60200000003c at pc 0x55780cb25d30 bp 0x7ffd83067af0 sp 0x7ffd83067ae0
WRITE of size 4 at 0x60200000003c thread T0
    #2 0x7fabeed390b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x60200000003c is located 0 bytes to the right of 12-byte region [0x602000000030,0x60200000003c)
allocated by thread T0 here:
    #0 0x7fabef97ebc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #3 0x7fabeed390b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 04 fa fa 00[04]fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Shadow gap:              cc
==44==ABORTING

Changed code:

This is my code now but it still doesn't work

int* getConcatenation(int* nums,
                      int numsSize, 
                      int* returnSize)
{
    int *ans;
    ans=malloc(2*numsSize * sizeof(int));
    for (int i=0;i<numsSize;i++)
    {
        ans[i]=nums[i];
        ans[i+numsSize]=nums[i];
    }

    return ans;
}

Solution

  • The access:

    ans[i+numsSize]=nums[i];
    

    is way beyond the bounds of the allocated space. You would need;

    ans = malloc(2 * numsSize * sizeof(int))
    

    You can return ans. What you cannot do is access the memory it points to because you returned it to the heap with free(). That makes it available for reuse.

    Even if the free() were removed, it is an ill-advised pattern in most cases in any event. By allocating memory inside a function, you would be relying on the caller knowing that the memory must be free'd. It is better generally to have the allocation in the same scope as the release (as you have done, but in the wrong scope). A more idiomatic pattern is to have the caller provide the memory and pass a pointer into the function. That way the memory need not even be dynamically allocated, it is in the control of the caller.

    malloc() returns a void* it need not be cast and is poor practice to do so.