From 5e0deb7018b06cdebafab5570b2e9fdf7c3f22de Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 21 Jul 2026 04:35:57 +0100 Subject: [PATCH] Perl: fixed $r->print() zero copy with mutable scalars Since d9b7669666c8, the single-SV zero copy path in $r->print() no longer required the SV to be read-only. Reference counting introduced by that change keeps the SV alive, but not its string buffer: modifying a mutable scalar after $r->print() overwrites the buffer in place or reallocates it, while nginx might still have it queued in r->out, since small responses are postponed by ngx_http_write_filter(). This resulted in corrupted responses, and in freed memory being sent to the client when the scalar was grown. The SV is now required to be read-only again. Reference counting is still needed here, as a read-only SV in an eval() might be freed with the eval's op tree. --- src/http/modules/perl/nginx.xs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index af8549661..efbab280a 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -692,7 +692,7 @@ print(r, ...) if (items == 2) { /* - * do zero copy for prolate single SV: + * single read-only SV: * $r->print("some text\n"); */ @@ -702,7 +702,7 @@ print(r, ...) sv = SvRV(sv); } - if (SvPOK(sv)) { + if (SvREADONLY(sv) && SvPOK(sv)) { p = (u_char *) SvPV(sv, len); @@ -728,7 +728,7 @@ print(r, ...) b->end = b->last; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "$r->print: single SV: %z", len); + "$r->print: read-only SV: %z", len); goto out; }