Skip to content

Commit 1eb08bc

Browse files
committed
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.
1 parent 52a0020 commit 1eb08bc

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

Diff for: deps/lua/src/lua_struct.c

+23-23
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
** {======================================================
33
** Library for packing/unpacking structures.
4-
** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
4+
** $Id: struct.c,v 1.7 2018/05/11 22:04:31 roberto Exp $
55
** See Copyright Notice at the end of this file
66
** =======================================================
77
*/
@@ -15,8 +15,8 @@
1515
** h/H - signed/unsigned short
1616
** l/L - signed/unsigned long
1717
** T - size_t
18-
** i/In - signed/unsigned integer with size `n' (default is size of int)
19-
** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
18+
** i/In - signed/unsigned integer with size 'n' (default is size of int)
19+
** cn - sequence of 'n' chars (from/to a string); when packing, n==0 means
2020
the whole string; when unpacking, n==0 means use the previous
2121
read number as the string length
2222
** s - zero-terminated string
@@ -89,14 +89,12 @@ typedef struct Header {
8989
} Header;
9090

9191

92-
static int getnum (lua_State *L, const char **fmt, int df) {
92+
static int getnum (const char **fmt, int df) {
9393
if (!isdigit(**fmt)) /* no number? */
9494
return df; /* return default value */
9595
else {
9696
int a = 0;
9797
do {
98-
if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))
99-
luaL_error(L, "integral size overflow");
10098
a = a*10 + *((*fmt)++) - '0';
10199
} while (isdigit(**fmt));
102100
return a;
@@ -117,9 +115,9 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
117115
case 'f': return sizeof(float);
118116
case 'd': return sizeof(double);
119117
case 'x': return 1;
120-
case 'c': return getnum(L, fmt, 1);
118+
case 'c': return getnum(fmt, 1);
121119
case 'i': case 'I': {
122-
int sz = getnum(L, fmt, sizeof(int));
120+
int sz = getnum(fmt, sizeof(int));
123121
if (sz > MAXINTSIZE)
124122
luaL_error(L, "integral size %d is larger than limit of %d",
125123
sz, MAXINTSIZE);
@@ -152,7 +150,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
152150
case '>': h->endian = BIG; return;
153151
case '<': h->endian = LITTLE; return;
154152
case '!': {
155-
int a = getnum(L, fmt, MAXALIGN);
153+
int a = getnum(fmt, MAXALIGN);
156154
if (!isp2(a))
157155
luaL_error(L, "alignment %d is not a power of 2", a);
158156
h->align = a;
@@ -296,20 +294,21 @@ static int b_unpack (lua_State *L) {
296294
size_t ld;
297295
const char *data = luaL_checklstring(L, 2, &ld);
298296
size_t pos = luaL_optinteger(L, 3, 1) - 1;
297+
int n = 0; /* number of results */
299298
defaultoptions(&h);
300-
lua_settop(L, 2);
301299
while (*fmt) {
302300
int opt = *fmt++;
303301
size_t size = optsize(L, opt, &fmt);
304302
pos += gettoalign(pos, &h, opt, size);
305303
luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
306-
luaL_checkstack(L, 1, "too many results");
304+
/* stack space for item + next position */
305+
luaL_checkstack(L, 2, "too many results");
307306
switch (opt) {
308307
case 'b': case 'B': case 'h': case 'H':
309308
case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
310309
int issigned = islower(opt);
311310
lua_Number res = getinteger(data+pos, h.endian, issigned, size);
312-
lua_pushnumber(L, res);
311+
lua_pushnumber(L, res); n++;
313312
break;
314313
}
315314
case 'x': {
@@ -319,41 +318,42 @@ static int b_unpack (lua_State *L) {
319318
float f;
320319
memcpy(&f, data+pos, size);
321320
correctbytes((char *)&f, sizeof(f), h.endian);
322-
lua_pushnumber(L, f);
321+
lua_pushnumber(L, f); n++;
323322
break;
324323
}
325324
case 'd': {
326325
double d;
327326
memcpy(&d, data+pos, size);
328327
correctbytes((char *)&d, sizeof(d), h.endian);
329-
lua_pushnumber(L, d);
328+
lua_pushnumber(L, d); n++;
330329
break;
331330
}
332331
case 'c': {
333332
if (size == 0) {
334-
if (!lua_isnumber(L, -1))
335-
luaL_error(L, "format `c0' needs a previous size");
333+
if (n == 0 || !lua_isnumber(L, -1))
334+
luaL_error(L, "format 'c0' needs a previous size");
336335
size = lua_tonumber(L, -1);
337-
lua_pop(L, 1);
338-
luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
336+
lua_pop(L, 1); n--;
337+
luaL_argcheck(L, size <= ld && pos <= ld - size,
338+
2, "data string too short");
339339
}
340-
lua_pushlstring(L, data+pos, size);
340+
lua_pushlstring(L, data+pos, size); n++;
341341
break;
342342
}
343343
case 's': {
344344
const char *e = (const char *)memchr(data+pos, '\0', ld - pos);
345345
if (e == NULL)
346346
luaL_error(L, "unfinished string in data");
347347
size = (e - (data+pos)) + 1;
348-
lua_pushlstring(L, data+pos, size - 1);
348+
lua_pushlstring(L, data+pos, size - 1); n++;
349349
break;
350350
}
351351
default: controloptions(L, opt, &fmt, &h);
352352
}
353353
pos += size;
354354
}
355-
lua_pushinteger(L, pos + 1);
356-
return lua_gettop(L) - 2;
355+
lua_pushinteger(L, pos + 1); /* next position */
356+
return n + 1;
357357
}
358358

359359

@@ -399,7 +399,7 @@ LUALIB_API int luaopen_struct (lua_State *L) {
399399

400400

401401
/******************************************************************************
402-
* Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved.
402+
* Copyright (C) 2010-2018 Lua.org, PUC-Rio. All rights reserved.
403403
*
404404
* Permission is hereby granted, free of charge, to any person obtaining
405405
* a copy of this software and associated documentation files (the

0 commit comments

Comments
 (0)