CVE-2022-29181 (Ruby, published 2022-05-20T19:15Z)
Description: value: Nokogiri is an open source XML and HTML library for Ruby. Nokogiri prior to version 1.13.6 does not type-check all inputs into the XML and HTML4 SAX parsers, allowing specially crafted untrusted inputs to cause illegal memory access errors (segfault) or reads from unrelated memory. Version 1.13.6 contains a patch for this issue. As a workaround, ensure the untrusted input is a `String` by calling `#to_s` or equivalent.
Severity: MEDIUM (CVSS v3 base score: 8.2)
Weakness: CWE-241 \u2014 Improper Handling of Unexpected Data Type
The product does not handle or incorrectly handles when a particular element is not the expected type, e.g. it expects a digit (0-9) but is provided with a letter (A-Z).
Repository: https://github.com/sparklemotion/nokogiri
Files changed:
CHANGELOG.md
ext/java/nokogiri/Html4SaxParserContext.java
ext/java/nokogiri/XmlSaxParserContext.java
ext/java/nokogiri/internals/ParserContext.java
ext/nokogiri/html4_sax_parser_context.c
ext/nokogiri/xml_sax_parser_context.c
lib/nokogiri/html4/sax/parser.rb
test/html4/sax/test_parser.rb
test/html4/sax/test_parser_context.rb
test/xml/sax/test_parser.rb
test/xml/sax/test_parser_context.rb
Commit message: fix: {HTML4,XML}::SAX::{Parser,ParserContext} check arg types

Previously, arguments of the wrong type might cause segfault on CRuby.


Vulnerable code:
* Installation from source on systems missing libiconv will once again generate a helpful error message (broken since v1.11.0). [#2505]
           IRubyObject enc)
    //int encoding = (int)enc.convertToInteger().getLongValue();
      throw ruby.newArgumentError("must be kind_of String");
  if (NIL_P(data)) {
    rb_raise(rb_eArgError, "data cannot be nil");
  }
  if (NIL_P(data)) {
    rb_raise(rb_eArgError, "data cannot be nil");
  }
          raise ArgumentError unless data
          assert_raises(ArgumentError) do
          assert_raises(ArgumentError) { parser.parse_memory(nil) }

Fixed code:
* `{HTML4,XML}::SAX::{Parser,ParserContext}` constructor methods now raise `TypeError` instead of segfaulting when an incorrect type is passed. (Thanks to [@agustingianni](https://github.com/agustingianni) from the Github Security Lab for reporting!)
* Installation from source on systems missing libiconv will once again generate a helpful error message (broken since v1.11.0). [[#2505](https://github.com/sparklemotion/nokogiri/issues/2505)]
    if (!(data instanceof RubyString)) {
      throw context.getRuntime().newTypeError("data must be kind_of String");
    }
    if (!(encoding instanceof RubyString)) {
      throw context.getRuntime().newTypeError("data must be kind_of String");
    }

    if (!(encoding instanceof RubyFixnum)) {
      throw context.getRuntime().newTypeError("encoding must be kind_of String");
    }

           IRubyObject encoding)
    // check the type of the unused encoding to match behavior of CRuby
    if (!(encoding instanceof RubyFixnum)) {
      throw context.getRuntime().newTypeError("encoding must be kind_of String");
    }
    Ruby ruby = context.getRuntime();

    if (!(data.respondsTo("read"))) {
      throw ruby.newTypeError("must respond to :read");
    }

      throw ruby.newTypeError("must be kind_of String");
  Check_Type(data, T_STRING);

static ID id_read;

  if (!rb_respond_to(io, id_read)) {
    rb_raise(rb_eTypeError, "argument expected to respond to :read");
  }

  Check_Type(data, T_STRING);


  id_read = rb_intern("read");
          raise TypeError unless String === data
          assert_raises(TypeError) do

        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

        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
        it "handles invalid types gracefully" do
          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

          assert_raises(TypeError) { parser.parse_memory(nil) }
        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