Skip to content

Commit 8bab92d

Browse files
ydahbyroot
authored andcommitted
Reject non-ASCII BINARY strings during JSON generation
1 parent 08e7229 commit 8bab92d

3 files changed

Lines changed: 19 additions & 48 deletions

File tree

‎ext/json/ext/generator/generator.c‎

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *dat
7575
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
7676
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
7777

78-
static int usascii_encindex, utf8_encindex, binary_encindex;
78+
static int usascii_encindex, utf8_encindex;
7979

8080
NORETURN(static void) raise_generator_error_str(VALUE invalid_object, VALUE str)
8181
{
@@ -865,20 +865,6 @@ NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data,
865865
}
866866
}
867867

868-
if (RB_ENCODING_GET_INLINED(str) == binary_encindex) {
869-
VALUE utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
870-
switch (rb_enc_str_coderange(utf8_string)) {
871-
case ENC_CODERANGE_7BIT:
872-
return utf8_string;
873-
case ENC_CODERANGE_VALID:
874-
// For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
875-
// TODO: Raise in 3.0.0
876-
rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
877-
return utf8_string;
878-
break;
879-
}
880-
}
881-
882868
return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
883869
}
884870

@@ -2140,7 +2126,6 @@ void Init_generator(void)
21402126

21412127
usascii_encindex = rb_usascii_encindex();
21422128
utf8_encindex = rb_utf8_encindex();
2143-
binary_encindex = rb_ascii8bit_encindex();
21442129

21452130
rb_require("json/ext/generator/state");
21462131

‎java/src/json/ext/StringEncoder.java‎

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import java.nio.charset.StandardCharsets;
1414

1515
import org.jcodings.Encoding;
16-
import org.jcodings.specific.ASCIIEncoding;
1716
import org.jcodings.specific.USASCIIEncoding;
1817
import org.jcodings.specific.UTF8Encoding;
1918
import org.jruby.Ruby;
@@ -229,28 +228,12 @@ static RubyString ensureValidEncoding(ThreadContext context, RubyString str) {
229228
return str;
230229
}
231230

232-
return tryWeirdEncodings(context, str, encoding);
231+
return tryWeirdEncodings(context, str);
233232
}
234233

235-
private static RubyString tryWeirdEncodings(ThreadContext context, RubyString str, Encoding encoding) {
234+
private static RubyString tryWeirdEncodings(ThreadContext context, RubyString str) {
236235
Ruby runtime = context.runtime;
237236

238-
RubyString utf8String;
239-
240-
if (encoding == ASCIIEncoding.INSTANCE) {
241-
utf8String = str.strDup(runtime);
242-
utf8String.setEncoding(UTF8Encoding.INSTANCE);
243-
switch (utf8String.getCodeRange()) {
244-
case StringSupport.CR_7BIT:
245-
return utf8String;
246-
case StringSupport.CR_VALID:
247-
// For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
248-
// TODO: Raise in 3.0.0
249-
runtime.getWarnings().warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
250-
return utf8String;
251-
}
252-
}
253-
254237
try {
255238
str = (RubyString) str.encode(context, runtime.getEncodingService().convertEncodingToRubyEncoding(UTF8Encoding.INSTANCE));
256239
} catch (RaiseException re) {

‎test/json/json_generator_test.rb‎

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,22 +1049,25 @@ def to_s
10491049
end
10501050
end
10511051

1052-
if defined?(JSON::Ext::Generator) and RUBY_PLATFORM != "java"
1053-
def test_valid_utf8_in_different_encoding
1054-
utf8_string = "€™"
1055-
wrong_encoding_string = utf8_string.b
1056-
# This behavior is historical. Not necessary desirable. We should deprecated it.
1057-
# The pure and java version of the gem already don't behave this way.
1058-
assert_warning(/UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0/) do
1059-
assert_equal utf8_string.to_json, wrong_encoding_string.to_json
1060-
end
1061-
1062-
assert_warning(/UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0/) do
1063-
assert_equal JSON.dump(utf8_string), JSON.dump(wrong_encoding_string)
1064-
end
1052+
def test_valid_utf8_in_binary_encoding
1053+
string = "€™".b.freeze
1054+
assert_raise(JSON::GeneratorError) { string.to_json }
1055+
assert_raise(JSON::GeneratorError) { JSON.dump(string) }
1056+
[string, [string], { string => 1 }, { value: string }].each do |object|
1057+
error = assert_raise(JSON::GeneratorError) { JSON.generate(object) }
1058+
assert_same string, error.invalid_object
1059+
assert_kind_of Encoding::UndefinedConversionError, error.cause
10651060
end
10661061
end
10671062

1063+
def test_ascii_in_binary_encoding
1064+
string = "ascii".b
1065+
assert_equal '"ascii"', string.to_json
1066+
assert_equal '"ascii"', JSON.dump(string)
1067+
assert_equal '["ascii"]', JSON.generate([string])
1068+
assert_equal '{"ascii":1}', JSON.generate(string => 1)
1069+
end
1070+
10681071
def test_nonutf8_encoding
10691072
assert_equal("\"5\u{b0}\"", "5\xb0".dup.force_encoding(Encoding::ISO_8859_1).to_json)
10701073
end

0 commit comments

Comments
 (0)