summaryrefslogtreecommitdiff
path: root/ext/json
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-02-12 03:05:45 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-02-12 03:05:45 +0000
commit062d2ee6f798205c3046730d0d348cfd0d0bc09d (patch)
tree8be6c2e72c796c481906978565bc116661e4fe9a /ext/json
parentf1194eb9b08b7c7be39e168c1f9620e377bee472 (diff)
* ext/json: merge JSON 1.7.7.
This includes security fix. [CVE-2013-0269] https://github.com/flori/json/commit/d0a62f3ced7560daba2ad546d83f0479a5ae2cf2 https://groups.google.com/d/topic/rubyonrails-security/4_YvCpLzL58/discussion git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39208 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/json')
-rw-r--r--ext/json/fbuffer/fbuffer.h8
-rw-r--r--ext/json/generator/generator.c62
-rw-r--r--ext/json/generator/generator.h9
-rw-r--r--ext/json/lib/json/add/bigdecimal.rb7
-rw-r--r--ext/json/lib/json/common.rb25
-rw-r--r--ext/json/lib/json/generic_object.rb22
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/parser.c8
-rw-r--r--ext/json/parser/parser.rl8
9 files changed, 112 insertions, 39 deletions
diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h
index b5e47eec42..af74187566 100644
--- a/ext/json/fbuffer/fbuffer.h
+++ b/ext/json/fbuffer/fbuffer.h
@@ -3,7 +3,6 @@
#define _FBUFFER_H_
#include "ruby.h"
-#include <assert.h>
#ifndef RHASH_SIZE
#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
@@ -166,11 +165,8 @@ static FBuffer *fbuffer_dup(FBuffer *fb)
unsigned long len = fb->len;
FBuffer *result;
- assert(len > 0);
- if (len > 0) {
- result = fbuffer_alloc(len);
- fbuffer_append(result, FBUFFER_PAIR(fb));
- }
+ result = fbuffer_alloc(len);
+ fbuffer_append(result, FBUFFER_PAIR(fb));
return result;
}
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 3cff87d7d5..ae4593c940 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -522,7 +522,7 @@ static VALUE cState_configure(VALUE self, VALUE opts)
unsigned long len;
Check_Type(tmp, T_STRING);
len = RSTRING_LEN(tmp);
- state->indent = fstrndup(RSTRING_PTR(tmp), len);
+ state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
state->indent_len = len;
}
tmp = rb_hash_aref(opts, ID2SYM(i_space));
@@ -530,7 +530,7 @@ static VALUE cState_configure(VALUE self, VALUE opts)
unsigned long len;
Check_Type(tmp, T_STRING);
len = RSTRING_LEN(tmp);
- state->space = fstrndup(RSTRING_PTR(tmp), len);
+ state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
state->space_len = len;
}
tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
@@ -538,7 +538,7 @@ static VALUE cState_configure(VALUE self, VALUE opts)
unsigned long len;
Check_Type(tmp, T_STRING);
len = RSTRING_LEN(tmp);
- state->space_before = fstrndup(RSTRING_PTR(tmp), len);
+ state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
state->space_before_len = len;
}
tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
@@ -546,7 +546,7 @@ static VALUE cState_configure(VALUE self, VALUE opts)
unsigned long len;
Check_Type(tmp, T_STRING);
len = RSTRING_LEN(tmp);
- state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
+ state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
state->array_nl_len = len;
}
tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
@@ -554,11 +554,11 @@ static VALUE cState_configure(VALUE self, VALUE opts)
unsigned long len;
Check_Type(tmp, T_STRING);
len = RSTRING_LEN(tmp);
- state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
+ state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
state->object_nl_len = len;
}
tmp = ID2SYM(i_max_nesting);
- state->max_nesting = 19;
+ state->max_nesting = 100;
if (option_given_p(opts, tmp)) {
VALUE max_nesting = rb_hash_aref(opts, tmp);
if (RTEST(max_nesting)) {
@@ -598,6 +598,18 @@ static VALUE cState_configure(VALUE self, VALUE opts)
return self;
}
+static void set_state_ivars(VALUE hash, VALUE state)
+{
+ VALUE ivars = rb_obj_instance_variables(state);
+ int i = 0;
+ for (i = 0; i < RARRAY_LEN(ivars); i++) {
+ VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0);
+ long key_len = RSTRING_LEN(key);
+ VALUE value = rb_iv_get(state, StringValueCStr(key));
+ rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value);
+ }
+}
+
/*
* call-seq: to_h
*
@@ -608,6 +620,7 @@ static VALUE cState_to_h(VALUE self)
{
VALUE result = rb_hash_new();
GET_STATE(self);
+ set_state_ivars(result, self);
rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
@@ -629,14 +642,33 @@ static VALUE cState_to_h(VALUE self)
*/
static VALUE cState_aref(VALUE self, VALUE name)
{
- GET_STATE(self);
+ name = rb_funcall(name, i_to_s, 0);
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
return rb_funcall(self, i_send, 1, name);
} else {
- return Qnil;
+ return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
}
}
+/*
+* call-seq: []=(name, value)
+*
+* Set the attribute name to value.
+*/
+static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
+{
+ VALUE name_writer;
+
+ name = rb_funcall(name, i_to_s, 0);
+ name_writer = rb_str_cat2(rb_str_dup(name), "=");
+ if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
+ return rb_funcall(self, i_send, 2, name_writer, value);
+ } else {
+ rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
+ }
+ return Qnil;
+}
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
char *object_nl = state->object_nl;
@@ -908,7 +940,7 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE opts;
GET_STATE(self);
- state->max_nesting = 19;
+ state->max_nesting = 100;
state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
rb_scan_args(argc, argv, "01", &opts);
if (!NIL_P(opts)) cState_configure(self, opts);
@@ -970,7 +1002,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
static VALUE cState_indent(VALUE self)
{
GET_STATE(self);
- return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
+ return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
}
/*
@@ -1007,7 +1039,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
static VALUE cState_space(VALUE self)
{
GET_STATE(self);
- return state->space ? rb_str_new2(state->space) : rb_str_new2("");
+ return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
}
/*
@@ -1044,7 +1076,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
static VALUE cState_space_before(VALUE self)
{
GET_STATE(self);
- return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
+ return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
}
/*
@@ -1081,7 +1113,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
static VALUE cState_object_nl(VALUE self)
{
GET_STATE(self);
- return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
+ return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
}
/*
@@ -1117,7 +1149,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
static VALUE cState_array_nl(VALUE self)
{
GET_STATE(self);
- return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
+ return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
}
/*
@@ -1327,7 +1359,9 @@ void Init_generator()
rb_define_method(cState, "configure", cState_configure, 1);
rb_define_alias(cState, "merge", "configure");
rb_define_method(cState, "to_h", cState_to_h, 0);
+ rb_define_alias(cState, "to_hash", "to_h");
rb_define_method(cState, "[]", cState_aref, 1);
+ rb_define_method(cState, "[]=", cState_aset, 2);
rb_define_method(cState, "generate", cState_generate, 1);
mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h
index 7d429d512c..b58cc4bc2f 100644
--- a/ext/json/generator/generator.h
+++ b/ext/json/generator/generator.h
@@ -2,7 +2,6 @@
#define _GENERATOR_H_
#include <string.h>
-#include <assert.h>
#include <math.h>
#include <ctype.h>
@@ -14,6 +13,14 @@
#include "re.h"
#endif
+#ifndef rb_intern_str
+#define rb_intern_str(string) SYM2ID(rb_str_intern(string))
+#endif
+
+#ifndef rb_obj_instance_variables
+#define rb_obj_instance_variables(object) rb_funcall(object, rb_intern("instance_variables"), 0)
+#endif
+
#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
/* unicode defintions */
diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb
index 4aafe537ab..0ef69f12e0 100644
--- a/ext/json/lib/json/add/bigdecimal.rb
+++ b/ext/json/lib/json/add/bigdecimal.rb
@@ -4,10 +4,16 @@ end
defined?(::BigDecimal) or require 'bigdecimal'
class BigDecimal
+ # Import a JSON Marshalled object.
+ #
+ # method used for JSON marshalling support.
def self.json_create(object)
BigDecimal._load object['b']
end
+ # Marshal the object to JSON.
+ #
+ # method used for JSON marshalling support.
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -15,6 +21,7 @@ class BigDecimal
}
end
+ # return the JSON value
def to_json(*)
as_json.to_json
end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 3349501337..65a74a1aa4 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -139,7 +139,7 @@ module JSON
# keys:
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
# structures. Disable depth checking with :max_nesting => false. It defaults
- # to 19.
+ # to 100.
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
# defiance of RFC 4627 to be parsed by the Parser. This option defaults
# to false.
@@ -199,7 +199,7 @@ module JSON
# encountered. This options defaults to false.
# * *max_nesting*: The maximum depth of nesting allowed in the data
# structures from which JSON is to be generated. Disable depth checking
- # with :max_nesting => false, it defaults to 19.
+ # with :max_nesting => false, it defaults to 100.
#
# See also the fast_generate for the fastest creation method with the least
# amount of sanity checks, and the pretty_generate method for some
@@ -299,21 +299,28 @@ module JSON
attr_accessor :load_default_options
end
self.load_default_options = {
- :max_nesting => false,
- :allow_nan => true,
- :quirks_mode => true,
+ :max_nesting => false,
+ :allow_nan => true,
+ :quirks_mode => true,
+ :create_additions => true,
}
# Load a ruby data structure from a JSON _source_ and return it. A source can
# either be a string-like object, an IO-like object, or an object responding
# to the read method. If _proc_ was given, it will be called with any nested
- # Ruby object as an argument recursively in depth first order. The default
- # options for the parser can be changed via the load_default_options method.
+ # Ruby object as an argument recursively in depth first order. To modify the
+ # default options pass in the optional _options_ argument as well.
+ #
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it. The
+ # default options for the parser can be changed via the load_default_options
+ # method.
#
# This method is part of the implementation of the load/dump interface of
# Marshal and YAML.
- def load(source, proc = nil)
- opts = load_default_options
+ def load(source, proc = nil, options = {})
+ opts = load_default_options.merge options
if source.respond_to? :to_str
source = source.to_str
elsif source.respond_to? :to_io
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
index 7f3dbbd78d..8b1074c941 100644
--- a/ext/json/lib/json/generic_object.rb
+++ b/ext/json/lib/json/generic_object.rb
@@ -5,12 +5,34 @@ module JSON
class << self
alias [] new
+ def json_creatable?
+ @json_creatable
+ end
+
+ attr_writer :json_creatable
+
def json_create(data)
data = data.dup
data.delete JSON.create_id
self[data]
end
+
+ def from_hash(object)
+ case
+ when object.respond_to?(:to_hash)
+ result = new
+ object.to_hash.each do |key, value|
+ result[key] = from_hash(value)
+ end
+ result
+ when object.respond_to?(:to_ary)
+ object.to_ary.map { |a| from_hash(a) }
+ else
+ object
+ end
+ end
end
+ self.json_creatable = false
def to_hash
table
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 45af03fd40..1de3d696f2 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,6 +1,6 @@
module JSON
# JSON version
- VERSION = '1.7.5'
+ VERSION = '1.7.7'
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/ext/json/parser/parser.c b/ext/json/parser/parser.c
index c140fdb2fe..df89f2c58b 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -1618,7 +1618,7 @@ static VALUE convert_encoding(VALUE source)
* _opts_ can have the following keys:
* * *max_nesting*: The maximum depth of nesting allowed in the parsed data
* structures. Disable depth checking with :max_nesting => false|nil|0, it
- * defaults to 19.
+ * defaults to 100.
* * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
* false.
@@ -1655,7 +1655,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 0;
}
} else {
- json->max_nesting = 19;
+ json->max_nesting = 100;
}
tmp = ID2SYM(i_allow_nan);
if (option_given_p(opts, tmp)) {
@@ -1680,7 +1680,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
} else {
- json->create_additions = 1;
+ json->create_additions = 0;
}
tmp = ID2SYM(i_create_id);
if (option_given_p(opts, tmp)) {
@@ -1709,7 +1709,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
}
} else {
- json->max_nesting = 19;
+ json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 1;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
index 20ecc486e1..ab8d318173 100644
--- a/ext/json/parser/parser.rl
+++ b/ext/json/parser/parser.rl
@@ -602,7 +602,7 @@ static VALUE convert_encoding(VALUE source)
* _opts_ can have the following keys:
* * *max_nesting*: The maximum depth of nesting allowed in the parsed data
* structures. Disable depth checking with :max_nesting => false|nil|0, it
- * defaults to 19.
+ * defaults to 100.
* * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
* false.
@@ -639,7 +639,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 0;
}
} else {
- json->max_nesting = 19;
+ json->max_nesting = 100;
}
tmp = ID2SYM(i_allow_nan);
if (option_given_p(opts, tmp)) {
@@ -664,7 +664,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
} else {
- json->create_additions = 1;
+ json->create_additions = 0;
}
tmp = ID2SYM(i_create_id);
if (option_given_p(opts, tmp)) {
@@ -693,7 +693,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
}
} else {
- json->max_nesting = 19;
+ json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 1;
json->create_id = rb_funcall(mJSON, i_create_id, 0);