diff --git a/rubygem-nokogiri-1.13.3-CVE-2022-24836-backport.patch b/rubygem-nokogiri-1.13.3-CVE-2022-24836-backport.patch new file mode 100644 index 0000000..6e61a18 --- /dev/null +++ b/rubygem-nokogiri-1.13.3-CVE-2022-24836-backport.patch @@ -0,0 +1,42 @@ +commit e444525ef1634b675cd1cf52d39f4320ef0aecfd +Author: Mike Dalessio +Date: Sun Apr 10 14:42:04 2022 -0400 + + fix(perf): HTML4::EncodingReader detection + +diff --git a/lib/nokogiri/html4/document.rb b/lib/nokogiri/html4/document.rb +index 177efc04..fbc22d20 100644 +--- a/lib/nokogiri/html/document.rb ++++ b/lib/nokogiri/html/document.rb +@@ -268,7 +268,7 @@ module Nokogiri + end + + def self.detect_encoding(chunk) +- m = chunk.match(/\A(<\?xml[ \t\r\n]+[^>]*>)/) and ++ m = chunk.match(/\A(<\?xml[ \t\r\n][^>]*>)/) and + return Nokogiri.XML(m[1]).encoding + + if Nokogiri.jruby? +diff --git a/test/html4/test_document_encoding.rb b/test/html4/test_document_encoding.rb +index 61153017..ecb4aa9a 100644 +--- a/test/html/test_document_encoding.rb ++++ b/test/html/test_document_encoding.rb +@@ -155,6 +155,18 @@ class TestNokogiriHtmlDocument < Nokogiri::TestCase + end + end + end ++ ++ it "does not start backtracking during detection of XHTML encoding" do ++ # this test is a quick and dirty version ++ # of the more complete perf test that is on main. ++ n = 40_000 ++ redos_string = " +Date: Fri, 6 May 2022 21:57:41 -0400 +Subject: [PATCH] fix: {HTML4,XML}::SAX::{Parser,ParserContext} check arg types + +Previously, arguments of the wrong type might cause segfault on CRuby. +--- + CHANGELOG.md | 3 ++- + ext/java/nokogiri/Html4SaxParserContext.java | 11 +++++++++++ + ext/java/nokogiri/XmlSaxParserContext.java | 7 +++++-- + ext/java/nokogiri/internals/ParserContext.java | 8 +++++++- + ext/nokogiri/html4_sax_parser_context.c | 5 ++--- + ext/nokogiri/xml_sax_parser_context.c | 13 ++++++++++--- + lib/nokogiri/html4/sax/parser.rb | 2 +- + test/html4/sax/test_parser.rb | 8 +++++++- + test/html4/sax/test_parser_context.rb | 9 +++++++++ + test/xml/sax/test_parser.rb | 8 +++++++- + test/xml/sax/test_parser_context.rb | 7 +++++++ + 11 files changed, 68 insertions(+), 13 deletions(-) + +diff --git a/ext/nokogiri/html_sax_parser_context.c b/ext/nokogiri/html_sax_parser_context.c +index dec0d88fe..54adca4cb 100644 +--- a/ext/nokogiri/html_sax_parser_context.c ++++ b/ext/nokogiri/html_sax_parser_context.c +@@ -19,9 +19,8 @@ parse_memory(VALUE klass, VALUE data, VALUE encoding) + { + htmlParserCtxtPtr ctxt; + +- if (NIL_P(data)) { +- rb_raise(rb_eArgError, "data cannot be nil"); +- } ++ Check_Type(data, T_STRING); ++ + if (!(int)RSTRING_LEN(data)) { + rb_raise(rb_eRuntimeError, "data cannot be empty"); + } +diff --git a/ext/nokogiri/xml_sax_parser_context.c b/ext/nokogiri/xml_sax_parser_context.c +index 60449347a..60c491984 100644 +--- a/ext/nokogiri/xml_sax_parser_context.c ++++ b/ext/nokogiri/xml_sax_parser_context.c +@@ -2,6 +2,8 @@ + + VALUE cNokogiriXmlSaxParserContext ; + ++static ID id_read; ++ + static void + deallocate(xmlParserCtxtPtr ctxt) + { +@@ -26,6 +28,10 @@ parse_io(VALUE klass, VALUE io, VALUE encoding) + xmlParserCtxtPtr ctxt; + xmlCharEncoding enc = (xmlCharEncoding)NUM2INT(encoding); + ++ if (!rb_respond_to(io, id_read)) { ++ rb_raise(rb_eTypeError, "argument expected to respond to :read"); ++ } ++ + ctxt = xmlCreateIOParserCtxt(NULL, NULL, + (xmlInputReadCallback)noko_io_read, + (xmlInputCloseCallback)noko_io_close, +@@ -62,9 +68,8 @@ parse_memory(VALUE klass, VALUE data) + { + xmlParserCtxtPtr ctxt; + +- if (NIL_P(data)) { +- rb_raise(rb_eArgError, "data cannot be nil"); +- } ++ Check_Type(data, T_STRING); ++ + if (!(int)RSTRING_LEN(data)) { + rb_raise(rb_eRuntimeError, "data cannot be empty"); + } +@@ -278,4 +283,6 @@ noko_init_xml_sax_parser_context() + rb_define_method(cNokogiriXmlSaxParserContext, "recovery", get_recovery, 0); + rb_define_method(cNokogiriXmlSaxParserContext, "line", line, 0); + rb_define_method(cNokogiriXmlSaxParserContext, "column", column, 0); ++ ++ id_read = rb_intern("read"); + } +diff --git a/lib/nokogiri/html/sax/parser.rb b/lib/nokogiri/html4/sax/parser.rb +index 2a074b6b9..1f8c03af6 100644 +--- a/lib/nokogiri/html/sax/parser.rb ++++ b/lib/nokogiri/html/sax/parser.rb +@@ -28,7 +28,7 @@ class Parser < Nokogiri::XML::SAX::Parser + ### + # Parse html stored in +data+ using +encoding+ + def parse_memory data, encoding = 'UTF-8' +- raise ArgumentError unless data ++ raise TypeError unless String === data + return unless data.length > 0 + ctx = ParserContext.memory(data, encoding) + yield ctx if block_given? +diff --git a/test/html/sax/test_parser.rb b/test/html/sax/test_parser.rb +index 3917dce2e..4dc6ac61f 100644 +--- a/test/html/sax/test_parser.rb ++++ b/test/html/sax/test_parser.rb +@@ -54,7 +54,7 @@ def test_parse_file_with_dir + end + + def test_parse_memory_nil +- assert_raise ArgumentError do ++ assert_raise TypeError do + @parser.parse_memory(nil) + end + end +@@ -161,6 +161,12 @@ def test_parsing_dom_error_from_io + def test_empty_processing_instruction + @parser.parse_memory("this will segfault") + end ++ ++ it "handles invalid types gracefully" do ++ assert_raises(TypeError) { Nokogiri::HTML::SAX::Parser.new.parse(0xcafecafe) } ++ assert_raises(TypeError) { Nokogiri::HTML::SAX::Parser.new.parse_memory(0xcafecafe) } ++ assert_raises(TypeError) { Nokogiri::HTML::SAX::Parser.new.parse_io(0xcafecafe) } ++ end + end + end + end +diff --git a/test/html/sax/test_parser_context.rb b/test/html/sax/test_parser_context.rb +index 0a0eda64c..594a3ac82 100644 +--- a/test/html/sax/test_parser_context.rb ++++ b/test/html/sax/test_parser_context.rb +@@ -40,6 +40,15 @@ def test_from_file + ctx.parse_with parser + # end + end ++ ++ def test_graceful_handling_of_invalid_types ++ assert_raises(TypeError) { ParserContext.new(0xcafecafe) } ++ assert_raises(TypeError) { ParserContext.memory(0xcafecafe, "UTF-8") } ++ assert_raises(TypeError) { ParserContext.io(0xcafecafe, 1) } ++ assert_raises(TypeError) { ParserContext.io(StringIO.new("asdf"), "should be an index into ENCODINGS") } ++ assert_raises(TypeError) { ParserContext.file(0xcafecafe, "UTF-8") } ++ assert_raises(TypeError) { ParserContext.file("path/to/file", 0xcafecafe) } ++ end + end + end + end +diff --git a/test/xml/sax/test_parser.rb b/test/xml/sax/test_parser.rb +index 6c0f1fc88..ac7d4ead0 100644 +--- a/test/xml/sax/test_parser.rb ++++ b/test/xml/sax/test_parser.rb +@@ -73,6 +73,12 @@ class TestCase + end + end + ++ def test_graceful_handling_of_invalid_types ++ assert_raises(TypeError) { Nokogiri::XML::SAX::Parser.new.parse(0xcafecafe) } ++ assert_raises(TypeError) { Nokogiri::XML::SAX::Parser.new.parse_memory(0xcafecafe) } ++ assert_raises(TypeError) { Nokogiri::XML::SAX::Parser.new.parse_io(0xcafecafe) } ++ end ++ + def test_namespace_declaration_order_is_saved + @parser.parse(<<~eoxml) + +@@ -263,7 +269,7 @@ def call_parse_io_with_encoding(encoding) + end + + def test_render_parse_nil_param +- assert_raises(ArgumentError) { @parser.parse_memory(nil) } ++ assert_raises(TypeError) { @parser.parse_memory(nil) } + end + + def test_bad_encoding_args +diff --git a/test/xml/sax/test_parser_context.rb b/test/xml/sax/test_parser_context.rb +index e38efd271..ba9857943 100644 +--- a/test/xml/sax/test_parser_context.rb ++++ b/test/xml/sax/test_parser_context.rb +@@ -6,6 +6,13 @@ + assert_equal true, pc.recovery + end + ++ def test_graceful_handling_of_invalid_types ++ assert_raises(TypeError) { ParserContext.new(0xcafecafe) } ++ assert_raises(TypeError) { ParserContext.memory(0xcafecafe) } ++ assert_raises(TypeError) { ParserContext.io(0xcafecafe, 1) } ++ assert_raises(TypeError) { ParserContext.io(StringIO.new("asdf"), "should be an index into ENCODINGS") } ++ end ++ + def test_from_io + ctx = ParserContext.new StringIO.new('fo'), 'UTF-8' + assert ctx diff --git a/rubygem-nokogiri.spec b/rubygem-nokogiri.spec index 4a3b320..b631b2f 100644 --- a/rubygem-nokogiri.spec +++ b/rubygem-nokogiri.spec @@ -1,7 +1,7 @@ %global mainver 1.11.7 #%%global prever .rc4 -%global mainrel 1 +%global mainrel 3 %global prerpmver %(echo "%{?prever}" | sed -e 's|\\.||g') %global gem_name nokogiri @@ -24,6 +24,12 @@ Source2: nokogiri-create-full-tarball.sh #Patch0: rubygem-nokogiri-1.5.0-allow-non-crosscompile.patch # Shut down libxml2 version unmatching warning Patch0: %{name}-1.11.0.rc4-shutdown-libxml2-warning.patch +# https://github.com/sparklemotion/nokogiri/commit/e444525ef1634b675cd1cf52d39f4320ef0aecfd +# Fix for CVE-2022-24836, backported +Patch1: %{name}-1.13.3-CVE-2022-24836-backport.patch +# https://github.com/sparklemotion/nokogiri/commit/db05ba9a1bd4b90aa6c76742cf6102a7c7297267 +# Fix for CVE-2022-24836, backported +Patch2: %{name}-1.13.5-6-CVE-2022-29181-backport.patch BuildRequires: ruby(release) BuildRequires: ruby(rubygems) ## @@ -81,7 +87,14 @@ This package provides non-Gem support for %{gem_name}. mv ../%{gem_name}-%{version}.gemspec . # patches +( +cd %{gem_name}-%{version}/ %patch0 -p1 +%patch1 -p1 +%patch2 -p1 +cd .. +cp -a %{gem_name}-%{version}/{lib,ext} . +) # remove bundled external libraries sed -i \ @@ -174,6 +187,12 @@ sed -i test/helper.rb \ sed -i '/require..minitest.reporters./ s/^/#/' test/helper.rb sed -i '/Minitest::Reporters/ s/^/#/' test/helper.rb +# PPC64LE with ruby3.1 does not seem to support GC.compact +# (On Fedora, the above is backported to 3.0 branch) +%ifarch ppc64le s390x +export NOKOGIRI_TEST_GC_LEVEL=major +%endif + # Need investigation. For now anyway build env \ RUBYLIB=".:lib:test:ext" \ @@ -206,6 +225,12 @@ popd %{gem_dir}/doc/%{gem_name}-%{mainver}%{?prever}/ %changelog +* Tue May 10 2022 Mamoru TASAKA - 1.11.7-3 +- Backport CVE-2022-29181 from between 1.13.5 and 1.13.6 + +* Thu Apr 14 2022 Mamoru TASAKA - 1.11.7-2 +- Backport CVE-2022-24836 from between 1.13.3 and 1.13.4 + * Sat Jun 19 2021 Mamoru TASAKA - 1.11.7-1 - 1.11.7