[nginx] Xslt: fixed vsnprintf() usage.
Maxim Dounin
mdounin at mdounin.ru
Fri Mar 6 04:23:33 UTC 2026
details: http://freenginx.org/hg/nginx/rev/2dbab7b19453
branches:
changeset: 9471:2dbab7b19453
user: Maxim Dounin <mdounin at mdounin.ru>
date: Fri Mar 06 07:11:33 2026 +0300
description:
Xslt: fixed vsnprintf() usage.
Previously, vsnprintf(), as used to handle error messages from the
libxml2 library in ngx_http_xslt_sax_error(), was used incorrectly: the
code assumed that vsnprintf() returns the number of bytes actually
printed, and never fails. But vsnprintf(), as originally introduced in
4.4BSD and later standardized in C99, returns the number of characters
that would have been written with a sufficiently large buffer, and "if
the return value is greater than or equal to the size argument, the
string was too short and some of the printed characters were discarded".
Additionally, vsnprintf() might theoretically result in a zero-length
error message, or might fail (for example, due to an incorrect format
specification in libxml2). Most notably, this can result in
out-of-bounds reads and segmentation faults in the worker process on
very long error messages.
The fix is to check the value returned by vsnprintf() and properly
handle too long error messages, as well as zero-length error messages
and vsnprintf() failures.
diffstat:
src/http/modules/ngx_http_xslt_filter_module.c | 21 +++++++++++++++++----
1 files changed, 17 insertions(+), 4 deletions(-)
diffs (44 lines):
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -540,23 +540,36 @@ ngx_http_xslt_sax_error(void *data, cons
{
xmlParserCtxtPtr ctxt = data;
- size_t n;
+ int n;
va_list args;
+ ngx_uint_t truncated;
ngx_http_xslt_filter_ctx_t *ctx;
u_char buf[NGX_MAX_ERROR_STR];
ctx = ctxt->sax->_private;
buf[0] = '\0';
+ truncated = 0;
va_start(args, msg);
- n = (size_t) vsnprintf((char *) buf, NGX_MAX_ERROR_STR, msg, args);
+ n = vsnprintf((char *) buf, NGX_MAX_ERROR_STR, msg, args);
va_end(args);
- while (--n && (buf[n] == CR || buf[n] == LF)) { /* void */ }
+ if (n < 0) {
+ n = 0;
+ truncated = 1;
+ }
+
+ if (n >= NGX_MAX_ERROR_STR) {
+ n = NGX_MAX_ERROR_STR - 1;
+ truncated = 1;
+ }
+
+ while (n && (buf[n - 1] == CR || buf[n - 1] == LF)) { n--; }
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
- "libxml2 error: \"%*s\"", n + 1, buf);
+ "libxml2 error: \"%*s%s\"",
+ (size_t) n, buf, truncated ? "..." : "");
}
More information about the nginx-devel
mailing list