summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2016-07-26 11:27:14 +0200
committerFlorian Frank <flori@ping.de>2016-07-26 11:42:18 +0200
commit047814c7a6916bde393e6080c98385c8170d3f98 (patch)
tree8c35b1e2abf068c33af2f2268a1bc6ab80da2780
parentbb5b67741c20c8a53f2e81985fafccbeb750818c (diff)
downloadjson-047814c7a6916bde393e6080c98385c8170d3f98.tar.gz
Fix issue #296 when parsing frozen strings
-rw-r--r--VERSION2
-rw-r--r--ext/json/ext/parser/parser.c19
-rw-r--r--ext/json/ext/parser/parser.rl3
-rw-r--r--java/src/json/ext/Parser.java145
-rw-r--r--java/src/json/ext/Parser.rl3
-rw-r--r--json.gemspecbin5473 -> 5473 bytes
-rw-r--r--json_pure.gemspec6
-rw-r--r--lib/json/version.rb2
-rw-r--r--tests/json_parser_test.rb7
9 files changed, 103 insertions, 84 deletions
diff --git a/VERSION b/VERSION
index 38f77a6..e9307ca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.1
+2.0.2
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 975a267..0dae674 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -1670,6 +1670,9 @@ static VALUE convert_encoding(VALUE source)
#ifdef HAVE_RUBY_ENCODING_H
rb_encoding *enc = rb_enc_get(source);
if (enc == rb_ascii8bit_encoding()) {
+ if (OBJ_FROZEN(source)) {
+ source = rb_str_dup(source);
+ }
FORCE_UTF8(source);
} else {
source = rb_str_conv_enc(source, NULL, rb_utf8_encoding());
@@ -1805,7 +1808,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
-#line 1809 "parser.c"
+#line 1812 "parser.c"
enum {JSON_start = 1};
enum {JSON_first_final = 10};
enum {JSON_error = 0};
@@ -1813,7 +1816,7 @@ enum {JSON_error = 0};
enum {JSON_en_main = 1};
-#line 717 "parser.rl"
+#line 720 "parser.rl"
/*
@@ -1830,16 +1833,16 @@ static VALUE cParser_parse(VALUE self)
GET_PARSER;
-#line 1834 "parser.c"
+#line 1837 "parser.c"
{
cs = JSON_start;
}
-#line 733 "parser.rl"
+#line 736 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1843 "parser.c"
+#line 1846 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1873,7 +1876,7 @@ st0:
cs = 0;
goto _out;
tr2:
-#line 709 "parser.rl"
+#line 712 "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;}
@@ -1883,7 +1886,7 @@ st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1887 "parser.c"
+#line 1890 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1972,7 +1975,7 @@ case 9:
_out: {}
}
-#line 736 "parser.rl"
+#line 739 "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 c67634b..dd24cf9 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -565,6 +565,9 @@ static VALUE convert_encoding(VALUE source)
#ifdef HAVE_RUBY_ENCODING_H
rb_encoding *enc = rb_enc_get(source);
if (enc == rb_ascii8bit_encoding()) {
+ if (OBJ_FROZEN(source)) {
+ source = rb_str_dup(source);
+ }
FORCE_UTF8(source);
} else {
source = rb_str_conv_enc(source, NULL, rb_utf8_encoding());
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index 8c33840..2a7d9f5 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -181,6 +181,9 @@ public class Parser extends RubyObject {
private RubyString convertEncoding(ThreadContext context, RubyString source) {
RubyEncoding encoding = (RubyEncoding)source.encoding(context);
if (encoding == info.ascii8bit.get()) {
+ if (source.isFrozen()) {
+ source = (RubyString) source.dup();
+ }
source.force_encoding(context, info.utf8.get());
} else {
source = (RubyString) source.encode(context, info.utf8.get());
@@ -304,11 +307,11 @@ public class Parser extends RubyObject {
}
-// line 330 "Parser.rl"
+// line 333 "Parser.rl"
-// line 312 "Parser.java"
+// line 315 "Parser.java"
private static byte[] init__JSON_value_actions_0()
{
return new byte [] {
@@ -422,7 +425,7 @@ static final int JSON_value_error = 0;
static final int JSON_value_en_main = 1;
-// line 436 "Parser.rl"
+// line 439 "Parser.rl"
void parseValue(ParserResult res, int p, int pe) {
@@ -430,14 +433,14 @@ static final int JSON_value_en_main = 1;
IRubyObject result = null;
-// line 434 "Parser.java"
+// line 437 "Parser.java"
{
cs = JSON_value_start;
}
-// line 443 "Parser.rl"
+// line 446 "Parser.rl"
-// line 441 "Parser.java"
+// line 444 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -463,13 +466,13 @@ case 1:
while ( _nacts-- > 0 ) {
switch ( _JSON_value_actions[_acts++] ) {
case 9:
-// line 421 "Parser.rl"
+// line 424 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 473 "Parser.java"
+// line 476 "Parser.java"
}
}
@@ -532,25 +535,25 @@ case 1:
switch ( _JSON_value_actions[_acts++] )
{
case 0:
-// line 338 "Parser.rl"
+// line 341 "Parser.rl"
{
result = getRuntime().getNil();
}
break;
case 1:
-// line 341 "Parser.rl"
+// line 344 "Parser.rl"
{
result = getRuntime().getFalse();
}
break;
case 2:
-// line 344 "Parser.rl"
+// line 347 "Parser.rl"
{
result = getRuntime().getTrue();
}
break;
case 3:
-// line 347 "Parser.rl"
+// line 350 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
@@ -560,7 +563,7 @@ case 1:
}
break;
case 4:
-// line 354 "Parser.rl"
+// line 357 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
@@ -570,7 +573,7 @@ case 1:
}
break;
case 5:
-// line 361 "Parser.rl"
+// line 364 "Parser.rl"
{
if (pe > p + 8 &&
absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) {
@@ -599,7 +602,7 @@ case 1:
}
break;
case 6:
-// line 387 "Parser.rl"
+// line 390 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -612,7 +615,7 @@ case 1:
}
break;
case 7:
-// line 397 "Parser.rl"
+// line 400 "Parser.rl"
{
currentNesting++;
parseArray(res, p, pe);
@@ -627,7 +630,7 @@ case 1:
}
break;
case 8:
-// line 409 "Parser.rl"
+// line 412 "Parser.rl"
{
currentNesting++;
parseObject(res, p, pe);
@@ -641,7 +644,7 @@ case 1:
}
}
break;
-// line 645 "Parser.java"
+// line 648 "Parser.java"
}
}
}
@@ -661,7 +664,7 @@ case 5:
break; }
}
-// line 444 "Parser.rl"
+// line 447 "Parser.rl"
if (cs >= JSON_value_first_final && result != null) {
res.update(result, p);
@@ -671,7 +674,7 @@ case 5:
}
-// line 675 "Parser.java"
+// line 678 "Parser.java"
private static byte[] init__JSON_integer_actions_0()
{
return new byte [] {
@@ -770,7 +773,7 @@ static final int JSON_integer_error = 0;
static final int JSON_integer_en_main = 1;
-// line 463 "Parser.rl"
+// line 466 "Parser.rl"
void parseInteger(ParserResult res, int p, int pe) {
@@ -788,15 +791,15 @@ static final int JSON_integer_en_main = 1;
int cs = EVIL;
-// line 792 "Parser.java"
+// line 795 "Parser.java"
{
cs = JSON_integer_start;
}
-// line 480 "Parser.rl"
+// line 483 "Parser.rl"
int memo = p;
-// line 800 "Parser.java"
+// line 803 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -877,13 +880,13 @@ case 1:
switch ( _JSON_integer_actions[_acts++] )
{
case 0:
-// line 457 "Parser.rl"
+// line 460 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 887 "Parser.java"
+// line 890 "Parser.java"
}
}
}
@@ -903,7 +906,7 @@ case 5:
break; }
}
-// line 482 "Parser.rl"
+// line 485 "Parser.rl"
if (cs < JSON_integer_first_final) {
return -1;
@@ -925,7 +928,7 @@ case 5:
}
-// line 929 "Parser.java"
+// line 932 "Parser.java"
private static byte[] init__JSON_float_actions_0()
{
return new byte [] {
@@ -1027,7 +1030,7 @@ static final int JSON_float_error = 0;
static final int JSON_float_en_main = 1;
-// line 517 "Parser.rl"
+// line 520 "Parser.rl"
void parseFloat(ParserResult res, int p, int pe) {
@@ -1045,15 +1048,15 @@ static final int JSON_float_en_main = 1;
int cs = EVIL;
-// line 1049 "Parser.java"
+// line 1052 "Parser.java"
{
cs = JSON_float_start;
}
-// line 534 "Parser.rl"
+// line 537 "Parser.rl"
int memo = p;
-// line 1057 "Parser.java"
+// line 1060 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1134,13 +1137,13 @@ case 1:
switch ( _JSON_float_actions[_acts++] )
{
case 0:
-// line 508 "Parser.rl"
+// line 511 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1144 "Parser.java"
+// line 1147 "Parser.java"
}
}
}
@@ -1160,7 +1163,7 @@ case 5:
break; }
}
-// line 536 "Parser.rl"
+// line 539 "Parser.rl"
if (cs < JSON_float_first_final) {
return -1;
@@ -1176,7 +1179,7 @@ case 5:
}
-// line 1180 "Parser.java"
+// line 1183 "Parser.java"
private static byte[] init__JSON_string_actions_0()
{
return new byte [] {
@@ -1278,7 +1281,7 @@ static final int JSON_string_error = 0;
static final int JSON_string_en_main = 1;
-// line 581 "Parser.rl"
+// line 584 "Parser.rl"
void parseString(ParserResult res, int p, int pe) {
@@ -1286,15 +1289,15 @@ static final int JSON_string_en_main = 1;
IRubyObject result = null;
-// line 1290 "Parser.java"
+// line 1293 "Parser.java"
{
cs = JSON_string_start;
}
-// line 588 "Parser.rl"
+// line 591 "Parser.rl"
int memo = p;
-// line 1298 "Parser.java"
+// line 1301 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1375,7 +1378,7 @@ case 1:
switch ( _JSON_string_actions[_acts++] )
{
case 0:
-// line 556 "Parser.rl"
+// line 559 "Parser.rl"
{
int offset = byteList.begin();
ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
@@ -1390,13 +1393,13 @@ case 1:
}
break;
case 1:
-// line 569 "Parser.rl"
+// line 572 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1400 "Parser.java"
+// line 1403 "Parser.java"
}
}
}
@@ -1416,7 +1419,7 @@ case 5:
break; }
}
-// line 590 "Parser.rl"
+// line 593 "Parser.rl"
if (parser.createAdditions) {
RubyHash matchString = parser.matchString;
@@ -1454,7 +1457,7 @@ case 5:
}
-// line 1458 "Parser.java"
+// line 1461 "Parser.java"
private static byte[] init__JSON_array_actions_0()
{
return new byte [] {
@@ -1567,7 +1570,7 @@ static final int JSON_array_error = 0;
static final int JSON_array_en_main = 1;
-// line 663 "Parser.rl"
+// line 666 "Parser.rl"
void parseArray(ParserResult res, int p, int pe) {
@@ -1587,14 +1590,14 @@ static final int JSON_array_en_main = 1;
}
-// line 1591 "Parser.java"
+// line 1594 "Parser.java"
{
cs = JSON_array_start;
}
-// line 682 "Parser.rl"
+// line 685 "Parser.rl"
-// line 1598 "Parser.java"
+// line 1601 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1675,7 +1678,7 @@ case 1:
switch ( _JSON_array_actions[_acts++] )
{
case 0:
-// line 632 "Parser.rl"
+// line 635 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -1692,13 +1695,13 @@ case 1:
}
break;
case 1:
-// line 647 "Parser.rl"
+// line 650 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1702 "Parser.java"
+// line 1705 "Parser.java"
}
}
}
@@ -1718,7 +1721,7 @@ case 5:
break; }
}
-// line 683 "Parser.rl"
+// line 686 "Parser.rl"
if (cs >= JSON_array_first_final) {
res.update(result, p + 1);
@@ -1728,7 +1731,7 @@ case 5:
}
-// line 1732 "Parser.java"
+// line 1735 "Parser.java"
private static byte[] init__JSON_object_actions_0()
{
return new byte [] {
@@ -1851,7 +1854,7 @@ static final int JSON_object_error = 0;
static final int JSON_object_en_main = 1;
-// line 742 "Parser.rl"
+// line 745 "Parser.rl"
void parseObject(ParserResult res, int p, int pe) {
@@ -1876,14 +1879,14 @@ static final int JSON_object_en_main = 1;
}
-// line 1880 "Parser.java"
+// line 1883 "Parser.java"
{
cs = JSON_object_start;
}
-// line 766 "Parser.rl"
+// line 769 "Parser.rl"
-// line 1887 "Parser.java"
+// line 1890 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1964,7 +1967,7 @@ case 1:
switch ( _JSON_object_actions[_acts++] )
{
case 0:
-// line 697 "Parser.rl"
+// line 700 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -1981,7 +1984,7 @@ case 1:
}
break;
case 1:
-// line 712 "Parser.rl"
+// line 715 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -2001,13 +2004,13 @@ case 1:
}
break;
case 2:
-// line 730 "Parser.rl"
+// line 733 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 2011 "Parser.java"
+// line 2014 "Parser.java"
}
}
}
@@ -2027,7 +2030,7 @@ case 5:
break; }
}
-// line 767 "Parser.rl"
+// line 770 "Parser.rl"
if (cs < JSON_object_first_final) {
res.update(null, p + 1);
@@ -2060,7 +2063,7 @@ case 5:
}
-// line 2064 "Parser.java"
+// line 2067 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
@@ -2163,7 +2166,7 @@ static final int JSON_error = 0;
static final int JSON_en_main = 1;
-// line 818 "Parser.rl"
+// line 821 "Parser.rl"
public IRubyObject parseImplemetation() {
@@ -2173,16 +2176,16 @@ static final int JSON_en_main = 1;
ParserResult res = new ParserResult();
-// line 2177 "Parser.java"
+// line 2180 "Parser.java"
{
cs = JSON_start;
}
-// line 827 "Parser.rl"
+// line 830 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2186 "Parser.java"
+// line 2189 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2263,7 +2266,7 @@ case 1:
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 804 "Parser.rl"
+// line 807 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2275,7 +2278,7 @@ case 1:
}
}
break;
-// line 2279 "Parser.java"
+// line 2282 "Parser.java"
}
}
}
@@ -2295,7 +2298,7 @@ case 5:
break; }
}
-// line 830 "Parser.rl"
+// line 833 "Parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl
index 28247ea..1ad8f21 100644
--- a/java/src/json/ext/Parser.rl
+++ b/java/src/json/ext/Parser.rl
@@ -179,6 +179,9 @@ public class Parser extends RubyObject {
private RubyString convertEncoding(ThreadContext context, RubyString source) {
RubyEncoding encoding = (RubyEncoding)source.encoding(context);
if (encoding == info.ascii8bit.get()) {
+ if (source.isFrozen()) {
+ source = (RubyString) source.dup();
+ }
source.force_encoding(context, info.utf8.get());
} else {
source = (RubyString) source.encode(context, info.utf8.get());
diff --git a/json.gemspec b/json.gemspec
index 4773094..2c304ef 100644
--- a/json.gemspec
+++ b/json.gemspec
Binary files differ
diff --git a/json_pure.gemspec b/json_pure.gemspec
index 841dfa7..b6d6093 100644
--- a/json_pure.gemspec
+++ b/json_pure.gemspec
@@ -1,14 +1,14 @@
# -*- encoding: utf-8 -*-
-# stub: json_pure 2.0.1 ruby lib
+# stub: json_pure 2.0.2 ruby lib
Gem::Specification.new do |s|
s.name = "json_pure".freeze
- s.version = "2.0.1"
+ s.version = "2.0.2"
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 = "2016-07-19"
+ s.date = "2016-07-26"
s.description = "This is a JSON implementation in pure Ruby.".freeze
s.email = "flori@ping.de".freeze
s.extra_rdoc_files = ["README.md".freeze]
diff --git a/lib/json/version.rb b/lib/json/version.rb
index 5184ad3..8997def 100644
--- a/lib/json/version.rb
+++ b/lib/json/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module JSON
# JSON version
- VERSION = '2.0.1'
+ VERSION = '2.0.2'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/tests/json_parser_test.rb b/tests/json_parser_test.rb
index f34bc02..40ad500 100644
--- a/tests/json_parser_test.rb
+++ b/tests/json_parser_test.rb
@@ -449,6 +449,13 @@ EOT
assert_equal obj, obj_again
end
+ def test_parsing_frozen_ascii8bit_string
+ assert_equal(
+ { 'foo' => 'bar' },
+ JSON('{ "foo": "bar" }'.force_encoding(Encoding::ASCII_8BIT).freeze)
+ )
+ end
+
private
def assert_equal_float(expected, actual, delta = 1e-2)