Skip to content

Commit 9ac5829

Browse files
authored
Merge pull request #574 from peterzhu2118/generator-mem-leak
Fix memory leak when exception is raised during JSON generation
2 parents 72d8d40 + 44df509 commit 9ac5829

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

ext/json/ext/generator/generator.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,6 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
892892
struct hash_foreach_arg arg;
893893

894894
if (max_nesting != 0 && depth > max_nesting) {
895-
fbuffer_free(buffer);
896895
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
897896
}
898897
fbuffer_append_char(buffer, '{');
@@ -927,7 +926,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
927926
long depth = ++state->depth;
928927
int i, j;
929928
if (max_nesting != 0 && depth > max_nesting) {
930-
fbuffer_free(buffer);
931929
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
932930
}
933931
fbuffer_append_char(buffer, '[');
@@ -1020,10 +1018,8 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
10201018
VALUE tmp = rb_funcall(obj, i_to_s, 0);
10211019
if (!allow_nan) {
10221020
if (isinf(value)) {
1023-
fbuffer_free(buffer);
10241021
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
10251022
} else if (isnan(value)) {
1026-
fbuffer_free(buffer);
10271023
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
10281024
}
10291025
}
@@ -1096,11 +1092,45 @@ static FBuffer *cState_prepare_buffer(VALUE self)
10961092
return buffer;
10971093
}
10981094

1095+
struct generate_json_data {
1096+
FBuffer *buffer;
1097+
VALUE vstate;
1098+
JSON_Generator_State *state;
1099+
VALUE obj;
1100+
};
1101+
1102+
static VALUE generate_json_try(VALUE d)
1103+
{
1104+
struct generate_json_data *data = (struct generate_json_data *)d;
1105+
1106+
generate_json(data->buffer, data->vstate, data->state, data->obj);
1107+
1108+
return Qnil;
1109+
}
1110+
1111+
static VALUE generate_json_rescue(VALUE d, VALUE exc)
1112+
{
1113+
struct generate_json_data *data = (struct generate_json_data *)d;
1114+
fbuffer_free(data->buffer);
1115+
1116+
rb_exc_raise(exc);
1117+
1118+
return Qundef;
1119+
}
1120+
10991121
static VALUE cState_partial_generate(VALUE self, VALUE obj)
11001122
{
11011123
FBuffer *buffer = cState_prepare_buffer(self);
11021124
GET_STATE(self);
1103-
generate_json(buffer, self, state, obj);
1125+
1126+
struct generate_json_data data = {
1127+
.buffer = buffer,
1128+
.vstate = self,
1129+
.state = state,
1130+
.obj = obj
1131+
};
1132+
rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1133+
11041134
return fbuffer_to_s(buffer);
11051135
}
11061136

0 commit comments

Comments
 (0)