andrei-markeev / ts2c

Convert Javascript/TypeScript to C
ISC License
1.26k stars 95 forks source link

Memory allocation bug #74

Open jarble opened 4 years ago

jarble commented 4 years ago

When I compile this JavaScript program to C, it prints 0 instead of 1. This appears to be due to a memory allocation bug, where the obj variable is freed before returning from the function:

function return_from_obj(){
  let obj = {key:1};
  return obj.key;
}

console.log(return_from_obj());

This is the compiler's output:

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef short int16_t;

struct obj_t {
    int16_t key;
};

int16_t return_from_obj()
{
    struct obj_t * obj;
    obj = malloc(sizeof(*obj));
    assert(obj != NULL);
    obj->key = 1;
    free(obj);
    return obj->key;

}

int main(void) {
    printf("%d\n", return_from_obj());

    return 0;
}

It might be possible to solve this problem using a garbage collector (like the Boehm garbage collector or tgc).

pitust commented 4 years ago

/cc me I am working on a fix for this. How should the test for this be called? I have it be 'regression1' right now, but perhaps it should be something else.

pitust commented 4 years ago

Just for information, this is the valgrind report before the patch:

$ valgrind -s ./x
==671532== Memcheck, a memory error detector
==671532== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==671532== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==671532== Command: ./x
==671532== 
==671532== Invalid read of size 2
==671532==    at 0x1091BE: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532==  Address 0x4a6d040 is 0 bytes inside a block of size 2 free'd
==671532==    at 0x483B9AB: free (vg_replace_malloc.c:538)
==671532==    by 0x1091B9: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532==  Block was alloc'd at
==671532==    at 0x483A77F: malloc (vg_replace_malloc.c:307)
==671532==    by 0x10917A: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532== 
1
==671532== 
==671532== HEAP SUMMARY:
==671532==     in use at exit: 0 bytes in 0 blocks
==671532==   total heap usage: 2 allocs, 2 frees, 1,026 bytes allocated
==671532== 
==671532== All heap blocks were freed -- no leaks are possible
==671532== 
==671532== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==671532== 
==671532== 1 errors in context 1 of 1:
==671532== Invalid read of size 2
==671532==    at 0x1091BE: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532==  Address 0x4a6d040 is 0 bytes inside a block of size 2 free'd
==671532==    at 0x483B9AB: free (vg_replace_malloc.c:538)
==671532==    by 0x1091B9: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532==  Block was alloc'd at
==671532==    at 0x483A77F: malloc (vg_replace_malloc.c:307)
==671532==    by 0x10917A: return_from_obj (in /home/pitust/code/pwg/x)
==671532==    by 0x1091D0: main (in /home/pitust/code/pwg/x)
==671532== 
==671532== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
pitust commented 4 years ago

^ I submitted a PR to fix this

jarble commented 3 years ago

@pitust I tried compiling the program again here, but the output hasn't changed. It still has the same bug.

pitust commented 3 years ago

Yeah, the PR is still open.

brunexgeek commented 3 years ago

As far I understand, the compiler is capable to detect the object is not used outside the current scope (i.e. the function) and perform the free before exiting (thus not using the "GC" mechanism). In this case, I think would be better to just allocate the object in the stack instead of using heap memory.