Skip to content

Commit 22f63c1

Browse files
committed
[ruby/json] Stop caching the generator state pointer
Fix: ruby/json#790 If we end up calling something that spills the state on the heap, the pointer we received is outdated and may be out of sync. ruby/json@2ffa4ea46b
1 parent 80a1a1b commit 22f63c1

File tree

2 files changed

+114
-89
lines changed

2 files changed

+114
-89
lines changed

ext/json/generator/generator.c

Lines changed: 90 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_n
4545

4646
struct generate_json_data;
4747

48-
typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
48+
typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
4949

5050
struct generate_json_data {
5151
FBuffer *buffer;
@@ -57,20 +57,20 @@ struct generate_json_data {
5757

5858
static VALUE cState_from_state_s(VALUE self, VALUE opts);
5959
static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io);
60-
static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
61-
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
62-
static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
63-
static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
64-
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
65-
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
66-
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
60+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
61+
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
62+
static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
63+
static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
64+
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
65+
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
66+
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
6767
#ifdef RUBY_INTEGER_UNIFICATION
68-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
68+
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
6969
#endif
70-
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
71-
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
72-
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
73-
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
70+
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
71+
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
72+
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
73+
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
7474

7575
static int usascii_encindex, utf8_encindex, binary_encindex;
7676

@@ -802,12 +802,12 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
802802
int j;
803803

804804
if (arg->iter > 0) fbuffer_append_char(buffer, ',');
805-
if (RB_UNLIKELY(state->object_nl)) {
806-
fbuffer_append_str(buffer, state->object_nl);
805+
if (RB_UNLIKELY(data->state->object_nl)) {
806+
fbuffer_append_str(buffer, data->state->object_nl);
807807
}
808-
if (RB_UNLIKELY(state->indent)) {
808+
if (RB_UNLIKELY(data->state->indent)) {
809809
for (j = 0; j < depth; j++) {
810-
fbuffer_append_str(buffer, state->indent);
810+
fbuffer_append_str(buffer, data->state->indent);
811811
}
812812
}
813813

@@ -829,36 +829,37 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
829829
}
830830

831831
if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
832-
generate_json_string(buffer, data, state, key_to_s);
832+
generate_json_string(buffer, data, key_to_s);
833833
} else {
834-
generate_json(buffer, data, state, key_to_s);
834+
generate_json(buffer, data, key_to_s);
835835
}
836-
if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, state->space_before);
836+
if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, data->state->space_before);
837837
fbuffer_append_char(buffer, ':');
838-
if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, state->space);
839-
generate_json(buffer, data, state, val);
838+
if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, data->state->space);
839+
generate_json(buffer, data, val);
840840

841841
arg->iter++;
842842
return ST_CONTINUE;
843843
}
844844

845-
static inline long increase_depth(JSON_Generator_State *state)
845+
static inline long increase_depth(struct generate_json_data *data)
846846
{
847+
JSON_Generator_State *state = data->state;
847848
long depth = ++state->depth;
848849
if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
849850
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
850851
}
851852
return depth;
852853
}
853854

854-
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
855+
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
855856
{
856857
int j;
857-
long depth = increase_depth(state);
858+
long depth = increase_depth(data);
858859

859860
if (RHASH_SIZE(obj) == 0) {
860861
fbuffer_append(buffer, "{}", 2);
861-
--state->depth;
862+
--data->state->depth;
862863
return;
863864
}
864865

@@ -870,49 +871,49 @@ static void generate_json_object(FBuffer *buffer, struct generate_json_data *dat
870871
};
871872
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
872873

873-
depth = --state->depth;
874-
if (RB_UNLIKELY(state->object_nl)) {
875-
fbuffer_append_str(buffer, state->object_nl);
876-
if (RB_UNLIKELY(state->indent)) {
874+
depth = --data->state->depth;
875+
if (RB_UNLIKELY(data->state->object_nl)) {
876+
fbuffer_append_str(buffer, data->state->object_nl);
877+
if (RB_UNLIKELY(data->state->indent)) {
877878
for (j = 0; j < depth; j++) {
878-
fbuffer_append_str(buffer, state->indent);
879+
fbuffer_append_str(buffer, data->state->indent);
879880
}
880881
}
881882
}
882883
fbuffer_append_char(buffer, '}');
883884
}
884885

885-
static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
886+
static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
886887
{
887888
int i, j;
888-
long depth = increase_depth(state);
889+
long depth = increase_depth(data);
889890

890891
if (RARRAY_LEN(obj) == 0) {
891892
fbuffer_append(buffer, "[]", 2);
892-
--state->depth;
893+
--data->state->depth;
893894
return;
894895
}
895896

896897
fbuffer_append_char(buffer, '[');
897-
if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
898+
if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
898899
for(i = 0; i < RARRAY_LEN(obj); i++) {
899900
if (i > 0) {
900901
fbuffer_append_char(buffer, ',');
901-
if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
902+
if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
902903
}
903-
if (RB_UNLIKELY(state->indent)) {
904+
if (RB_UNLIKELY(data->state->indent)) {
904905
for (j = 0; j < depth; j++) {
905-
fbuffer_append_str(buffer, state->indent);
906+
fbuffer_append_str(buffer, data->state->indent);
906907
}
907908
}
908-
generate_json(buffer, data, state, RARRAY_AREF(obj, i));
909+
generate_json(buffer, data, RARRAY_AREF(obj, i));
909910
}
910-
state->depth = --depth;
911-
if (RB_UNLIKELY(state->array_nl)) {
912-
fbuffer_append_str(buffer, state->array_nl);
913-
if (RB_UNLIKELY(state->indent)) {
911+
data->state->depth = --depth;
912+
if (RB_UNLIKELY(data->state->array_nl)) {
913+
fbuffer_append_str(buffer, data->state->array_nl);
914+
if (RB_UNLIKELY(data->state->indent)) {
914915
for (j = 0; j < depth; j++) {
915-
fbuffer_append_str(buffer, state->indent);
916+
fbuffer_append_str(buffer, data->state->indent);
916917
}
917918
}
918919
}
@@ -961,7 +962,7 @@ static inline VALUE ensure_valid_encoding(VALUE str)
961962
return str;
962963
}
963964

964-
static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
965+
static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
965966
{
966967
obj = ensure_valid_encoding(obj);
967968

@@ -977,9 +978,9 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat
977978
switch(rb_enc_str_coderange(obj)) {
978979
case ENC_CODERANGE_7BIT:
979980
case ENC_CODERANGE_VALID:
980-
if (RB_UNLIKELY(state->ascii_only)) {
981-
convert_UTF8_to_ASCII_only_JSON(&search, state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
982-
} else if (RB_UNLIKELY(state->script_safe)) {
981+
if (RB_UNLIKELY(data->state->ascii_only)) {
982+
convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
983+
} else if (RB_UNLIKELY(data->state->script_safe)) {
983984
convert_UTF8_to_script_safe_JSON(&search);
984985
} else {
985986
convert_UTF8_to_JSON(&search);
@@ -992,7 +993,7 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat
992993
fbuffer_append_char(buffer, '"');
993994
}
994995

995-
static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
996+
static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
996997
{
997998
VALUE tmp;
998999
if (rb_respond_to(obj, i_to_json)) {
@@ -1002,68 +1003,68 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
10021003
} else {
10031004
tmp = rb_funcall(obj, i_to_s, 0);
10041005
Check_Type(tmp, T_STRING);
1005-
generate_json_string(buffer, data, state, tmp);
1006+
generate_json_string(buffer, data, tmp);
10061007
}
10071008
}
10081009

1009-
static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1010+
static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10101011
{
1011-
if (state->strict) {
1012-
generate_json_string(buffer, data, state, rb_sym2str(obj));
1012+
if (data->state->strict) {
1013+
generate_json_string(buffer, data, rb_sym2str(obj));
10131014
} else {
1014-
generate_json_fallback(buffer, data, state, obj);
1015+
generate_json_fallback(buffer, data, obj);
10151016
}
10161017
}
10171018

1018-
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1019+
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10191020
{
10201021
fbuffer_append(buffer, "null", 4);
10211022
}
10221023

1023-
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1024+
static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10241025
{
10251026
fbuffer_append(buffer, "false", 5);
10261027
}
10271028

1028-
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1029+
static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10291030
{
10301031
fbuffer_append(buffer, "true", 4);
10311032
}
10321033

1033-
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1034+
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10341035
{
10351036
fbuffer_append_long(buffer, FIX2LONG(obj));
10361037
}
10371038

1038-
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1039+
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10391040
{
10401041
VALUE tmp = rb_funcall(obj, i_to_s, 0);
10411042
fbuffer_append_str(buffer, tmp);
10421043
}
10431044

10441045
#ifdef RUBY_INTEGER_UNIFICATION
1045-
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1046+
static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10461047
{
10471048
if (FIXNUM_P(obj))
1048-
generate_json_fixnum(buffer, data, state, obj);
1049+
generate_json_fixnum(buffer, data, obj);
10491050
else
1050-
generate_json_bignum(buffer, data, state, obj);
1051+
generate_json_bignum(buffer, data, obj);
10511052
}
10521053
#endif
10531054

1054-
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1055+
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10551056
{
10561057
double value = RFLOAT_VALUE(obj);
1057-
char allow_nan = state->allow_nan;
1058+
char allow_nan = data->state->allow_nan;
10581059
if (isinf(value) || isnan(value)) {
10591060
/* for NaN and Infinity values we either raise an error or rely on Float#to_s. */
10601061
if (!allow_nan) {
1061-
if (state->strict && state->as_json) {
1062-
VALUE casted_obj = rb_proc_call_with_block(state->as_json, 1, &obj, Qnil);
1062+
if (data->state->strict && data->state->as_json) {
1063+
VALUE casted_obj = rb_proc_call_with_block(data->state->as_json, 1, &obj, Qnil);
10631064
if (casted_obj != obj) {
1064-
increase_depth(state);
1065-
generate_json(buffer, data, state, casted_obj);
1066-
state->depth--;
1065+
increase_depth(data);
1066+
generate_json(buffer, data, casted_obj);
1067+
data->state->depth--;
10671068
return;
10681069
}
10691070
}
@@ -1089,74 +1090,74 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
10891090
buffer->len += len;
10901091
}
10911092

1092-
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1093+
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
10931094
{
10941095
VALUE fragment = RSTRUCT_GET(obj, 0);
10951096
Check_Type(fragment, T_STRING);
10961097
fbuffer_append_str(buffer, fragment);
10971098
}
10981099

1099-
static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1100+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
11001101
{
11011102
bool as_json_called = false;
11021103
start:
11031104
if (obj == Qnil) {
1104-
generate_json_null(buffer, data, state, obj);
1105+
generate_json_null(buffer, data, obj);
11051106
} else if (obj == Qfalse) {
1106-
generate_json_false(buffer, data, state, obj);
1107+
generate_json_false(buffer, data, obj);
11071108
} else if (obj == Qtrue) {
1108-
generate_json_true(buffer, data, state, obj);
1109+
generate_json_true(buffer, data, obj);
11091110
} else if (RB_SPECIAL_CONST_P(obj)) {
11101111
if (RB_FIXNUM_P(obj)) {
1111-
generate_json_fixnum(buffer, data, state, obj);
1112+
generate_json_fixnum(buffer, data, obj);
11121113
} else if (RB_FLONUM_P(obj)) {
1113-
generate_json_float(buffer, data, state, obj);
1114+
generate_json_float(buffer, data, obj);
11141115
} else if (RB_STATIC_SYM_P(obj)) {
1115-
generate_json_symbol(buffer, data, state, obj);
1116+
generate_json_symbol(buffer, data, obj);
11161117
} else {
11171118
goto general;
11181119
}
11191120
} else {
11201121
VALUE klass = RBASIC_CLASS(obj);
11211122
switch (RB_BUILTIN_TYPE(obj)) {
11221123
case T_BIGNUM:
1123-
generate_json_bignum(buffer, data, state, obj);
1124+
generate_json_bignum(buffer, data, obj);
11241125
break;
11251126
case T_HASH:
11261127
if (klass != rb_cHash) goto general;
1127-
generate_json_object(buffer, data, state, obj);
1128+
generate_json_object(buffer, data, obj);
11281129
break;
11291130
case T_ARRAY:
11301131
if (klass != rb_cArray) goto general;
1131-
generate_json_array(buffer, data, state, obj);
1132+
generate_json_array(buffer, data, obj);
11321133
break;
11331134
case T_STRING:
11341135
if (klass != rb_cString) goto general;
1135-
generate_json_string(buffer, data, state, obj);
1136+
generate_json_string(buffer, data, obj);
11361137
break;
11371138
case T_SYMBOL:
1138-
generate_json_symbol(buffer, data, state, obj);
1139+
generate_json_symbol(buffer, data, obj);
11391140
break;
11401141
case T_FLOAT:
11411142
if (klass != rb_cFloat) goto general;
1142-
generate_json_float(buffer, data, state, obj);
1143+
generate_json_float(buffer, data, obj);
11431144
break;
11441145
case T_STRUCT:
11451146
if (klass != cFragment) goto general;
1146-
generate_json_fragment(buffer, data, state, obj);
1147+
generate_json_fragment(buffer, data, obj);
11471148
break;
11481149
default:
11491150
general:
1150-
if (state->strict) {
1151-
if (RTEST(state->as_json) && !as_json_called) {
1152-
obj = rb_proc_call_with_block(state->as_json, 1, &obj, Qnil);
1151+
if (data->state->strict) {
1152+
if (RTEST(data->state->as_json) && !as_json_called) {
1153+
obj = rb_proc_call_with_block(data->state->as_json, 1, &obj, Qnil);
11531154
as_json_called = true;
11541155
goto start;
11551156
} else {
11561157
raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
11571158
}
11581159
} else {
1159-
generate_json_fallback(buffer, data, state, obj);
1160+
generate_json_fallback(buffer, data, obj);
11601161
}
11611162
}
11621163
}
@@ -1166,7 +1167,7 @@ static VALUE generate_json_try(VALUE d)
11661167
{
11671168
struct generate_json_data *data = (struct generate_json_data *)d;
11681169

1169-
data->func(data->buffer, data, data->state, data->obj);
1170+
data->func(data->buffer, data, data->obj);
11701171

11711172
return Qnil;
11721173
}

0 commit comments

Comments
 (0)