details: https://hg.nginx.org/njs/rev/1d13f6e877ad branches: changeset: 2236:1d13f6e877ad user: Dmitry Volyntsev <xei...@nginx.com> date: Tue Nov 21 08:57:03 2023 -0800 description: Modules: fixed js_set with Buffer values.
Previously, a Buffer value which contains invalid UTF-8 when returned as a value for js_set handler was mangled because the bytes value was converted to a string value. The fix is to use bytes value of Buffer, TypedArray and ArrayBuffer as is, and not convert it to a string first. diffstat: nginx/ngx_http_js_module.c | 8 +++--- nginx/ngx_stream_js_module.c | 8 +++--- nginx/t/js.t | 28 ++++++++++++++++++++++++-- nginx/t/stream_js.t | 45 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 14 deletions(-) diffs (243 lines): diff -r 8e024f36e38e -r 1d13f6e877ad nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Nov 21 06:49:30 2023 -0800 +++ b/nginx/ngx_http_js_module.c Tue Nov 21 08:57:03 2023 -0800 @@ -1250,7 +1250,7 @@ ngx_http_js_variable_set(ngx_http_reques ngx_int_t rc; njs_int_t pending; - ngx_str_t value; + njs_str_t value; ngx_http_js_ctx_t *ctx; rc = ngx_http_js_init_vm(r, ngx_http_js_request_proto_id); @@ -1285,15 +1285,15 @@ ngx_http_js_variable_set(ngx_http_reques return NGX_ERROR; } - if (ngx_js_retval(ctx->vm, &ctx->retval, &value) != NGX_OK) { + if (ngx_js_string(ctx->vm, njs_value_arg(&ctx->retval), &value) != NGX_OK) { return NGX_ERROR; } - v->len = value.len; + v->len = value.length; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - v->data = value.data; + v->data = value.start; return NGX_OK; } diff -r 8e024f36e38e -r 1d13f6e877ad nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue Nov 21 06:49:30 2023 -0800 +++ b/nginx/ngx_stream_js_module.c Tue Nov 21 08:57:03 2023 -0800 @@ -914,7 +914,7 @@ ngx_stream_js_variable_set(ngx_stream_se ngx_int_t rc; njs_int_t pending; - ngx_str_t value; + njs_str_t value; ngx_stream_js_ctx_t *ctx; rc = ngx_stream_js_init_vm(s, ngx_stream_js_session_proto_id); @@ -949,15 +949,15 @@ ngx_stream_js_variable_set(ngx_stream_se return NGX_ERROR; } - if (ngx_js_retval(ctx->vm, &ctx->retval, &value) != NGX_OK) { + if (ngx_js_string(ctx->vm, njs_value_arg(&ctx->retval), &value) != NGX_OK) { return NGX_ERROR; } - v->len = value.len; + v->len = value.length; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - v->data = value.data; + v->data = value.start; return NGX_OK; } diff -r 8e024f36e38e -r 1d13f6e877ad nginx/t/js.t --- a/nginx/t/js.t Tue Nov 21 06:49:30 2023 -0800 +++ b/nginx/t/js.t Tue Nov 21 08:57:03 2023 -0800 @@ -46,6 +46,7 @@ http { js_set $test_global test.global_obj; js_set $test_log test.log; js_set $test_internal test.sub_internal; + js_set $buffer test.buffer; js_set $test_except test.except; js_import test.js; @@ -95,6 +96,10 @@ http { js_content test.status; } + location /buffer_variable { + js_content test.buffer_variable; + } + location /request_body { js_content test.request_body; } @@ -171,6 +176,10 @@ EOF return 'variable=' + r.variables.remote_addr; } + function buffer(r) { + return Buffer.from([0xaa, 0xbb, 0xcc, 0xdd]); + } + function global_obj(r) { return 'global=' + global; } @@ -225,6 +234,10 @@ EOF r.log('SEE-LOG'); } + function buffer_variable(r) { + r.return(200, r.rawVariables.buffer.toString('hex')); + } + async function internal(r) { let reply = await r.subrequest('/sub_internal'); @@ -248,14 +261,15 @@ EOF function content_empty(r) { } - export default {njs:test_njs, method, version, addr, uri, + export default {njs:test_njs, method, version, addr, uri, buffer, variable, global_obj, status, request_body, internal, request_body_cache, send, return_method, sub_internal, - type, log, except, content_except, content_empty}; + type, log, buffer_variable, except, content_except, + content_empty}; EOF -$t->try_run('no njs available')->plan(27); +$t->try_run('no njs available')->plan(28); ############################################################################### @@ -307,6 +321,14 @@ like(http_get('/internal'), qr/parent: f } + +TODO: { +local $TODO = 'not yet' unless has_version('0.8.3'); + +like(http_get('/buffer_variable'), qr/aabbccdd/, 'buffer variable'); + +} + http_get('/except'); http_get('/content_except'); diff -r 8e024f36e38e -r 1d13f6e877ad nginx/t/stream_js.t --- a/nginx/t/stream_js.t Tue Nov 21 06:49:30 2023 -0800 +++ b/nginx/t/stream_js.t Tue Nov 21 08:57:03 2023 -0800 @@ -68,6 +68,7 @@ stream { js_set $js_req_line test.req_line; js_set $js_sess_unk test.sess_unk; js_set $js_async test.asyncf; + js_set $js_buffer test.buffer; js_import test.js; @@ -190,6 +191,11 @@ stream { listen 127.0.0.1:8100; return $js_async; } + + server { + listen 127.0.0.1:8101; + return $js_buffer; + } } EOF @@ -211,8 +217,13 @@ EOF return 'sess_unk=' + s.unk; } + function buffer(s) { + return Buffer.from([0xaa, 0xbb, 0xcc, 0xdd]); + } + function log(s) { s.log("SEE-THIS"); + return 'log'; } var res = ''; @@ -377,12 +388,13 @@ EOF preread_step, filter_step, access_undecided, access_allow, access_deny, preread_async, preread_data, preread_req_line, req_line, filter_empty, filter_header_inject, filter_search, - access_except, preread_except, filter_except, asyncf}; + access_except, preread_except, filter_except, asyncf, + buffer}; EOF $t->run_daemon(\&stream_daemon, port(8090)); -$t->try_run('no stream njs available')->plan(23); +$t->try_run('no stream njs available')->plan(24); $t->waitforsocket('127.0.0.1:' . port(8090)); ############################################################################### @@ -391,7 +403,7 @@ is(stream('127.0.0.1:' . port(8080))->re 's.remoteAddress'); is(dgram('127.0.0.1:' . port(8985))->io('.'), 'addr=127.0.0.1', 's.remoteAddress udp'); -is(stream('127.0.0.1:' . port(8081))->read(), 'undefined', 's.log'); +is(stream('127.0.0.1:' . port(8081))->read(), 'log', 's.log'); is(stream('127.0.0.1:' . port(8082))->read(), 'variable=127.0.0.1', 's.variables'); is(stream('127.0.0.1:' . port(8083))->read(), '', 'stream js unknown function'); @@ -417,6 +429,14 @@ stream('127.0.0.1:' . port(8099))->io('x is(stream('127.0.0.1:' . port(8100))->read(), 'retval: 30', 'asyncf'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.3'); + +like(stream('127.0.0.1:' . port(8101))->read(), qr/\xaa\xbb\xcc\xdd/, + 'buffer variable'); + +} + $t->stop(); ok(index($t->read_file('error.log'), 'SEE-THIS') > 0, 'stream js log'); @@ -432,6 +452,25 @@ like($t->read_file('status.log'), qr/$p[ ############################################################################### +sub has_version { + my $need = shift; + + get('/njs') =~ /^([.0-9]+)$/m; + + my @v = split(/\./, $1); + my ($n, $v); + + for $n (split(/\./, $need)) { + $v = shift @v || 0; + return 0 if $n > $v; + return 1 if $v > $n; + } + + return 1; +} + +############################################################################### + sub stream_daemon { my $server = IO::Socket::INET->new( Proto => 'tcp', _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel