From b9371ef17d94e53cdc84c7d4e2c157903287fb1c Mon Sep 17 00:00:00 2001 From: Affan Ziya Date: Wed, 4 Nov 2026 14:47:54 +0530 Subject: [PATCH] xml BUGFIX reject character references that overflow The code point of a character reference was accumulated in a uint32_t without a bound, so a reference with enough digits wrapped around before ly_pututf8() checked its range. � and � were both decoded to '<' instead of being rejected as out of range. --- src/xml.c | 10 ++++++++++ tests/utests/basic/test_xml.c | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/xml.c b/src/xml.c index 881385a284..54acc4d8fd 100644 --- a/src/xml.c +++ b/src/xml.c @@ -516,10 +516,20 @@ lyxml_parse_value(struct lyxml_ctx *xmlctx, char endchar, char **value, uint32_t ADD_CHECK_OVERFLOW(offset, 1, error); if (isdigit(in[offset])) { for (n = 0; isdigit(in[offset]); offset++) { + if (n > 0x10ffff) { + /* too large, would overflow */ + LOGVAL(ctx, NULL, LYVE_SYNTAX, "Invalid character reference \"%.12s\".", p); + goto error; + } n = (LY_BASE_DEC * n) + (in[offset] - '0'); } } else if ((in[offset] == 'x') && isxdigit(in[offset + 1])) { for (n = 0, ++offset; isxdigit(in[offset]); offset++) { + if (n > 0x10ffff) { + /* too large, would overflow */ + LOGVAL(ctx, NULL, LYVE_SYNTAX, "Invalid character reference \"%.12s\".", p); + goto error; + } if (isdigit(in[offset])) { u = (in[offset] - '0'); } else if (in[offset] > 'F') { diff --git a/tests/utests/basic/test_xml.c b/tests/utests/basic/test_xml.c index 5712f34685..c47adbf827 100644 --- a/tests/utests/basic/test_xml.c +++ b/tests/utests/basic/test_xml.c @@ -268,6 +268,22 @@ test_text(void **state) str = "�"; + assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, str, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); + CHECK_LOG_CTX("Invalid character reference \"�\".", NULL, 1); + + /* leading zeros are fine */ + str = "<<"; + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, str, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); + assert_non_null(tree); + lyd_free_all(tree); + tree = NULL; } static void