lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I noticed loadStringN was diverging between using a local stack array for short string loading vs a dynamically allocated TString buffer for long strings. And I noticed that a test in calls.lua uses a custom string reader function passed to load. The custom read1 method in calls.lua also invokes the garabagecollector. Turns out, you could cause the TString allocated for long string loads to be freed during load.

to repro
go to line 320 in calls.lua -> https://github.com/lua/lua/blob/master/testes/calls.lua#L320
change the line from:
- x = string.dump(load("x = 1; return x"))
to
+ x = string.dump(load("x = 1; return                                                                                                                                    x"))

The intention here is simply to load a string with more than 40 chars, to get outside the short string optimization and cause loadStringN to allocate a TString, and then try to write directly to its buffer. The collectgarbage method is called inside the load reader, causing the not-in-stack TString to be free'd. If using a test build, the free'd memory will get AB values written to its memory address first, easily hitting an abort shortly there after

I'm not sure what the best solution to this would be, my fix is to push the TString on the stack to protect it from gc.

static TString *loadStringN (LoadState *S, Proto *p) {
   ....
    setsvalue2s(L, L->top, ts);  /* push ts on stack to protect from possible gc */
    api_incr_top(L);
    loadVector(S, getstr(ts), size);  /* load directly in final place */
    lua_unlock(L);
    lua_settop(L, -2);
    lua_lock(L);

I don't think my solution is very good, I am interested in what the community proposes to fix this.