CVE-2018-11219 (C, published 2018-06-17T17:29Z)
Description: value: An Integer Overflow issue was discovered in the struct library in the Lua subsystem in Redis before 3.2.12, 4.x before 4.0.10, and 5.x before 5.0 RC2, leading to a failure of bounds checking.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-190 \u2014 Integer Overflow or Wraparound
The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
Repository: https://github.com/antirez/redis
Files changed:
deps/lua/src/lua_struct.c
Commit message: Security: update Lua struct package for security.

During an auditing Apple found that the "struct" Lua package
we ship with Redis (http://www.inf.puc-rio.br/~roberto/struct/) contains
a security problem. A bound-checking statement fails because of integer
overflow. The bug exists since we initially integrated this package with
Lua, when scripting was introduced, so every version of Redis with
EVAL/EVALSHA capabilities exposed is affected.

Instead of just fixing the bug, the library was updated to the latest
version shipped by the author.


Vulnerable code:
** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
** i/In - signed/unsigned integer with size `n' (default is size of int)
** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
static int getnum (lua_State *L, const char **fmt, int df) {
      if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))
        luaL_error(L, "integral size overflow");
    case 'c': return getnum(L, fmt, 1);
      int sz = getnum(L, fmt, sizeof(int));
      int a = getnum(L, fmt, MAXALIGN);
  lua_settop(L, 2);
    luaL_checkstack(L, 1, "too many results");
        lua_pushnumber(L, res);
        lua_pushnumber(L, f);
        lua_pushnumber(L, d);
          if (!lua_isnumber(L, -1))
            luaL_error(L, "format `c0' needs a previous size");
          lua_pop(L, 1);
          luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
        lua_pushlstring(L, data+pos, size);
        lua_pushlstring(L, data+pos, size - 1);
  lua_pushinteger(L, pos + 1);
  return lua_gettop(L) - 2;
* Copyright (C) 2010-2012 Lua.org, PUC-Rio.  All rights reserved.

Fixed code:
** $Id: struct.c,v 1.7 2018/05/11 22:04:31 roberto Exp $
** i/In - signed/unsigned integer with size 'n' (default is size of int)
** cn - sequence of 'n' chars (from/to a string); when packing, n==0 means
static int getnum (const char **fmt, int df) {
    case 'c': return getnum(fmt, 1);
      int sz = getnum(fmt, sizeof(int));
      int a = getnum(fmt, MAXALIGN);
  int n = 0;  /* number of results */
    /* stack space for item + next position */
    luaL_checkstack(L, 2, "too many results");
        lua_pushnumber(L, res); n++;
        lua_pushnumber(L, f); n++;
        lua_pushnumber(L, d); n++;
          if (n == 0 || !lua_isnumber(L, -1))
            luaL_error(L, "format 'c0' needs a previous size");
          lua_pop(L, 1); n--;
          luaL_argcheck(L, size <= ld && pos <= ld - size,
                           2, "data string too short");
        lua_pushlstring(L, data+pos, size); n++;
        lua_pushlstring(L, data+pos, size - 1); n++;
  lua_pushinteger(L, pos + 1);  /* next position */
  return n + 1;
* Copyright (C) 2010-2018 Lua.org, PUC-Rio.  All rights reserved.