Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions ext/json/ext/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2113,9 +2113,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src)
// Ensure the string isn't mutated under us.
// The classic API to use is `rb_str_locktmp`, but then we'd
// need to use `rb_protect` to make sure we always unlock.
if (Vsource == src) {
Vsource = rb_str_new_frozen(Vsource);
}
Vsource = rb_str_new_frozen(Vsource);

VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
rvalue_stack value_stack = {
Expand Down
35 changes: 35 additions & 0 deletions test/json/json_parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,41 @@ def test_mutating_source_string_during_parsing
assert_equal expected, actual
end

def test_adversary_encode
fake_string = Class.new(String) do
def encode(*)
42
end
end

assert_raise TypeError, Encoding::InvalidByteSequenceError do
JSON.parse(fake_string.new("\xff".b, encoding: Encoding::UTF_16))
end

if RUBY_ENGINE != "jruby"
fake_string = Class.new(String) do
attr_reader :encoded_str

def initialize(...)
super
@encoded_str = JSON.dump(1000.times.to_a)
end

def encode(*)
@encoded_str
end
end

fake = fake_string.new("blah", encoding: Encoding::UTF_16)
assert_equal 1000.times.to_a, JSON.parse(fake, on_load: ->(v) {
if v == 20
fake.encoded_str.clear
end
v
})
end
end

private

def assert_equal_float(expected, actual, delta = 1e-2)
Expand Down
Loading