diff options
author | antirez <antirez@gmail.com> | 2018-05-14 17:49:06 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2018-06-13 12:40:33 +0200 |
commit | 1eb08bcd4634ae42ec45e8284923ac048beaa4c3 (patch) | |
tree | 396b817824e3a0e440058bb227396d6005abcc5b /deps/lua/src/lua_struct.c | |
parent | 52a00201fca331217c3b4b8b634f6a0f57d6b7d3 (diff) | |
download | redis-1eb08bcd4634ae42ec45e8284923ac048beaa4c3.tar.gz |
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.
Diffstat (limited to 'deps/lua/src/lua_struct.c')
-rw-r--r-- | deps/lua/src/lua_struct.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/deps/lua/src/lua_struct.c b/deps/lua/src/lua_struct.c index a602bb430..b03a002da 100644 --- a/deps/lua/src/lua_struct.c +++ b/deps/lua/src/lua_struct.c @@ -1,7 +1,7 @@ /* ** {====================================================== ** Library for packing/unpacking structures. -** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $ +** $Id: struct.c,v 1.7 2018/05/11 22:04:31 roberto Exp $ ** See Copyright Notice at the end of this file ** ======================================================= */ @@ -15,8 +15,8 @@ ** h/H - signed/unsigned short ** l/L - signed/unsigned long ** T - size_t -** 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 +** 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 the whole string; when unpacking, n==0 means use the previous read number as the string length ** s - zero-terminated string @@ -89,14 +89,12 @@ typedef struct Header { } Header; -static int getnum (lua_State *L, const char **fmt, int df) { +static int getnum (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; @@ -117,9 +115,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(L, fmt, 1); + case 'c': return getnum(fmt, 1); case 'i': case 'I': { - int sz = getnum(L, fmt, sizeof(int)); + int sz = getnum(fmt, sizeof(int)); if (sz > MAXINTSIZE) luaL_error(L, "integral size %d is larger than limit of %d", sz, MAXINTSIZE); @@ -152,7 +150,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(L, fmt, MAXALIGN); + int a = getnum(fmt, MAXALIGN); if (!isp2(a)) luaL_error(L, "alignment %d is not a power of 2", a); h->align = a; @@ -296,20 +294,21 @@ static int b_unpack (lua_State *L) { size_t ld; const char *data = luaL_checklstring(L, 2, &ld); size_t pos = luaL_optinteger(L, 3, 1) - 1; + int n = 0; /* number of results */ defaultoptions(&h); - lua_settop(L, 2); while (*fmt) { int opt = *fmt++; size_t size = optsize(L, opt, &fmt); pos += gettoalign(pos, &h, opt, size); luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); - luaL_checkstack(L, 1, "too many results"); + /* stack space for item + next position */ + luaL_checkstack(L, 2, "too many results"); switch (opt) { case 'b': case 'B': case 'h': case 'H': case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ int issigned = islower(opt); lua_Number res = getinteger(data+pos, h.endian, issigned, size); - lua_pushnumber(L, res); + lua_pushnumber(L, res); n++; break; } case 'x': { @@ -319,25 +318,26 @@ static int b_unpack (lua_State *L) { float f; memcpy(&f, data+pos, size); correctbytes((char *)&f, sizeof(f), h.endian); - lua_pushnumber(L, f); + lua_pushnumber(L, f); n++; break; } case 'd': { double d; memcpy(&d, data+pos, size); correctbytes((char *)&d, sizeof(d), h.endian); - lua_pushnumber(L, d); + lua_pushnumber(L, d); n++; break; } case 'c': { if (size == 0) { - if (!lua_isnumber(L, -1)) - luaL_error(L, "format `c0' needs a previous size"); + if (n == 0 || !lua_isnumber(L, -1)) + luaL_error(L, "format 'c0' needs a previous size"); size = lua_tonumber(L, -1); - lua_pop(L, 1); - luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); + lua_pop(L, 1); n--; + luaL_argcheck(L, size <= ld && pos <= ld - size, + 2, "data string too short"); } - lua_pushlstring(L, data+pos, size); + lua_pushlstring(L, data+pos, size); n++; break; } case 's': { @@ -345,15 +345,15 @@ static int b_unpack (lua_State *L) { if (e == NULL) luaL_error(L, "unfinished string in data"); size = (e - (data+pos)) + 1; - lua_pushlstring(L, data+pos, size - 1); + lua_pushlstring(L, data+pos, size - 1); n++; break; } default: controloptions(L, opt, &fmt, &h); } pos += size; } - lua_pushinteger(L, pos + 1); - return lua_gettop(L) - 2; + lua_pushinteger(L, pos + 1); /* next position */ + return n + 1; } @@ -399,7 +399,7 @@ LUALIB_API int luaopen_struct (lua_State *L) { /****************************************************************************** -* Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved. +* Copyright (C) 2010-2018 Lua.org, PUC-Rio. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the |