Vulnerability: 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.
Vulnerability ID: CVE-2020-14147
CWE: CWE-190
Severity score: 2.9
Project: https://github.com/antirez/redis
Published: 2020-06-15
File: deps/lua/src/lua_struct.c
Commit message: [FIX] revisit CVE-2015-8080 vulnerability
Commit author: Seunghoon Woo

Vulnerable version (before fix):
 typedef struct Header { } Header;   static int getnum (const char **fmt, int df) {   if (!isdigit(**fmt))  /* no number? */     return df;  /* return default value */   else {     int a = 0;     do {       a = a*10 + *((*fmt)++) - '0';     } while (isdigit(**fmt));     return a; static size_t optsize (lua_State *L, char opt, const char **fmt) {     case 'f':  return sizeof(float);     case 'd':  return sizeof(double);     case 'x': return 1;     case 'c': return getnum(fmt, 1);     case 'i': case 'I': {       int sz = getnum(fmt, sizeof(int));       if (sz > MAXINTSIZE)         luaL_error(L, "integral size %d is larger than limit of %d",                        sz, MAXINTSIZE); static void controloptions (lua_State *L, int opt, const char **fmt,     case '>': h->endian = BIG; return;     case '<': h->endian = LITTLE; return;     case '!': {       int a = getnum(fmt, MAXALIGN);       if (!isp2(a))         luaL_error(L, "alignment %d is not a power of 2", a);       h->align = a;

Fixed version (after fix):
 typedef struct Header { } Header;   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; static size_t optsize (lua_State *L, char opt, const char **fmt) {     case 'f':  return sizeof(float);     case 'd':  return sizeof(double);     case 'x': return 1;     case 'c': return getnum(L, fmt, 1);     case 'i': case 'I': {       int sz = getnum(L, fmt, sizeof(int));       if (sz > MAXINTSIZE)         luaL_error(L, "integral size %d is larger than limit of %d",                        sz, MAXINTSIZE); static void controloptions (lua_State *L, int opt, const char **fmt,     case '>': h->endian = BIG; return;     case '<': h->endian = LITTLE; return;     case '!': {       int a = getnum(L, fmt, MAXALIGN);       if (!isp2(a))         luaL_error(L, "alignment %d is not a power of 2", a);       h->align = a;

Patch:
patch: @@ -89,12 +89,14 @@ typedef struct Header {
 } 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;
@@ -115,9 +117,9 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
     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);
@@ -150,7 +152,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
     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;
path: deps/lua/src/lua_struct.c