From f45f0683b1ec2b4db1c6d807f2446c86a33bc32e Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Sat, 13 Jun 2026 14:17:36 +0300 Subject: [PATCH] Reject negative string length in json_pack s#/+# format --- doc/apiref.rst | 4 +++- src/pack_unpack.c | 10 +++++++++- test/suites/api/test_pack.c | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/apiref.rst b/doc/apiref.rst index 924a72c48..7f812fc97 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -1535,7 +1535,9 @@ arguments. .. versionadded:: 2.11 ``s#`` (string) [const char \*, int] - Convert a UTF-8 buffer of a given length to a JSON string. + Convert a UTF-8 buffer of a given length to a JSON string. The + length must not be negative; a negative length results in a + ``json_error_invalid_argument`` error. .. versionadded:: 2.5 diff --git a/src/pack_unpack.c b/src/pack_unpack.c index 60d33c71d..5ce8a7a3e 100644 --- a/src/pack_unpack.c +++ b/src/pack_unpack.c @@ -173,7 +173,15 @@ static char *read_string(scanner_t *s, va_list *ap, const char *purpose, size_t next_token(s); if (token(s) == '#') { - length = va_arg(*ap, int); + int len = va_arg(*ap, int); + if (len < 0) { + set_error(s, "", json_error_invalid_argument, + "Invalid length for %s: %d", purpose, len); + s->has_error = 1; + length = 0; + } else { + length = (size_t)len; + } } else if (token(s) == '%') { length = va_arg(*ap, size_t); } else { diff --git a/test/suites/api/test_pack.c b/test/suites/api/test_pack.c index 865f60b68..94c9e0653 100644 --- a/test/suites/api/test_pack.c +++ b/test/suites/api/test_pack.c @@ -167,6 +167,12 @@ static void run_tests() { fail("json_pack string and length (int) refcount failed"); json_decref(value); + /* negative length (int) is rejected */ + if (json_pack_ex(&error, 0, "s#", "test", -2)) + fail("json_pack failed to catch negative length"); + check_error(json_error_invalid_argument, "Invalid length for string: -2", "", 1, + 2, 2); + /* string and length (size_t), non-NUL terminated string */ value = json_pack("s%", buffer, (size_t)4); if (!json_is_string(value) || strcmp("test", json_string_value(value)))