Skip to content

Commit 61853a9

Browse files
committed
Lua struct library updated to version 0.2.
There was a bug in the previous version of this library that caused a crash under the circumstances described in issue redis#901. The newer version of the library appears to be fixed (I tested it manually with valgrind and everything seems fine now). For more information about this library please visit this web site: http://www.inf.puc-rio.br/~roberto/struct/
1 parent 88015b8 commit 61853a9

File tree

1 file changed

+119
-52
lines changed

1 file changed

+119
-52
lines changed

deps/lua/src/lua_struct.c

+119-52
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
1-
2-
#include <assert.h>
3-
#include <ctype.h>
4-
#include <limits.h>
5-
#include <string.h>
6-
7-
8-
#include "lua.h"
9-
#include "lauxlib.h"
10-
11-
121
/*
132
** {======================================================
143
** Library for packing/unpacking structures.
15-
** $Id: struct.c,v 1.2 2008/04/18 20:06:01 roberto Exp $
4+
** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
165
** See Copyright Notice at the end of this file
176
** =======================================================
187
*/
@@ -25,6 +14,7 @@
2514
** b/B - signed/unsigned byte
2615
** h/H - signed/unsigned short
2716
** l/L - signed/unsigned long
17+
** T - size_t
2818
** i/In - signed/unsigned integer with size `n' (default is size of int)
2919
** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
3020
the whole string; when unpacking, n==0 means use the previous
@@ -36,6 +26,38 @@
3626
*/
3727

3828

29+
#include <assert.h>
30+
#include <ctype.h>
31+
#include <limits.h>
32+
#include <stddef.h>
33+
#include <string.h>
34+
35+
36+
#include "lua.h"
37+
#include "lauxlib.h"
38+
39+
40+
#if (LUA_VERSION_NUM >= 502)
41+
42+
#define luaL_register(L,n,f) luaL_newlib(L,f)
43+
44+
#endif
45+
46+
47+
/* basic integer type */
48+
#if !defined(STRUCT_INT)
49+
#define STRUCT_INT long
50+
#endif
51+
52+
typedef STRUCT_INT Inttype;
53+
54+
/* corresponding unsigned version */
55+
typedef unsigned STRUCT_INT Uinttype;
56+
57+
58+
/* maximum size (in bytes) for integral types */
59+
#define MAXINTSIZE 32
60+
3961
/* is 'x' a power of 2? */
4062
#define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0)
4163

@@ -67,11 +89,11 @@ typedef struct Header {
6789
} Header;
6890

6991

70-
static size_t getnum (const char **fmt, size_t df) {
92+
static int getnum (const char **fmt, int df) {
7193
if (!isdigit(**fmt)) /* no number? */
7294
return df; /* return default value */
7395
else {
74-
size_t a = 0;
96+
int a = 0;
7597
do {
7698
a = a*10 + *((*fmt)++) - '0';
7799
} while (isdigit(**fmt));
@@ -89,33 +111,40 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
89111
case 'B': case 'b': return sizeof(char);
90112
case 'H': case 'h': return sizeof(short);
91113
case 'L': case 'l': return sizeof(long);
114+
case 'T': return sizeof(size_t);
92115
case 'f': return sizeof(float);
93116
case 'd': return sizeof(double);
94117
case 'x': return 1;
95118
case 'c': return getnum(fmt, 1);
96-
case 's': case ' ': case '<': case '>': case '!': return 0;
97119
case 'i': case 'I': {
98120
int sz = getnum(fmt, sizeof(int));
99-
if (!isp2(sz))
100-
luaL_error(L, "integral size %d is not a power of 2", sz);
121+
if (sz > MAXINTSIZE)
122+
luaL_error(L, "integral size %d is larger than limit of %d",
123+
sz, MAXINTSIZE);
101124
return sz;
102125
}
103-
default: {
104-
const char *msg = lua_pushfstring(L, "invalid format option [%c]", opt);
105-
return luaL_argerror(L, 1, msg);
106-
}
126+
default: return 0; /* other cases do not need alignment */
107127
}
108128
}
109129

110130

131+
/*
132+
** return number of bytes needed to align an element of size 'size'
133+
** at current position 'len'
134+
*/
111135
static int gettoalign (size_t len, Header *h, int opt, size_t size) {
112136
if (size == 0 || opt == 'c') return 0;
113-
if (size > (size_t)h->align) size = h->align; /* respect max. alignment */
114-
return (size - (len & (size - 1))) & (size - 1);
137+
if (size > (size_t)h->align)
138+
size = h->align; /* respect max. alignment */
139+
return (size - (len & (size - 1))) & (size - 1);
115140
}
116141

117142

118-
static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) {
143+
/*
144+
** options to control endianess and alignment
145+
*/
146+
static void controloptions (lua_State *L, int opt, const char **fmt,
147+
Header *h) {
119148
switch (opt) {
120149
case ' ': return; /* ignore white spaces */
121150
case '>': h->endian = BIG; return;
@@ -127,29 +156,38 @@ static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) {
127156
h->align = a;
128157
return;
129158
}
130-
default: assert(0);
159+
default: {
160+
const char *msg = lua_pushfstring(L, "invalid format option '%c'", opt);
161+
luaL_argerror(L, 1, msg);
162+
}
131163
}
132164
}
133165

134166

135167
static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,
136168
int size) {
137169
lua_Number n = luaL_checknumber(L, arg);
138-
unsigned long value;
139-
if (n < (lua_Number)LONG_MAX)
140-
value = (long)n;
170+
Uinttype value;
171+
char buff[MAXINTSIZE];
172+
if (n < 0)
173+
value = (Uinttype)(Inttype)n;
141174
else
142-
value = (unsigned long)n;
175+
value = (Uinttype)n;
143176
if (endian == LITTLE) {
144177
int i;
145-
for (i = 0; i < size; i++)
146-
luaL_addchar(b, (value >> 8*i) & 0xff);
178+
for (i = 0; i < size; i++) {
179+
buff[i] = (value & 0xff);
180+
value >>= 8;
181+
}
147182
}
148183
else {
149184
int i;
150-
for (i = size - 1; i >= 0; i--)
151-
luaL_addchar(b, (value >> 8*i) & 0xff);
185+
for (i = size - 1; i >= 0; i--) {
186+
buff[i] = (value & 0xff);
187+
value >>= 8;
188+
}
152189
}
190+
luaL_addlstring(b, buff, size);
153191
}
154192

155193

@@ -179,15 +217,15 @@ static int b_pack (lua_State *L) {
179217
size_t size = optsize(L, opt, &fmt);
180218
int toalign = gettoalign(totalsize, &h, opt, size);
181219
totalsize += toalign;
182-
while (toalign-- > 0) luaL_putchar(&b, '\0');
220+
while (toalign-- > 0) luaL_addchar(&b, '\0');
183221
switch (opt) {
184222
case 'b': case 'B': case 'h': case 'H':
185-
case 'l': case 'L': case 'i': case 'I': { /* integer types */
223+
case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
186224
putinteger(L, &b, arg++, h.endian, size);
187225
break;
188226
}
189227
case 'x': {
190-
luaL_putchar(&b, '\0');
228+
luaL_addchar(&b, '\0');
191229
break;
192230
}
193231
case 'f': {
@@ -209,12 +247,12 @@ static int b_pack (lua_State *L) {
209247
luaL_argcheck(L, l >= (size_t)size, arg, "string too short");
210248
luaL_addlstring(&b, s, size);
211249
if (opt == 's') {
212-
luaL_putchar(&b, '\0'); /* add zero at the end */
250+
luaL_addchar(&b, '\0'); /* add zero at the end */
213251
size++;
214252
}
215253
break;
216254
}
217-
default: commoncases(L, opt, &fmt, &h);
255+
default: controloptions(L, opt, &fmt, &h);
218256
}
219257
totalsize += size;
220258
}
@@ -225,24 +263,27 @@ static int b_pack (lua_State *L) {
225263

226264
static lua_Number getinteger (const char *buff, int endian,
227265
int issigned, int size) {
228-
unsigned long l = 0;
266+
Uinttype l = 0;
267+
int i;
229268
if (endian == BIG) {
230-
int i;
231-
for (i = 0; i < size; i++)
232-
l |= (unsigned long)(unsigned char)buff[size - i - 1] << (i*8);
269+
for (i = 0; i < size; i++) {
270+
l <<= 8;
271+
l |= (Uinttype)(unsigned char)buff[i];
272+
}
233273
}
234274
else {
235-
int i;
236-
for (i = 0; i < size; i++)
237-
l |= (unsigned long)(unsigned char)buff[i] << (i*8);
275+
for (i = size - 1; i >= 0; i--) {
276+
l <<= 8;
277+
l |= (Uinttype)(unsigned char)buff[i];
278+
}
238279
}
239280
if (!issigned)
240281
return (lua_Number)l;
241282
else { /* signed format */
242-
unsigned long mask = ~(0UL) << (size*8 - 1);
283+
Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);
243284
if (l & mask) /* negative value? */
244285
l |= mask; /* signal extension */
245-
return (lua_Number)(long)l;
286+
return (lua_Number)(Inttype)l;
246287
}
247288
}
248289

@@ -260,9 +301,10 @@ static int b_unpack (lua_State *L) {
260301
size_t size = optsize(L, opt, &fmt);
261302
pos += gettoalign(pos, &h, opt, size);
262303
luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
304+
luaL_checkstack(L, 1, "too many results");
263305
switch (opt) {
264306
case 'b': case 'B': case 'h': case 'H':
265-
case 'l': case 'L': case 'i': case 'I': { /* integer types */
307+
case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
266308
int issigned = islower(opt);
267309
lua_Number res = getinteger(data+pos, h.endian, issigned, size);
268310
lua_pushnumber(L, res);
@@ -304,34 +346,58 @@ static int b_unpack (lua_State *L) {
304346
lua_pushlstring(L, data+pos, size - 1);
305347
break;
306348
}
307-
default: commoncases(L, opt, &fmt, &h);
349+
default: controloptions(L, opt, &fmt, &h);
308350
}
309351
pos += size;
310352
}
311353
lua_pushinteger(L, pos + 1);
312354
return lua_gettop(L) - 2;
313355
}
314356

357+
358+
static int b_size (lua_State *L) {
359+
Header h;
360+
const char *fmt = luaL_checkstring(L, 1);
361+
size_t pos = 0;
362+
defaultoptions(&h);
363+
while (*fmt) {
364+
int opt = *fmt++;
365+
size_t size = optsize(L, opt, &fmt);
366+
pos += gettoalign(pos, &h, opt, size);
367+
if (opt == 's')
368+
luaL_argerror(L, 1, "option 's' has no fixed size");
369+
else if (opt == 'c' && size == 0)
370+
luaL_argerror(L, 1, "option 'c0' has no fixed size");
371+
if (!isalnum(opt))
372+
controloptions(L, opt, &fmt, &h);
373+
pos += size;
374+
}
375+
lua_pushinteger(L, pos);
376+
return 1;
377+
}
378+
315379
/* }====================================================== */
316380

317381

318382

319-
static const struct luaL_reg thislib[] = {
383+
static const struct luaL_Reg thislib[] = {
320384
{"pack", b_pack},
321385
{"unpack", b_unpack},
386+
{"size", b_size},
322387
{NULL, NULL}
323388
};
324389

325390

391+
LUALIB_API int luaopen_struct (lua_State *L);
392+
326393
LUALIB_API int luaopen_struct (lua_State *L) {
327394
luaL_register(L, "struct", thislib);
328395
return 1;
329396
}
330397

331398

332-
333399
/******************************************************************************
334-
* Copyright (C) 2010 Lua.org, PUC-Rio. All rights reserved.
400+
* Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved.
335401
*
336402
* Permission is hereby granted, free of charge, to any person obtaining
337403
* a copy of this software and associated documentation files (the
@@ -352,3 +418,4 @@ LUALIB_API int luaopen_struct (lua_State *L) {
352418
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
353419
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
354420
******************************************************************************/
421+

0 commit comments

Comments
 (0)