diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/json/generator/generator.c | 17 | ||||
| -rw-r--r-- | ext/json/lib/json/version.rb | 2 | ||||
| -rw-r--r-- | ext/json/parser/parser.c | 44 |
3 files changed, 40 insertions, 23 deletions
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 882d47a611..9260712c9a 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1367,12 +1367,14 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig) if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State"); MEMCPY(objState, origState, JSON_Generator_State, 1); - objState->indent = origState->indent; - objState->space = origState->space; - objState->space_before = origState->space_before; - objState->object_nl = origState->object_nl; - objState->array_nl = origState->array_nl; - objState->as_json = origState->as_json; + + RB_OBJ_WRITTEN(obj, Qundef, objState->indent); + RB_OBJ_WRITTEN(obj, Qundef, objState->space); + RB_OBJ_WRITTEN(obj, Qundef, objState->space_before); + RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl); + RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl); + RB_OBJ_WRITTEN(obj, Qundef, objState->as_json); + return obj; } @@ -1590,6 +1592,9 @@ static long depth_config(VALUE num) if (RB_UNLIKELY(d < 0)) { rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d); } + if (RB_UNLIKELY(d > INT_MAX)) { + rb_raise(rb_eArgError, "depth is too large (got %ld)", d); + } return d; } diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index ebb55656d7..a69590ff9c 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.19.5' + VERSION = '2.19.7' end diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index a740bd42ed..363f109d3a 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1202,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig raise_parse_error_at("invalid number: %s", state, start); } - exponent = negative_exponent ? -abs_exponent : abs_exponent; + if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) { + exponent = negative_exponent ? INT64_MIN : INT64_MAX; + } else { + exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent; + } } if (integer) { @@ -1457,18 +1461,21 @@ static void json_ensure_eof(JSON_ParserState *state) static VALUE convert_encoding(VALUE source) { - int encindex = RB_ENCODING_GET(source); + StringValue(source); + int encindex = RB_ENCODING_GET(source); - if (RB_LIKELY(encindex == utf8_encindex)) { - return source; - } + if (RB_LIKELY(encindex == utf8_encindex)) { + return source; + } - if (encindex == binary_encindex) { - // For historical reason, we silently reinterpret binary strings as UTF-8 - return rb_enc_associate_index(rb_str_dup(source), utf8_encindex); - } + if (encindex == binary_encindex) { + // For historical reason, we silently reinterpret binary strings as UTF-8 + return rb_enc_associate_index(rb_str_dup(source), utf8_encindex); + } - return rb_funcall(source, i_encode, 1, Encoding_UTF_8); + source = rb_funcall(source, i_encode, 1, Encoding_UTF_8); + StringValue(source); + return source; } struct parser_config_init_args { @@ -1583,10 +1590,16 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts) return self; } -static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) +static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src) { - Vsource = convert_encoding(StringValue(Vsource)); - StringValue(Vsource); + VALUE Vsource = convert_encoding(src); + + // Ensure the string isn't mutated under us. + // The classic API to use is `rb_str_locktmp`, but then we'd + // need to use `rb_protect` to make sure we always unlock. + if (Vsource == src) { + Vsource = rb_str_new_frozen(Vsource); + } VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { @@ -1597,6 +1610,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) long len; const char *start; + RSTRING_GETMEM(Vsource, start, len); VALUE stack_handle = 0; @@ -1615,6 +1629,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) // it won't cause a leak. rvalue_stack_eagerly_release(stack_handle); RB_GC_GUARD(stack_handle); + RB_GC_GUARD(Vsource); json_ensure_eof(state); return result; @@ -1635,9 +1650,6 @@ static VALUE cParserConfig_parse(VALUE self, VALUE Vsource) static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts) { - Vsource = convert_encoding(StringValue(Vsource)); - StringValue(Vsource); - JSON_ParserConfig _config = {0}; JSON_ParserConfig *config = &_config; parser_config_init(config, opts, false); |
