Skip to content

Commit 4dd7974

Browse files
committed
bugfix: lua panic handling in ngx.socket.tcp
If luaL_pushresult() encounters a buffer larger than 2GB, it triggers a Lua panic. This panic is handled by ngx_http_lua_atpanic(), which performs a longjmp() back to the last setjmp() call point (e.g., ngx_http_lua_log_by_chunk()), potentially causing a SEGFAULT or ABORT signal if stack protection is enabled. The fix sets the handler that manages Lua panics directly within ngx_http_lua_socket_push_input_data().
1 parent bdba93c commit 4dd7974

File tree

1 file changed

+46
-35
lines changed

1 file changed

+46
-35
lines changed

src/ngx_http_lua_socket_tcp.c

+46-35
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "ngx_http_lua_socket_tcp.h"
1414
#include "ngx_http_lua_input_filters.h"
1515
#include "ngx_http_lua_util.h"
16+
#include "ngx_http_lua_exception.h"
1617
#include "ngx_http_lua_uthread.h"
1718
#include "ngx_http_lua_output.h"
1819
#include "ngx_http_lua_contentby.h"
@@ -5912,62 +5913,72 @@ ngx_http_lua_socket_push_input_data(ngx_http_request_t *r,
59125913
size_t nbufs;
59135914
luaL_Buffer luabuf;
59145915

5915-
dd("bufs_in: %p, buf_in: %p", u->bufs_in, u->buf_in);
5916+
/* set Lua VM panic handler */
5917+
lua_atpanic(L, ngx_http_lua_atpanic);
59165918

5917-
nbufs = 0;
5918-
ll = NULL;
5919+
NGX_LUA_EXCEPTION_TRY {
59195920

5920-
luaL_buffinit(L, &luabuf);
5921+
dd("bufs_in: %p, buf_in: %p", u->bufs_in, u->buf_in);
59215922

5922-
for (cl = u->bufs_in; cl; cl = cl->next) {
5923-
b = cl->buf;
5924-
chunk_size = b->last - b->pos;
5923+
nbufs = 0;
5924+
ll = NULL;
5925+
5926+
luaL_buffinit(L, &luabuf);
59255927

5926-
dd("copying input data chunk from %p: \"%.*s\"", cl,
5927-
(int) chunk_size, b->pos);
5928+
for (cl = u->bufs_in; cl; cl = cl->next) {
5929+
b = cl->buf;
5930+
chunk_size = b->last - b->pos;
59285931

5929-
luaL_addlstring(&luabuf, (char *) b->pos, chunk_size);
5932+
dd("copying input data chunk from %p: \"%.*s\"", cl,
5933+
(int) chunk_size, b->pos);
59305934

5931-
if (cl->next) {
5932-
ll = &cl->next;
5933-
}
5935+
luaL_addlstring(&luabuf, (char *) b->pos, chunk_size);
5936+
5937+
if (cl->next) {
5938+
ll = &cl->next;
5939+
}
59345940

59355941
#if (DDEBUG) || (NGX_DTRACE)
5936-
size += chunk_size;
5942+
size += chunk_size;
59375943
#endif
59385944

5939-
nbufs++;
5940-
}
5945+
nbufs++;
5946+
}
59415947

5942-
luaL_pushresult(&luabuf);
5948+
luaL_pushresult(&luabuf);
59435949

59445950
#if (DDEBUG)
5945-
dd("size: %d, nbufs: %d", (int) size, (int) nbufs);
5951+
dd("size: %d, nbufs: %d", (int) size, (int) nbufs);
59465952
#endif
59475953

59485954
#if (NGX_DTRACE)
5949-
ngx_http_lua_probe_socket_tcp_receive_done(r, u,
5950-
(u_char *) lua_tostring(L, -1),
5951-
size);
5955+
ngx_http_lua_probe_socket_tcp_receive_done(
5956+
r, u, (u_char *) lua_tostring(L, -1), size);
59525957
#endif
59535958

5954-
if (nbufs > 1 && ll) {
5955-
dd("recycle buffers: %d", (int) (nbufs - 1));
5959+
if (nbufs > 1 && ll) {
5960+
dd("recycle buffers: %d", (int) (nbufs - 1));
59565961

5957-
*ll = ctx->free_recv_bufs;
5958-
ctx->free_recv_bufs = u->bufs_in;
5959-
u->bufs_in = u->buf_in;
5960-
}
5962+
*ll = ctx->free_recv_bufs;
5963+
ctx->free_recv_bufs = u->bufs_in;
5964+
u->bufs_in = u->buf_in;
5965+
}
59615966

5962-
if (u->buffer.pos == u->buffer.last) {
5963-
dd("resetting u->buffer pos & last");
5964-
u->buffer.pos = u->buffer.start;
5965-
u->buffer.last = u->buffer.start;
5966-
}
5967+
if (u->buffer.pos == u->buffer.last) {
5968+
dd("resetting u->buffer pos & last");
5969+
u->buffer.pos = u->buffer.start;
5970+
u->buffer.last = u->buffer.start;
5971+
}
59675972

5968-
if (u->bufs_in) {
5969-
u->buf_in->buf->last = u->buffer.pos;
5970-
u->buf_in->buf->pos = u->buffer.pos;
5973+
if (u->bufs_in) {
5974+
u->buf_in->buf->last = u->buffer.pos;
5975+
u->buf_in->buf->pos = u->buffer.pos;
5976+
}
5977+
5978+
} NGX_LUA_EXCEPTION_CATCH {
5979+
5980+
dd("nginx execution restored");
5981+
return NGX_ERROR;
59715982
}
59725983
}
59735984

0 commit comments

Comments
 (0)