summaryrefslogtreecommitdiff
path: root/deps/lua/src/lua_struct.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-05-14 17:49:06 +0200
committerantirez <antirez@gmail.com>2018-06-13 12:40:33 +0200
commit1eb08bcd4634ae42ec45e8284923ac048beaa4c3 (patch)
tree396b817824e3a0e440058bb227396d6005abcc5b /deps/lua/src/lua_struct.c
parent52a00201fca331217c3b4b8b634f6a0f57d6b7d3 (diff)
downloadredis-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.c46
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