diff options
author | Florian Frank <flori@ping.de> | 2017-03-23 14:26:12 +0100 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2017-04-18 10:38:41 +0200 |
commit | f94da5a9bf3dfe841ff217e4c2d0c9a13252c627 (patch) | |
tree | 7b455a9f90537bf2b6b6143816f3e6e76e888438 | |
parent | 8f782fd8e181d9cfe9387ded43a5ca9692266b85 (diff) | |
download | json-f94da5a9bf3dfe841ff217e4c2d0c9a13252c627.tar.gz |
Raise exception
for incomplete unicode surrogates/character escape sequences
-rw-r--r-- | ext/json/ext/parser/parser.c | 46 | ||||
-rw-r--r-- | ext/json/ext/parser/parser.rl | 12 | ||||
-rw-r--r-- | json.gemspec | bin | 5473 -> 5474 bytes | |||
-rw-r--r-- | json_pure.gemspec | 4 | ||||
-rw-r--r-- | tests/json_encoding_test.rb | 2 |
5 files changed, 41 insertions, 23 deletions
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index 5a4da40..2546d46 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -1443,13 +1443,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) break; case 'u': if (pe > stringEnd - 4) { - return Qnil; + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p + ); } else { UTF32 ch = unescape_unicode((unsigned char *) ++pe); pe += 3; if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { pe++; - if (pe > stringEnd - 6) return Qnil; + if (pe > stringEnd - 6) { + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete surrogate pair at '%s'", __LINE__, p + ); + } if (pe[0] == '\\' && pe[1] == 'u') { UTF32 sur = unescape_unicode((unsigned char *) pe + 2); ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) @@ -1479,7 +1487,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) } -#line 1483 "parser.c" +#line 1491 "parser.c" enum {JSON_string_start = 1}; enum {JSON_string_first_final = 8}; enum {JSON_string_error = 0}; @@ -1487,7 +1495,7 @@ enum {JSON_string_error = 0}; enum {JSON_string_en_main = 1}; -#line 512 "parser.rl" +#line 520 "parser.rl" static int @@ -1509,15 +1517,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu *result = rb_str_buf_new(0); -#line 1513 "parser.c" +#line 1521 "parser.c" { cs = JSON_string_start; } -#line 533 "parser.rl" +#line 541 "parser.rl" json->memo = p; -#line 1521 "parser.c" +#line 1529 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1542,7 +1550,7 @@ case 2: goto st0; goto st2; tr2: -#line 498 "parser.rl" +#line 506 "parser.rl" { *result = json_string_unescape(*result, json->memo + 1, p); if (NIL_P(*result)) { @@ -1553,14 +1561,14 @@ tr2: {p = (( p + 1))-1;} } } -#line 509 "parser.rl" +#line 517 "parser.rl" { p--; {p++; cs = 8; goto _out;} } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 1564 "parser.c" +#line 1572 "parser.c" goto st0; st3: if ( ++p == pe ) @@ -1636,7 +1644,7 @@ case 7: _out: {} } -#line 535 "parser.rl" +#line 543 "parser.rl" if (json->create_additions && RTEST(match_string = json->match_string)) { VALUE klass; @@ -1823,7 +1831,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) } -#line 1827 "parser.c" +#line 1835 "parser.c" enum {JSON_start = 1}; enum {JSON_first_final = 10}; enum {JSON_error = 0}; @@ -1831,7 +1839,7 @@ enum {JSON_error = 0}; enum {JSON_en_main = 1}; -#line 735 "parser.rl" +#line 743 "parser.rl" /* @@ -1848,16 +1856,16 @@ static VALUE cParser_parse(VALUE self) GET_PARSER; -#line 1852 "parser.c" +#line 1860 "parser.c" { cs = JSON_start; } -#line 751 "parser.rl" +#line 759 "parser.rl" p = json->source; pe = p + json->len; -#line 1861 "parser.c" +#line 1869 "parser.c" { if ( p == pe ) goto _test_eof; @@ -1891,7 +1899,7 @@ st0: cs = 0; goto _out; tr2: -#line 727 "parser.rl" +#line 735 "parser.rl" { char *np = JSON_parse_value(json, p, pe, &result, 0); if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} @@ -1901,7 +1909,7 @@ st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 1905 "parser.c" +#line 1913 "parser.c" switch( (*p) ) { case 13: goto st10; case 32: goto st10; @@ -1990,7 +1998,7 @@ case 9: _out: {} } -#line 754 "parser.rl" +#line 762 "parser.rl" if (cs >= JSON_first_final && p == pe) { return result; diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl index dc66026..de2ef69 100644 --- a/ext/json/ext/parser/parser.rl +++ b/ext/json/ext/parser/parser.rl @@ -454,13 +454,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) break; case 'u': if (pe > stringEnd - 4) { - return Qnil; + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p + ); } else { UTF32 ch = unescape_unicode((unsigned char *) ++pe); pe += 3; if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { pe++; - if (pe > stringEnd - 6) return Qnil; + if (pe > stringEnd - 6) { + rb_enc_raise( + EXC_ENCODING eParserError, + "%u: incomplete surrogate pair at '%s'", __LINE__, p + ); + } if (pe[0] == '\\' && pe[1] == 'u') { UTF32 sur = unescape_unicode((unsigned char *) pe + 2); ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) diff --git a/json.gemspec b/json.gemspec Binary files differindex f97fdc3..d6ca864 100644 --- a/json.gemspec +++ b/json.gemspec diff --git a/json_pure.gemspec b/json_pure.gemspec index da7a564..417787c 100644 --- a/json_pure.gemspec +++ b/json_pure.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Florian Frank".freeze] - s.date = "2017-01-12" + s.date = "2017-03-23" s.description = "This is a JSON implementation in pure Ruby.".freeze s.email = "flori@ping.de".freeze s.extra_rdoc_files = ["README.md".freeze] @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.licenses = ["Ruby".freeze] s.rdoc_options = ["--title".freeze, "JSON implemention for ruby".freeze, "--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 1.9".freeze) - s.rubygems_version = "2.6.8".freeze + s.rubygems_version = "2.6.10".freeze s.summary = "JSON Implementation for Ruby".freeze s.test_files = ["./tests/test_helper.rb".freeze] diff --git a/tests/json_encoding_test.rb b/tests/json_encoding_test.rb index 29ae02e..4e086ef 100644 --- a/tests/json_encoding_test.rb +++ b/tests/json_encoding_test.rb @@ -79,6 +79,8 @@ class JSONEncodingTest < Test::Unit::TestCase json = '["\ud840\udc01"]' assert_equal json, generate(utf8, :ascii_only => true) assert_equal utf8, parse(json) + assert_raises(JSON::ParserError) { parse('"\u"') } + assert_raises(JSON::ParserError) { parse('"\ud800"') } end def test_chars |