-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix various memory corruption and unwanted behavior scenarios #591
base: master
Are you sure you want to change the base?
Changes from 13 commits
b6ad5a6
11b8387
4c37623
14514b6
00fdb66
a5a1352
aece64f
579ac29
86eae8b
713fbcb
d19723c
035d7c5
9dfdc24
4bdc0f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -671,10 +671,10 @@ static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_buf_t *buf, int | |
//move the msg pool | ||
d->pool = fsub->publisher.msg_pool; | ||
d->msgbuf = buf; | ||
d->subrequest = NULL; | ||
fsub->publisher.msg_pool = NULL; | ||
|
||
if(fsub->publisher.intercept || fsub->publisher.upstream_request_url == NULL) { // don't need to send request upstream | ||
d->subrequest = NULL; | ||
websocket_publish_continue(d); | ||
} | ||
else { | ||
|
@@ -1086,11 +1086,13 @@ static ngx_int_t websocket_perform_handshake(full_subscriber_t *fsub) { | |
|
||
static void websocket_reading(ngx_http_request_t *r); | ||
|
||
static ngx_buf_t *websocket_inflate_message(full_subscriber_t *fsub, ngx_buf_t *msgbuf, ngx_pool_t *pool) { | ||
static ngx_buf_t *websocket_inflate_message(full_subscriber_t *fsub, ngx_buf_t *msgbuf, ngx_pool_t *pool, uint64_t max, int *result) { | ||
#if (NGX_ZLIB) | ||
z_stream *strm; | ||
int rc; | ||
ngx_buf_t *outbuf; | ||
|
||
*result = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops... fixed |
||
|
||
if(fsub->deflate.zstream_in == NULL) { | ||
if((fsub->deflate.zstream_in = ngx_calloc(sizeof(*strm), ngx_cycle->log)) == NULL) { | ||
|
@@ -1115,7 +1117,7 @@ static ngx_buf_t *websocket_inflate_message(full_subscriber_t *fsub, ngx_buf_t * | |
|
||
strm = fsub->deflate.zstream_in; | ||
|
||
outbuf = nchan_inflate(strm, msgbuf, fsub->sub.request, pool); | ||
outbuf = nchan_inflate(strm, msgbuf, fsub->sub.request, pool, max, result); | ||
return outbuf; | ||
#else | ||
return NULL; | ||
|
@@ -1304,6 +1306,8 @@ static void websocket_reading(ngx_http_request_t *r) { | |
ngx_connection_t *c; | ||
ngx_buf_t *msgbuf, buf; | ||
//ngx_str_t msg_in_str; | ||
ngx_http_core_loc_conf_t *clcf; | ||
int result; | ||
retry: | ||
ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); | ||
fsub = (full_subscriber_t *)ctx->sub; | ||
|
@@ -1468,8 +1472,15 @@ static void websocket_reading(ngx_http_request_t *r) { | |
return websocket_reading_finalize(r); | ||
} | ||
|
||
//TODO: check max websocket message length | ||
clcf = ngx_http_get_module_loc_conf(ctx->sub->request, ngx_http_core_module); | ||
|
||
if(frame->payload == NULL) { | ||
if(clcf->client_max_body_size && (uint64_t)clcf->client_max_body_size < frame->payload_len) { | ||
websocket_send_close_frame_cstr(fsub, CLOSE_POLICY_VIOLATION, "Message too large."); | ||
ws_destroy_msgpool(fsub); | ||
fsub->publisher.msg_pool = NULL; | ||
return websocket_reading_finalize(r); | ||
} | ||
if(ws_get_msgpool(fsub) == NULL) { | ||
ERR("failed to get msgpool"); | ||
websocket_send_close_frame(fsub, CLOSE_INTERNAL_SERVER_ERROR, NULL); | ||
|
@@ -1486,6 +1497,13 @@ static void websocket_reading(ngx_http_request_t *r) { | |
} | ||
|
||
set_buffer(&buf, frame->payload, frame->last, frame->payload_len); | ||
if(clcf->client_max_body_size && clcf->client_max_body_size < ngx_buf_size(&buf)) { | ||
websocket_send_close_frame_cstr(fsub, CLOSE_POLICY_VIOLATION, "Message too large."); | ||
ws_destroy_msgpool(fsub); | ||
fsub->publisher.msg_pool = NULL; | ||
return websocket_reading_finalize(r); | ||
} | ||
|
||
|
||
if (frame->payload_len > 0 && (rc = ws_recv(c, rev, &buf, frame->payload_len)) != NGX_OK) { | ||
DBG("ws_recv NOT OK when receiving payload, but that's ok"); | ||
|
@@ -1513,7 +1531,12 @@ static void websocket_reading(ngx_http_request_t *r) { | |
|
||
//inflate message if needed | ||
if(fsub->deflate.enabled && frame->rsv1) { | ||
if((msgbuf = websocket_inflate_message(fsub, msgbuf, ws_get_msgpool(fsub))) == NULL) { | ||
if((msgbuf = websocket_inflate_message(fsub, msgbuf, ws_get_msgpool(fsub), (uint64_t)clcf->client_max_body_size, &result)) == NULL) { | ||
if(result == -1) { | ||
websocket_send_close_frame_cstr(fsub, CLOSE_POLICY_VIOLATION, "Message too large."); | ||
ws_destroy_msgpool(fsub); | ||
return websocket_reading_finalize(r); | ||
} | ||
websocket_send_close_frame_cstr(fsub, CLOSE_INVALID_PAYLOAD, "Invalid permessage-deflate data"); | ||
ws_destroy_msgpool(fsub); | ||
return websocket_reading_finalize(r); | ||
|
@@ -1577,7 +1600,7 @@ static void websocket_reading(ngx_http_request_t *r) { | |
|
||
static ngx_flag_t is_utf8(ngx_buf_t *buf) { | ||
|
||
u_char *p; | ||
u_char *p, *op; | ||
size_t n; | ||
|
||
u_char c, *last; | ||
|
@@ -1599,6 +1622,7 @@ static ngx_flag_t is_utf8(ngx_buf_t *buf) { | |
} | ||
|
||
last = p + n; | ||
op = p; | ||
|
||
for (len = 0; p < last; len++) { | ||
c = *p; | ||
|
@@ -1611,13 +1635,13 @@ static ngx_flag_t is_utf8(ngx_buf_t *buf) { | |
if (ngx_utf8_decode(&p, last - p) > 0x10ffff) { | ||
/* invalid UTF-8 */ | ||
if(mmapped) { | ||
munmap(p, n); | ||
munmap(op, n); | ||
} | ||
return 0; | ||
} | ||
} | ||
if(mmapped) { | ||
munmap(p, n); | ||
munmap(op, n); | ||
} | ||
return 1; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The caller below expects
*result
to be initialized if the return value isNULL
. However, there appear to be three (rare?) cases below where this does not happen.Also a
-1
magic number for "message too large" is a bit ugly, and it may be better to follow a pattern where the primary return value indicates whether/how the call is successful and the pointer is returned via indirection (ngx_buf_t **result
).