Skip to content

Commit 1c44851

Browse files
committed
Raise JSON::GeneratorError instead of Encoding::UndefinedConversionError
Followup: ruby#633 That's what was raised historically. You could argue that this new exception is more precise, but I've encountered some real production code that expected the old behavior and that was broken by this change.
1 parent dcd8292 commit 1c44851

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

ext/json/ext/generator/generator.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,10 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
10361036
struct generate_json_data *data = (struct generate_json_data *)d;
10371037
fbuffer_free(data->buffer);
10381038

1039+
if (RBASIC_CLASS(exc) == rb_path2class("Encoding::UndefinedConversionError")) {
1040+
exc = rb_exc_new_str(eGeneratorError, rb_funcall(exc, rb_intern("message"), 0));
1041+
}
1042+
10391043
rb_exc_raise(exc);
10401044

10411045
return Qundef;

java/src/json/ext/Generator.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.jruby.runtime.ThreadContext;
1818
import org.jruby.runtime.builtin.IRubyObject;
1919
import org.jruby.util.ByteList;
20+
import org.jruby.exceptions.RaiseException;
2021

2122
public final class Generator {
2223
private Generator() {
@@ -402,14 +403,19 @@ void generate(Session session, RubyString object, ByteList buffer) {
402403
RuntimeInfo info = session.getInfo();
403404
RubyString src;
404405

405-
if (object.encoding(session.getContext()) != info.utf8.get()) {
406-
src = (RubyString)object.encode(session.getContext(),
407-
info.utf8.get());
408-
} else {
409-
src = object;
410-
}
406+
try {
407+
if (object.encoding(session.getContext()) != info.utf8.get()) {
408+
src = (RubyString)object.encode(session.getContext(),
409+
info.utf8.get());
410+
} else {
411+
src = object;
412+
}
411413

412-
session.getStringEncoder().encode(src.getByteList(), buffer);
414+
session.getStringEncoder().encode(src.getByteList(), buffer);
415+
} catch (RaiseException re) {
416+
throw Utils.newException(session.getContext(), Utils.M_GENERATOR_ERROR,
417+
re.getMessage());
418+
}
413419
}
414420
};
415421

lib/json/pure/generator.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,13 @@ def generate(obj)
354354
# Assumes !@ascii_only, !@script_safe
355355
private def fast_serialize_string(string, buf) # :nodoc:
356356
buf << '"'
357-
string = string.encode(::Encoding::UTF_8) unless string.encoding == ::Encoding::UTF_8
357+
unless string.encoding == ::Encoding::UTF_8
358+
begin
359+
string = string.encode(::Encoding::UTF_8)
360+
rescue Encoding::UndefinedConversionError => error
361+
raise GeneratorError, error.message
362+
end
363+
end
358364
raise GeneratorError, "source sequence is illegal/malformed utf-8" unless string.valid_encoding?
359365

360366
if /["\\\x0-\x1f]/n.match?(string)
@@ -557,6 +563,8 @@ def to_json(state = nil, *args)
557563
else
558564
%("#{JSON.utf8_to_json(string, state.script_safe)}")
559565
end
566+
rescue Encoding::UndefinedConversionError => error
567+
raise ::JSON::GeneratorError, error.message
560568
end
561569

562570
# Module that holds the extending methods if, the String module is

test/json/json_generator_test.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,12 +477,20 @@ def test_invalid_encoding_string
477477
end
478478
assert_includes error.message, "source sequence is illegal/malformed utf-8"
479479

480-
assert_raise(Encoding::UndefinedConversionError) do
480+
assert_raise(JSON::GeneratorError) do
481+
JSON.dump("\x82\xAC\xEF".b)
482+
end
483+
484+
assert_raise(JSON::GeneratorError) do
481485
"\x82\xAC\xEF".b.to_json
482486
end
483487

484-
assert_raise(Encoding::UndefinedConversionError) do
485-
JSON.dump("\x82\xAC\xEF".b)
488+
assert_raise(JSON::GeneratorError) do
489+
["\x82\xAC\xEF".b].to_json
490+
end
491+
492+
assert_raise(JSON::GeneratorError) do
493+
{ foo: "\x82\xAC\xEF".b }.to_json
486494
end
487495
end
488496

0 commit comments

Comments
 (0)