ruby-changes:27163
From: naruse <ko1@a...>
Date: Wed, 13 Feb 2013 15:35:03 +0900 (JST)
Subject: [ruby-changes:27163] naruse:r39215 (ruby_2_0_0): merge revision(s) 39208:
naruse 2013-02-13 15:34:48 +0900 (Wed, 13 Feb 2013) New Revision: 39215 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=39215 Log: merge revision(s) 39208: * 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 Modified directories: branches/ruby_2_0_0/ Modified files: branches/ruby_2_0_0/ChangeLog branches/ruby_2_0_0/NEWS branches/ruby_2_0_0/ext/json/fbuffer/fbuffer.h branches/ruby_2_0_0/ext/json/generator/generator.c branches/ruby_2_0_0/ext/json/generator/generator.h branches/ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb branches/ruby_2_0_0/ext/json/lib/json/common.rb branches/ruby_2_0_0/ext/json/lib/json/generic_object.rb branches/ruby_2_0_0/ext/json/lib/json/version.rb branches/ruby_2_0_0/ext/json/parser/parser.c branches/ruby_2_0_0/ext/json/parser/parser.rl branches/ruby_2_0_0/test/json/fixtures/fail18.json branches/ruby_2_0_0/test/json/test_json.rb branches/ruby_2_0_0/test/json/test_json_addition.rb branches/ruby_2_0_0/test/json/test_json_encoding.rb branches/ruby_2_0_0/test/json/test_json_fixtures.rb branches/ruby_2_0_0/test/json/test_json_generate.rb branches/ruby_2_0_0/test/json/test_json_generic_object.rb branches/ruby_2_0_0/test/json/test_json_string_matching.rb branches/ruby_2_0_0/test/json/test_json_unicode.rb branches/ruby_2_0_0/version.h Index: ruby_2_0_0/ChangeLog =================================================================== --- ruby_2_0_0/ChangeLog (revision 39214) +++ ruby_2_0_0/ChangeLog (revision 39215) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ChangeLog#L1 +Wed Feb 13 15:34:21 2013 NARUSE, Yui <naruse@r...> + + * 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 + Sat Feb 9 21:13:35 2013 Kazuki Tsujimoto <kazuki@c...> * backport r39167 from trunk. [ruby-core:52059] [Bug #7812] Index: ruby_2_0_0/ext/json/fbuffer/fbuffer.h =================================================================== --- ruby_2_0_0/ext/json/fbuffer/fbuffer.h (revision 39214) +++ ruby_2_0_0/ext/json/fbuffer/fbuffer.h (revision 39215) @@ -3,7 +3,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/fbuffer/fbuffer.h#L3 #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) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/fbuffer/fbuffer.h#L165 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; } Index: ruby_2_0_0/ext/json/generator/generator.c =================================================================== --- ruby_2_0_0/ext/json/generator/generator.c (revision 39214) +++ ruby_2_0_0/ext/json/generator/generator.c (revision 39215) @@ -522,7 +522,7 @@ static VALUE cState_configure(VALUE self https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L522 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L530 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L538 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L546 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L554 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L598 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) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L620 { 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) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L642 */ 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, https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L940 { 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 s https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1002 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 sel https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1039 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1076 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(VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1113 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1149 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() https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.c#L1359 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"); Index: ruby_2_0_0/ext/json/generator/generator.h =================================================================== --- ruby_2_0_0/ext/json/generator/generator.h (revision 39214) +++ ruby_2_0_0/ext/json/generator/generator.h (revision 39215) @@ -2,7 +2,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.h#L2 #define _GENERATOR_H_ #include <string.h> -#include <assert.h> #include <math.h> #include <ctype.h> @@ -14,6 +13,14 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/generator/generator.h#L13 #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 */ Index: ruby_2_0_0/ext/json/lib/json/generic_object.rb =================================================================== --- ruby_2_0_0/ext/json/lib/json/generic_object.rb (revision 39214) +++ ruby_2_0_0/ext/json/lib/json/generic_object.rb (revision 39215) @@ -5,12 +5,34 @@ module JSON https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/generic_object.rb#L5 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 Index: ruby_2_0_0/ext/json/lib/json/version.rb =================================================================== --- ruby_2_0_0/ext/json/lib/json/version.rb (revision 39214) +++ ruby_2_0_0/ext/json/lib/json/version.rb (revision 39215) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/version.rb#L1 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: Index: ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb =================================================================== --- ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb (revision 39214) +++ ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb (revision 39215) @@ -4,10 +4,16 @@ end https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb#L4 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/add/bigdecimal.rb#L21 } end + # return the JSON value def to_json(*) as_json.to_json end Index: ruby_2_0_0/ext/json/lib/json/common.rb =================================================================== --- ruby_2_0_0/ext/json/lib/json/common.rb (revision 39214) +++ ruby_2_0_0/ext/json/lib/json/common.rb (revision 39215) @@ -139,7 +139,7 @@ module JSON https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/common.rb#L139 # 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/common.rb#L199 # 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/lib/json/common.rb#L299 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 Index: ruby_2_0_0/ext/json/parser/parser.rl =================================================================== --- ruby_2_0_0/ext/json/parser/parser.rl (revision 39214) +++ ruby_2_0_0/ext/json/parser/parser.rl (revision 39215) @@ -602,7 +602,7 @@ static VALUE convert_encoding(VALUE sour https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.rl#L602 * _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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.rl#L639 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.rl#L664 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.rl#L693 } } } 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); Index: ruby_2_0_0/ext/json/parser/parser.c =================================================================== --- ruby_2_0_0/ext/json/parser/parser.c (revision 39214) +++ ruby_2_0_0/ext/json/parser/parser.c (revision 39215) @@ -1618,7 +1618,7 @@ static VALUE convert_encoding(VALUE sour https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.c#L1618 * _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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.c#L1655 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/json/parser/parser.c#L1680 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 (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/