CVE-2020-14147: Integer Overflow or Wraparound (CWE-190)
value: An integer overflow in the getnum function in lua_struct.c in Redis before 6.0.3 allows context-dependent attackers with permission to run Lua code in a Redis session to cause a denial of service (memory corruption and application crash) or possibly bypass intended sandbox restrictions via a large number, which triggers a stack-based buffer overflow. NOTE: this issue exists because of a CVE-2015-8080 regression.
CWE description: 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.
CVSS v3 base score: 7.7
Published: 2020-06-15T18:15Z
Repository: https://github.com/antirez/redis
Language: C
Files changed: deps/lua/src/lua_struct.c
Commit date: 2020-02-10 16:32:46 +0900
Commit message: [FIX] revisit CVE-2015-8080 vulnerability

Diff: diff --git a/deps/lua/src/lua_struct.c b/deps/lua/src/lua_struct.c
index 4d5f027b8..c58c8e72b 100644
--- a/deps/lua/src/lua_struct.c
+++ b/deps/lua/src/lua_struct.c
@@ -87,16 +87,18 @@ typedef struct Header {
   int endian;
   int align;
 } Header;
 
 
-static int getnum (const char **fmt, int df) {
+static int getnum (lua_State *L, const char **fmt, int df) {
   if (!isdigit(**fmt))  /* no number? */
     return df;  /* return default value */
   else {
     int a = 0;
     do {
+      if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))
+        luaL_error(L, "integral size overflow");
       a = a*10 + *((*fmt)++) - '0';
     } while (isdigit(**fmt));
     return a;
   }
 }
@@ -113,13 +115,13 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
     case 'L': case 'l': return sizeof(long);
     case 'T': return sizeof(size_t);
     case 'f':  return sizeof(float);
     case 'd':  return sizeof(double);
     case 'x': return 1;
-    case 'c': return getnum(fmt, 1);
+    case 'c': return getnum(L, fmt, 1);
     case 'i': case 'I': {
-      int sz = getnum(fmt, sizeof(int));
+      int sz = getnum(L, fmt, sizeof(int));
       if (sz > MAXINTSIZE)
         luaL_error(L, "integral size %d is larger than limit of %d",
                        sz, MAXINTSIZE);
       return sz;
     }
@@ -148,11 +150,11 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
   switch (opt) {
     case  ' ': return;  /* ignore white spaces */
     case '>': h->endian = BIG; return;
     case '<': h->endian = LITTLE; return;
     case '!': {
-      int a = getnum(fmt, MAXALIGN);
+      int a = getnum(L, fmt, MAXALIGN);
       if (!isp2(a))
         luaL_error(L, "alignment %d is not a power of 2", a);
       h->align = a;
       return;
     }

Vulnerable code: 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);
Fixed code: 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);