summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2017-03-23 14:26:12 +0100
committerFlorian Frank <flori@ping.de>2017-04-18 10:38:41 +0200
commitf94da5a9bf3dfe841ff217e4c2d0c9a13252c627 (patch)
tree7b455a9f90537bf2b6b6143816f3e6e76e888438
parent8f782fd8e181d9cfe9387ded43a5ca9692266b85 (diff)
downloadjson-f94da5a9bf3dfe841ff217e4c2d0c9a13252c627.tar.gz
Raise exception
for incomplete unicode surrogates/character escape sequences
-rw-r--r--ext/json/ext/parser/parser.c46
-rw-r--r--ext/json/ext/parser/parser.rl12
-rw-r--r--json.gemspecbin5473 -> 5474 bytes
-rw-r--r--json_pure.gemspec4
-rw-r--r--tests/json_encoding_test.rb2
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
index f97fdc3..d6ca864 100644
--- a/json.gemspec
+++ b/json.gemspec
Binary files differ
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