From: Dmitry Volyntsev Date: Wed, 19 Aug 2026 19:50:59 +0000 (-0700) Subject: Fetch: fix empty response status text handling X-Git-Tag: 1.0.1~1 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=a62feb4831e75c75c446298ca4a23862dcfcbab4;p=njs.git Fetch: fix empty response status text handling A status line with an empty reason phrase terminated by a bare LF left the status text start unset. The resulting invalid string slice crashed the worker when JavaScript read Response.statusText. Initialize both ends of an empty status text before returning from the parser. This also avoids subtracting NULL pointers for status lines without a reason phrase. --- diff --git a/nginx/ngx_js_http.c b/nginx/ngx_js_http.c index d2b7323a..7d2a6395 100644 --- a/nginx/ngx_js_http.c +++ b/nginx/ngx_js_http.c @@ -1264,6 +1264,11 @@ ngx_js_http_parse_status_line(ngx_js_http_parse_t *hp, ngx_buf_t *b) done: + if (hp->status_text == NULL) { + hp->status_text = p; + hp->status_text_end = p; + } + b->pos = p + 1; hp->state = sw_start; diff --git a/nginx/t/js_fetch.t b/nginx/t/js_fetch.t index f3601b82..4c23fcfb 100644 --- a/nginx/t/js_fetch.t +++ b/nginx/t/js_fetch.t @@ -181,12 +181,15 @@ $t->write_file('test.js', < @@ -472,7 +475,7 @@ EOF $t->try_run('no njs.fetch'); -$t->plan(41); +$t->plan(45); $t->run_daemon(\&http_daemon, port(8082)); $t->waitforsocket('127.0.0.1:' . port(8082)); @@ -503,6 +506,14 @@ like(http_get('/property?pr=statusText'), qr/200 OK.*OK$/s, 'fetch statusText OK'); like(http_get('/property?pr=statusText&code=403'), qr/200 OK.*Forbidden$/s, 'fetch statusText Forbidden'); +like(http_get('/property?pr=statusText&raw=status_text_empty_lf'), + qr/200 OK.*\x0d\x0a\x0d\x0a$/s, 'fetch empty statusText LF'); +like(http_get('/property?pr=statusText&raw=status_text_iis_lf'), + qr/200 OK.*\x0d\x0a\x0d\x0a$/s, 'fetch empty statusText IIS LF'); +like(http_get('/property?pr=statusText&raw=status_text_empty_crlf'), + qr/200 OK.*\x0d\x0a\x0d\x0a$/s, 'fetch empty statusText CRLF'); +like(http_get('/property?pr=statusText&raw=status_text_no_space_lf'), + qr/200 OK.*\x0d\x0a\x0d\x0a$/s, 'fetch empty statusText no space'); like(http_get('/property?pr=type'), qr/200 OK.*basic$/s, 'fetch type'); like(http_get('/header?loc=duplicate_header&h=BAR'), qr/200 OK.*"c"$/s, @@ -642,6 +653,13 @@ sub http_daemon { local $SIG{PIPE} = 'IGNORE'; + my %status_lines = ( + '/status_text_empty_lf' => "HTTP/1.1 200 \n", + '/status_text_iis_lf' => "HTTP/1.1 200.\n", + '/status_text_empty_crlf' => "HTTP/1.1 200 " . CRLF, + '/status_text_no_space_lf' => "HTTP/1.1 200\n", + ); + while (my $client = $server->accept()) { $client->autoflush(1); @@ -655,7 +673,14 @@ sub http_daemon { $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; - if ($uri eq '/status_line') { + if (exists $status_lines{$uri}) { + print $client + $status_lines{$uri} . + "Content-Length: 0" . CRLF . + "Connection: close" . CRLF . + CRLF; + + } elsif ($uri eq '/status_line') { print $client "HTTP/1.1 2A";