Skip to content

Commit 0178d4e

Browse files
committed
bugfix: ngx.say and ngx.print might cause nginx to crash when table-typed arguments were given. thanks sztanpet for reporting this in github issue #54.
1 parent 0428b88 commit 0178d4e

6 files changed

+80
-17
lines changed

src/ngx_http_lua_bodyfilterby.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r,
543543
return 0;
544544

545545
case LUA_TTABLE:
546-
size = ngx_http_lua_calc_strlen_in_table(L, 3 /* index */,
546+
size = ngx_http_lua_calc_strlen_in_table(L, 3 /* index */, 3 /* arg */,
547547
1 /* strict */);
548548
data = NULL;
549549
break;
@@ -605,7 +605,7 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r,
605605
}
606606

607607
if (type == LUA_TTABLE) {
608-
cl->buf->last = ngx_http_lua_copy_str_in_table(L, cl->buf->last);
608+
cl->buf->last = ngx_http_lua_copy_str_in_table(L, 3, cl->buf->last);
609609

610610
} else {
611611
cl->buf->last = ngx_copy(cl->buf->pos, data, size);

src/ngx_http_lua_output.c

+30-11
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
110110

111111
case LUA_TTABLE:
112112

113-
size += ngx_http_lua_calc_strlen_in_table(L, i, 0 /* strict */);
113+
size += ngx_http_lua_calc_strlen_in_table(L, i, i,
114+
0 /* strict */);
114115
break;
115116

116117
case LUA_TLIGHTUSERDATA:
@@ -187,7 +188,7 @@ ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
187188
break;
188189

189190
case LUA_TTABLE:
190-
b->last = ngx_http_lua_copy_str_in_table(L, b->last);
191+
b->last = ngx_http_lua_copy_str_in_table(L, i, b->last);
191192
break;
192193

193194
case LUA_TLIGHTUSERDATA:
@@ -242,7 +243,8 @@ ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
242243

243244

244245
size_t
245-
ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict)
246+
ngx_http_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i,
247+
unsigned strict)
246248
{
247249
double key;
248250
int max;
@@ -252,11 +254,24 @@ ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict)
252254
size_t len;
253255
const char *msg;
254256

257+
if (index < 0) {
258+
index = lua_gettop(L) + index + 1;
259+
}
260+
261+
dd("table index: %d", index);
262+
255263
max = 0;
256264

257265
lua_pushnil(L); /* stack: table key */
258-
while (lua_next(L, -2) != 0) { /* stack: table key value */
259-
if (lua_type(L, -2) == LUA_TNUMBER && (key = lua_tonumber(L, -2))) {
266+
while (lua_next(L, index) != 0) { /* stack: table key value */
267+
dd("key type: %s", luaL_typename(L, -2));
268+
269+
if (lua_type(L, -2) == LUA_TNUMBER) {
270+
271+
key = lua_tonumber(L, -2);
272+
273+
dd("key value: %d", (int) key);
274+
260275
if (floor(key) == key && key >= 1) {
261276
if (key > max) {
262277
max = key;
@@ -278,7 +293,7 @@ ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict)
278293
size = 0;
279294

280295
for (i = 1; i <= max; i++) {
281-
lua_rawgeti(L, -1, i); /* stack: table value */
296+
lua_rawgeti(L, index, i); /* stack: table value */
282297
type = lua_type(L, -1);
283298

284299
switch (type) {
@@ -315,7 +330,7 @@ ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict)
315330

316331
case LUA_TTABLE:
317332

318-
size += ngx_http_lua_calc_strlen_in_table(L, arg_i, strict);
333+
size += ngx_http_lua_calc_strlen_in_table(L, -1, arg_i, strict);
319334
break;
320335

321336
case LUA_TLIGHTUSERDATA:
@@ -347,7 +362,7 @@ ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict)
347362

348363

349364
u_char *
350-
ngx_http_lua_copy_str_in_table(lua_State *L, u_char *dst)
365+
ngx_http_lua_copy_str_in_table(lua_State *L, int index, u_char *dst)
351366
{
352367
double key;
353368
int max;
@@ -356,10 +371,14 @@ ngx_http_lua_copy_str_in_table(lua_State *L, u_char *dst)
356371
size_t len;
357372
u_char *p;
358373

374+
if (index < 0) {
375+
index = lua_gettop(L) + index + 1;
376+
}
377+
359378
max = 0;
360379

361380
lua_pushnil(L); /* stack: table key */
362-
while (lua_next(L, -2) != 0) { /* stack: table key value */
381+
while (lua_next(L, index) != 0) { /* stack: table key value */
363382
key = lua_tonumber(L, -2);
364383
if (key > max) {
365384
max = key;
@@ -369,7 +388,7 @@ ngx_http_lua_copy_str_in_table(lua_State *L, u_char *dst)
369388
}
370389

371390
for (i = 1; i <= max; i++) {
372-
lua_rawgeti(L, -1, i); /* stack: table value */
391+
lua_rawgeti(L, index, i); /* stack: table value */
373392
type = lua_type(L, -1);
374393
switch (type) {
375394
case LUA_TNUMBER:
@@ -402,7 +421,7 @@ ngx_http_lua_copy_str_in_table(lua_State *L, u_char *dst)
402421
break;
403422

404423
case LUA_TTABLE:
405-
dst = ngx_http_lua_copy_str_in_table(L, dst);
424+
dst = ngx_http_lua_copy_str_in_table(L, -1, dst);
406425
break;
407426

408427
case LUA_TLIGHTUSERDATA:

src/ngx_http_lua_output.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
void ngx_http_lua_inject_output_api(lua_State *L);
99

10-
size_t ngx_http_lua_calc_strlen_in_table(lua_State *L, int arg_i,
10+
size_t ngx_http_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i,
1111
unsigned strict);
1212

13-
u_char * ngx_http_lua_copy_str_in_table(lua_State *L, u_char *dst);
13+
u_char * ngx_http_lua_copy_str_in_table(lua_State *L, int index, u_char *dst);
1414

1515

1616
#endif /* NGX_HTTP_LUA_OUTPUT_H */

src/ngx_http_lua_socket.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,7 @@ ngx_http_lua_socket_tcp_send(lua_State *L)
14611461
break;
14621462

14631463
case LUA_TTABLE:
1464-
len = ngx_http_lua_calc_strlen_in_table(L, 2, 1 /* strict */);
1464+
len = ngx_http_lua_calc_strlen_in_table(L, 2, 2, 1 /* strict */);
14651465
break;
14661466

14671467
default:
@@ -1493,7 +1493,7 @@ ngx_http_lua_socket_tcp_send(lua_State *L)
14931493
break;
14941494

14951495
case LUA_TTABLE:
1496-
b->last = ngx_http_lua_copy_str_in_table(L, b->last);
1496+
b->last = ngx_http_lua_copy_str_in_table(L, -1, b->last);
14971497
break;
14981498

14991499
default:

t/002-content.t

+24
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,27 @@ hello,
662662
world
663663
--- timeout: 5
664664

665+
666+
667+
=== TEST 36: ngx.print table arguments (github issue #54)
668+
--- config
669+
location /t {
670+
content_by_lua 'ngx.print({10, {0, 5}, 15}, 32)';
671+
}
672+
--- request
673+
GET /t
674+
--- response_body chop
675+
10051532
676+
677+
678+
679+
=== TEST 37: ngx.say table arguments (github issue #54)
680+
--- config
681+
location /t {
682+
content_by_lua 'ngx.say({10, {0, "5"}, 15}, 32)';
683+
}
684+
--- request
685+
GET /t
686+
--- response_body
687+
10051532
688+

t/082-body-filter.t

+20
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,23 @@ aaaaaa
390390
--- no_error_log
391391
[error]
392392

393+
394+
395+
=== TEST 15: table arguments to ngx.arg[1] (github issue #54)
396+
--- config
397+
location /t {
398+
echo -n hello;
399+
400+
body_filter_by_lua '
401+
if ngx.arg[1] ~= "" then
402+
ngx.arg[1] = {{ngx.arg[1]}, "!", "\\n"}
403+
end
404+
';
405+
}
406+
--- request
407+
GET /t
408+
--- response_body
409+
hello!
410+
--- no_error_log
411+
[error]
412+

0 commit comments

Comments
 (0)