error "too many local variables (limit is -1)" when int is 16 bit

154 views
Skip to first unread message

Marcus Lund

unread,
Sep 7, 2024, 12:33:17 PM9/7/24
to lua-l
When sizeof(int) is 2 bytes I've encountered an issue in lparser.c.
Attempting to create a local variable produces the error message:
"too many local variables (limit is -1)".

I'm building using the v5.4 branch on github at https://github.com/lua/lua,
commit 782ef85b.

Looking at the source code, it is connected with lparser.c line 201 in static
function new_localvar. Specifically the line:

luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
                dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");

Following the call through, it calls the function luaM_growaux_ via the
luaM_growvector macro.

The prototype of luaM_growaux_ is:

void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
                     int size_elems, int limit, const char *what)

where the type of parameter 'limit' is int.

When sizeof(int) is 2 bytes the USHRT_MAX (65535) from the luaM_growvector
call is being passed through the int 'limit' parameter where it becomes -1.
This causes the luaG_runerror invocation within luaM_growaux_, where size is
0 and limit is -1:

  if (size >= limit / 2) {  /* cannot double it? */
    if (l_unlikely(size >= limit))  /* cannot grow even a little? */
      luaG_runerror(L, "too many %s (limit is %d)", what, limit);
    size = limit;  /* still have at least one free place */
  }

If I change the luaM_growvector invocation to use MAX_INT instead of USHRT_MAX
I no longer see the reported issue.

Philippe Verdy

unread,
Sep 8, 2024, 7:11:31 PM9/8/24
to lu...@googlegroups.com
The problem is the parameter declaration "  int size_elems"  luaM_growaux_: a size should never be an int but a size type (size_t), like in the standard C library, to ensure portability (there may exist some C environments that don't have any size_t type predefined , or that have no "stdtypes.h" header, but this should be rare today, even when you don't focus on advanced C99 features. As Lua is normally using C89, "size_t" should be present. And the code in  luaM_growvector does not even check for negative values, assuming it can only be positive.

Any use of negative size value is for very specific needs and generally only for a single special valid value (-1) which is used for some function specific guards or special meaning (e.g. end of stream).

Lua in its string and table libraries also uses specific negative values for offsets (not sizes) relative to the effective end of string, but  unusually uses indexes starting by 1 (not 0) and ranges are noted inclusively on both ends (where as typical C library is using offsets inclusively for the start and exclusively for the end). But this is a part of its exposed language feature and not for their implementation in C (as long as we don't invoke the Lua API using the Lua stack for passing paameters and handling Lua objects).

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lua-l/b8cd1502-4e0b-4326-8826-3789b269c2cbn%40googlegroups.com.

Roberto Ierusalimschy

unread,
Sep 10, 2024, 9:31:03 AM9/10/24
to lu...@googlegroups.com
> When sizeof(int) is 2 bytes I've encountered an issue in lparser.c.
> Attempting to create a local variable produces the error message:
> "too many local variables (limit is -1)".

Many thanks for the feedback.


> If I change the luaM_growvector invocation to use MAX_INT instead of
> USHRT_MAX
> I no longer see the reported issue.

It would be safer to change to SHRT_MAX; MAX_INT will have problems
when sizeof(int) is not 2.

-- Roberto
Reply all
Reply to author
Forward
0 new messages