diff --git a/ruby-4.0.3-Fix-a-format-string-injection-vulnerability.patch b/ruby-4.0.3-Fix-a-format-string-injection-vulnerability.patch new file mode 100644 index 0000000..a654e9e --- /dev/null +++ b/ruby-4.0.3-Fix-a-format-string-injection-vulnerability.patch @@ -0,0 +1,86 @@ +From 83dbd3f615bd8e7a31571124059eb3264f73c559 Mon Sep 17 00:00:00 2001 +From: Jean Boussier +Date: Wed, 18 Mar 2026 08:56:17 +0100 +Subject: [PATCH] Fix a format string injection vulnerability + +In `JSON.parse(doc, allow_duplicate_key: false)`. +--- + ext/json/parser/parser.c | 26 +++++++++++++++++++------- + test/json/json_parser_test.rb | 7 +++++++ + 2 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c +index 8f9729ef28..a05c5e9657 100644 +--- a/ext/json/parser/parser.c ++++ b/ext/json/parser/parser.c +@@ -400,14 +400,9 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state) + + #define PARSE_ERROR_FRAGMENT_LEN 32 + +-#ifdef RBIMPL_ATTR_NORETURN +-RBIMPL_ATTR_NORETURN() +-#endif +-static void raise_parse_error(const char *format, JSON_ParserState *state) ++static VALUE build_parse_error_message(const char *format, JSON_ParserState *state, long line, long column) + { + unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3]; +- long line, column; +- cursor_position(state, &line, &column); + + const char *ptr = "EOF"; + if (state->cursor && state->cursor < state->end) { +@@ -442,11 +437,23 @@ static void raise_parse_error(const char *format, JSON_ParserState *state) + VALUE msg = rb_sprintf(format, ptr); + VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column); + RB_GC_GUARD(msg); ++ return message; ++} + ++static VALUE parse_error_new(VALUE message, long line, long column) ++{ + VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message); + rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line)); + rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column)); +- rb_exc_raise(exc); ++ return exc; ++} ++ ++NORETURN(static) void raise_parse_error(const char *format, JSON_ParserState *state) ++{ ++ long line, column; ++ cursor_position(state, &line, &column); ++ VALUE message = build_parse_error_message(format, state, line, column); ++ rb_exc_raise(parse_error_new(message, line, column)); + } + + #ifdef RBIMPL_ATTR_NORETURN +@@ -896,6 +903,11 @@ static void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_k + rb_inspect(duplicate_key) + ); + ++ long line, column; ++ cursor_position(state, &line, &column); ++ rb_str_concat(message, build_parse_error_message("", state, line, column)) ; ++ rb_exc_raise(parse_error_new(message, line, column)); ++ + raise_parse_error(RSTRING_PTR(message), state); + RB_GC_GUARD(message); + } +diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb +index ec9391909d..61ea35d1f9 100644 +--- a/test/json/json_parser_test.rb ++++ b/test/json/json_parser_test.rb +@@ -411,6 +411,13 @@ def test_parse_duplicate_key + end + end + ++ def test_parse_duplicate_key_escape ++ error = assert_raise(ParserError) do ++ JSON.parse('{"%s%s%s%s":1,"%s%s%s%s":2}', allow_duplicate_key: false) ++ end ++ assert_match "%s%s%s%s", error.message ++ end ++ + def test_some_wrong_inputs + assert_raise(ParserError) { parse('[] bla') } + assert_raise(ParserError) { parse('[] 1') } diff --git a/ruby4.0.spec b/ruby4.0.spec index 09aad9e..887734f 100644 --- a/ruby4.0.spec +++ b/ruby4.0.spec @@ -335,6 +335,12 @@ Patch10: ruby-4.0.1-test_box-avoid-failure-with-program-suffix.patch # option in Ruby's main build. # https://github.com/brianmario/mysql2/issues/1201 Patch11: rubygem-mysql2-0.5.7-Disable-RPATH-completely-in-extconf.rb.patch +# CVE-2026-33210 +# Fix for Denial of Service or Information Disclosure +# via format string injection +# in Ruby JSON +# https://github.com/ruby/json/commit/393b41c3e5f87491e1e34fa59fa78ff6fa179a74 +Patch12: ruby-4.0.3-Fix-a-format-string-injection-vulnerability.patch %{?with_rubypick:Suggests: rubypick} @@ -498,6 +504,7 @@ popd %patch 7 -p1 %patch 8 -p1 %patch 10 -p1 +%patch 12 -p1 # Provide an example of usage of the tapset: cp -a %{SOURCE3} . @@ -1645,6 +1652,9 @@ make -C %{_vpath_builddir} runruby TESTRUN_SCRIPT=" \ - Fix ERB: Arbitrary code execution via deserialization bypass (CVE-2026-41316) Resolves: RHEL-170911 +- Fix JSON: Denial of Service or Information Disclosure via format string injection + (CVE-2026-33210) + Resolves: RHEL-169964 * Thu Feb 05 2026 Jarek Prokop - 4.0.1-33 - Initial package.