ext/oj/object.c in oj-2.2.3 vs ext/oj/object.c in oj-2.3.0

- old
+ new

@@ -183,20 +183,42 @@ hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) { if (T_ARRAY == rb_type(value)) { int len = (int)RARRAY_LEN(value); if (2 == klen && 'u' == key[1]) { - volatile VALUE sc; + VALUE sc; if (0 == len) { oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data"); return 1; } - // If struct is not defined of new is not supported on the class then - // let this fail and raise an exception. + // If struct is not defined then we let this fail and raise an exception. sc = rb_const_get(oj_struct_class, rb_to_id(*RARRAY_PTR(value))); - parent->val = rb_funcall2(sc, oj_new_id, len - 1, RARRAY_PTR(value) + 1); + // Create a properly initialized struct instance without calling the initialize method. + parent->val = rb_obj_alloc(sc); + // If the JSON array has more entries than the struct class allows, we record an error. +#ifdef RSTRUCT_LEN + // MRI >= 1.9 + if (len - 1 > RSTRUCT_LEN(parent->val)) { + oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data"); + } else { + MEMCPY(RSTRUCT_PTR(parent->val), RARRAY_PTR(value) + 1, VALUE, len - 1); + } +#else + { + // MRI < 1.9 or Rubinius + int slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0)); + int i; + if (len - 1 > slen) { + oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data"); + } else { + for (i = 0; i < slen; i++) { + rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]); + } + } + } +#endif return 1; } else if (3 <= klen && '#' == key[1]) { volatile VALUE *a; if (2 != len) {