[PATCH 1 of 2] Xslt: fixed vsnprintf() usage
Maxim Dounin
mdounin at mdounin.ru
Thu Feb 26 01:17:42 UTC 2026
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1772068486 -10800
# Thu Feb 26 04:14:46 2026 +0300
# Node ID 525677dd6b0a766fc61796ce4d74b5619132d33e
# Parent 125ca4a7d885b9c30f8745dccef669f29d91a68a
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.
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