lua-users home
lua-l archive

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


On Sun, Mar 30, 2014 at 9:46 PM, Paige DePol <lual@serfnet.org> wrote:
Another way of fixing the issue ...

Reminder: this issue is present in 5.2 as well.

A portable solution for fixing unpack (without changing lua_checkstack) using unsigned arithmetic:

static int unpack (lua_State *L) {
  int i, e;
  unsigned int n;
  luaL_checktype(L, 1, LUA_TTABLE);
  i = luaL_optint(L, 2, 1);
  e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
  if (i > e) return 0;  /* empty range */
  n = (unsigned int )e - (unsigned int )i;  /* number of elements minus one */
  if (n >= INT_MAX || !lua_checkstack(L, (int )(n+1)))  /* detect arith. overflow */
    return luaL_error(L, "too many results to unpack");
  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */
  while (i++ < e)  /* push arg[i + 1...e] */
    lua_rawgeti(L, 1, i);
  return n;
}

The variable n is changed to unsigned, and the calculation of the number of elements uses unsigned arithmetic. This works because unsigned arithmetic cannot overflow; we know the sign of the result is positive since i <= e. Note that we defer the addition of 1 to n until after the test against INT_MAX to avoid a carry in the case of unpack ({}, -2^31, 2^31-1) leading to a result of zero.

e