oj 3.16.17 → 3.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +0 -16
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +2 -2
- data/ext/oj/dump.c +8 -8
- data/ext/oj/fast.c +36 -16
- data/ext/oj/intern.c +1 -1
- data/ext/oj/mimic_json.c +1 -0
- data/ext/oj/oj.c +32 -1
- data/ext/oj/oj.h +38 -37
- data/ext/oj/parse.c +22 -2
- data/ext/oj/parser.c +79 -40
- data/ext/oj/rxclass.c +1 -1
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/safe.c +230 -0
- data/ext/oj/safe.h +79 -0
- data/ext/oj/sparse.c +3 -0
- data/ext/oj/usual.c +18 -5
- data/ext/oj/wab.c +1 -1
- data/lib/oj/version.rb +1 -1
- metadata +4 -2
data/ext/oj/parser.c
CHANGED
|
@@ -75,7 +75,7 @@ enum {
|
|
|
75
75
|
|
|
76
76
|
/*
|
|
77
77
|
0123456789abcdef0123456789abcdef */
|
|
78
|
-
static const char value_map[
|
|
78
|
+
static const char value_map[258] = "\
|
|
79
79
|
X........ab..a..................\
|
|
80
80
|
a.i..........f..ghhhhhhhhh......\
|
|
81
81
|
...........................k.m..\
|
|
@@ -85,7 +85,7 @@ a.i..........f..ghhhhhhhhh......\
|
|
|
85
85
|
................................\
|
|
86
86
|
................................v";
|
|
87
87
|
|
|
88
|
-
static const char null_map[
|
|
88
|
+
static const char null_map[258] = "\
|
|
89
89
|
................................\
|
|
90
90
|
............o...................\
|
|
91
91
|
................................\
|
|
@@ -95,7 +95,7 @@ static const char null_map[257] = "\
|
|
|
95
95
|
................................\
|
|
96
96
|
................................N";
|
|
97
97
|
|
|
98
|
-
static const char true_map[
|
|
98
|
+
static const char true_map[258] = "\
|
|
99
99
|
................................\
|
|
100
100
|
............o...................\
|
|
101
101
|
................................\
|
|
@@ -105,7 +105,7 @@ static const char true_map[257] = "\
|
|
|
105
105
|
................................\
|
|
106
106
|
................................T";
|
|
107
107
|
|
|
108
|
-
static const char false_map[
|
|
108
|
+
static const char false_map[258] = "\
|
|
109
109
|
................................\
|
|
110
110
|
............o...................\
|
|
111
111
|
................................\
|
|
@@ -115,7 +115,7 @@ static const char false_map[257] = "\
|
|
|
115
115
|
................................\
|
|
116
116
|
................................F";
|
|
117
117
|
|
|
118
|
-
static const char comma_map[
|
|
118
|
+
static const char comma_map[258] = "\
|
|
119
119
|
.........ab..a..................\
|
|
120
120
|
a.i..........f..ghhhhhhhhh......\
|
|
121
121
|
...........................k....\
|
|
@@ -125,7 +125,7 @@ a.i..........f..ghhhhhhhhh......\
|
|
|
125
125
|
................................\
|
|
126
126
|
................................,";
|
|
127
127
|
|
|
128
|
-
static const char after_map[
|
|
128
|
+
static const char after_map[258] = "\
|
|
129
129
|
X........ab..a..................\
|
|
130
130
|
a...........o...................\
|
|
131
131
|
.............................m..\
|
|
@@ -135,7 +135,7 @@ a...........o...................\
|
|
|
135
135
|
................................\
|
|
136
136
|
................................a";
|
|
137
137
|
|
|
138
|
-
static const char key1_map[
|
|
138
|
+
static const char key1_map[258] = "\
|
|
139
139
|
.........ab..a..................\
|
|
140
140
|
a.p.............................\
|
|
141
141
|
................................\
|
|
@@ -145,7 +145,7 @@ a.p.............................\
|
|
|
145
145
|
................................\
|
|
146
146
|
................................K";
|
|
147
147
|
|
|
148
|
-
static const char key_map[
|
|
148
|
+
static const char key_map[258] = "\
|
|
149
149
|
.........ab..a..................\
|
|
150
150
|
a.p.............................\
|
|
151
151
|
................................\
|
|
@@ -155,7 +155,7 @@ a.p.............................\
|
|
|
155
155
|
................................\
|
|
156
156
|
................................k";
|
|
157
157
|
|
|
158
|
-
static const char colon_map[
|
|
158
|
+
static const char colon_map[258] = "\
|
|
159
159
|
.........ab..a..................\
|
|
160
160
|
a.........................q.....\
|
|
161
161
|
................................\
|
|
@@ -165,7 +165,7 @@ a.........................q.....\
|
|
|
165
165
|
................................\
|
|
166
166
|
................................:";
|
|
167
167
|
|
|
168
|
-
static const char neg_map[
|
|
168
|
+
static const char neg_map[258] = "\
|
|
169
169
|
................................\
|
|
170
170
|
................O---------......\
|
|
171
171
|
................................\
|
|
@@ -175,7 +175,7 @@ static const char neg_map[257] = "\
|
|
|
175
175
|
................................\
|
|
176
176
|
................................-";
|
|
177
177
|
|
|
178
|
-
static const char zero_map[
|
|
178
|
+
static const char zero_map[258] = "\
|
|
179
179
|
.........rs..r..................\
|
|
180
180
|
r...........u.t.................\
|
|
181
181
|
.............................H..\
|
|
@@ -185,7 +185,7 @@ r...........u.t.................\
|
|
|
185
185
|
................................\
|
|
186
186
|
................................0";
|
|
187
187
|
|
|
188
|
-
static const char digit_map[
|
|
188
|
+
static const char digit_map[258] = "\
|
|
189
189
|
.........rs..r..................\
|
|
190
190
|
r...........u.t.NNNNNNNNNN......\
|
|
191
191
|
.....w.......................H..\
|
|
@@ -195,7 +195,7 @@ r...........u.t.NNNNNNNNNN......\
|
|
|
195
195
|
................................\
|
|
196
196
|
................................d";
|
|
197
197
|
|
|
198
|
-
static const char dot_map[
|
|
198
|
+
static const char dot_map[258] = "\
|
|
199
199
|
................................\
|
|
200
200
|
................vvvvvvvvvv......\
|
|
201
201
|
................................\
|
|
@@ -205,7 +205,7 @@ static const char dot_map[257] = "\
|
|
|
205
205
|
................................\
|
|
206
206
|
.................................";
|
|
207
207
|
|
|
208
|
-
static const char frac_map[
|
|
208
|
+
static const char frac_map[258] = "\
|
|
209
209
|
.........rs..r..................\
|
|
210
210
|
r...........u...vvvvvvvvvv......\
|
|
211
211
|
.....w.......................H..\
|
|
@@ -215,7 +215,7 @@ r...........u...vvvvvvvvvv......\
|
|
|
215
215
|
................................\
|
|
216
216
|
................................f";
|
|
217
217
|
|
|
218
|
-
static const char exp_sign_map[
|
|
218
|
+
static const char exp_sign_map[258] = "\
|
|
219
219
|
................................\
|
|
220
220
|
...........x.x..yyyyyyyyyy......\
|
|
221
221
|
................................\
|
|
@@ -225,7 +225,7 @@ static const char exp_sign_map[257] = "\
|
|
|
225
225
|
................................\
|
|
226
226
|
................................x";
|
|
227
227
|
|
|
228
|
-
static const char exp_zero_map[
|
|
228
|
+
static const char exp_zero_map[258] = "\
|
|
229
229
|
................................\
|
|
230
230
|
................yyyyyyyyyy......\
|
|
231
231
|
................................\
|
|
@@ -235,7 +235,7 @@ static const char exp_zero_map[257] = "\
|
|
|
235
235
|
................................\
|
|
236
236
|
................................z";
|
|
237
237
|
|
|
238
|
-
static const char exp_map[
|
|
238
|
+
static const char exp_map[258] = "\
|
|
239
239
|
.........rs..r..................\
|
|
240
240
|
r...........u...yyyyyyyyyy......\
|
|
241
241
|
.............................H..\
|
|
@@ -245,7 +245,7 @@ r...........u...yyyyyyyyyy......\
|
|
|
245
245
|
................................\
|
|
246
246
|
................................X";
|
|
247
247
|
|
|
248
|
-
static const char big_digit_map[
|
|
248
|
+
static const char big_digit_map[258] = "\
|
|
249
249
|
.........rs..r..................\
|
|
250
250
|
r...........u.D.CCCCCCCCCC......\
|
|
251
251
|
.....J.......................H..\
|
|
@@ -255,7 +255,7 @@ r...........u.D.CCCCCCCCCC......\
|
|
|
255
255
|
................................\
|
|
256
256
|
................................D";
|
|
257
257
|
|
|
258
|
-
static const char big_dot_map[
|
|
258
|
+
static const char big_dot_map[258] = "\
|
|
259
259
|
................................\
|
|
260
260
|
................IIIIIIIIII......\
|
|
261
261
|
................................\
|
|
@@ -265,7 +265,7 @@ static const char big_dot_map[257] = "\
|
|
|
265
265
|
................................\
|
|
266
266
|
................................o";
|
|
267
267
|
|
|
268
|
-
static const char big_frac_map[
|
|
268
|
+
static const char big_frac_map[258] = "\
|
|
269
269
|
.........rs..r..................\
|
|
270
270
|
r...........u...IIIIIIIIII......\
|
|
271
271
|
.....J.......................H..\
|
|
@@ -275,7 +275,7 @@ r...........u...IIIIIIIIII......\
|
|
|
275
275
|
................................\
|
|
276
276
|
................................g";
|
|
277
277
|
|
|
278
|
-
static const char big_exp_sign_map[
|
|
278
|
+
static const char big_exp_sign_map[258] = "\
|
|
279
279
|
................................\
|
|
280
280
|
...........K.K..LLLLLLLLLL......\
|
|
281
281
|
................................\
|
|
@@ -285,7 +285,7 @@ static const char big_exp_sign_map[257] = "\
|
|
|
285
285
|
................................\
|
|
286
286
|
................................B";
|
|
287
287
|
|
|
288
|
-
static const char big_exp_zero_map[
|
|
288
|
+
static const char big_exp_zero_map[258] = "\
|
|
289
289
|
................................\
|
|
290
290
|
................LLLLLLLLLL......\
|
|
291
291
|
................................\
|
|
@@ -295,7 +295,7 @@ static const char big_exp_zero_map[257] = "\
|
|
|
295
295
|
................................\
|
|
296
296
|
................................Z";
|
|
297
297
|
|
|
298
|
-
static const char big_exp_map[
|
|
298
|
+
static const char big_exp_map[258] = "\
|
|
299
299
|
.........rs..r..................\
|
|
300
300
|
r...........u...LLLLLLLLLL......\
|
|
301
301
|
.............................H..\
|
|
@@ -305,7 +305,7 @@ r...........u...LLLLLLLLLL......\
|
|
|
305
305
|
................................\
|
|
306
306
|
................................Y";
|
|
307
307
|
|
|
308
|
-
static const char string_map[
|
|
308
|
+
static const char string_map[258] = "\
|
|
309
309
|
................................\
|
|
310
310
|
RRzRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
|
|
311
311
|
RRRRRRRRRRRRRRRRRRRRRRRRRRRRARRR\
|
|
@@ -315,7 +315,7 @@ RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
|
|
|
315
315
|
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\
|
|
316
316
|
PPPPPPPPPPPPPPPPQQQQQQQQ........s";
|
|
317
317
|
|
|
318
|
-
static const char esc_map[
|
|
318
|
+
static const char esc_map[258] = "\
|
|
319
319
|
................................\
|
|
320
320
|
..B............B................\
|
|
321
321
|
............................B...\
|
|
@@ -325,7 +325,7 @@ static const char esc_map[257] = "\
|
|
|
325
325
|
................................\
|
|
326
326
|
................................~";
|
|
327
327
|
|
|
328
|
-
static const char esc_byte_map[
|
|
328
|
+
static const char esc_byte_map[258] = "\
|
|
329
329
|
................................\
|
|
330
330
|
..\"............/................\
|
|
331
331
|
............................\\...\
|
|
@@ -335,7 +335,7 @@ static const char esc_byte_map[257] = "\
|
|
|
335
335
|
................................\
|
|
336
336
|
................................b";
|
|
337
337
|
|
|
338
|
-
static const char u_map[
|
|
338
|
+
static const char u_map[258] = "\
|
|
339
339
|
................................\
|
|
340
340
|
................EEEEEEEEEE......\
|
|
341
341
|
.EEEEEE.........................\
|
|
@@ -345,7 +345,7 @@ static const char u_map[257] = "\
|
|
|
345
345
|
................................\
|
|
346
346
|
................................u";
|
|
347
347
|
|
|
348
|
-
static const char utf_map[
|
|
348
|
+
static const char utf_map[258] = "\
|
|
349
349
|
................................\
|
|
350
350
|
................................\
|
|
351
351
|
................................\
|
|
@@ -355,7 +355,7 @@ SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\
|
|
|
355
355
|
................................\
|
|
356
356
|
................................8";
|
|
357
357
|
|
|
358
|
-
static const char space_map[
|
|
358
|
+
static const char space_map[258] = "\
|
|
359
359
|
.........ab..a..................\
|
|
360
360
|
a...............................\
|
|
361
361
|
................................\
|
|
@@ -365,7 +365,7 @@ a...............................\
|
|
|
365
365
|
................................\
|
|
366
366
|
................................S";
|
|
367
367
|
|
|
368
|
-
static const char trail_map[
|
|
368
|
+
static const char trail_map[258] = "\
|
|
369
369
|
.........ab..a..................\
|
|
370
370
|
a...............................\
|
|
371
371
|
................................\
|
|
@@ -375,7 +375,7 @@ a...............................\
|
|
|
375
375
|
................................\
|
|
376
376
|
................................R";
|
|
377
377
|
|
|
378
|
-
static const byte hex_map[
|
|
378
|
+
static const byte hex_map[257] = "\
|
|
379
379
|
................................\
|
|
380
380
|
................\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09......\
|
|
381
381
|
.\x0a\x0b\x0c\x0d\x0e\x0f.........................\
|
|
@@ -594,7 +594,7 @@ static void big_change(ojParser p) {
|
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
-
static void parse(ojParser p, const byte *json) {
|
|
597
|
+
static void parse(ojParser p, const byte *json, bool more) {
|
|
598
598
|
const byte *start;
|
|
599
599
|
const byte *b = json;
|
|
600
600
|
int i;
|
|
@@ -635,7 +635,7 @@ static void parse(ojParser p, const byte *json) {
|
|
|
635
635
|
if ('"' == *b) {
|
|
636
636
|
p->map = colon_map;
|
|
637
637
|
break;
|
|
638
|
-
} else if ('\0' == *b) {
|
|
638
|
+
} else if ('\0' == *b && !more) {
|
|
639
639
|
parse_error(p, "quoted string not terminated");
|
|
640
640
|
break;
|
|
641
641
|
}
|
|
@@ -662,7 +662,7 @@ static void parse(ojParser p, const byte *json) {
|
|
|
662
662
|
p->funcs[p->stack[p->depth]].add_str(p);
|
|
663
663
|
p->map = (0 == p->depth) ? value_map : after_map;
|
|
664
664
|
break;
|
|
665
|
-
} else if ('\0' == *b) {
|
|
665
|
+
} else if ('\0' == *b && !more) {
|
|
666
666
|
parse_error(p, "quoted string not terminated");
|
|
667
667
|
break;
|
|
668
668
|
}
|
|
@@ -674,6 +674,10 @@ static void parse(ojParser p, const byte *json) {
|
|
|
674
674
|
p->cur = b - json;
|
|
675
675
|
p->funcs[p->stack[p->depth]].open_object(p);
|
|
676
676
|
p->depth++;
|
|
677
|
+
if ((int)sizeof(p->stack) <= p->depth) {
|
|
678
|
+
parse_error(p, "too deeply nested");
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
677
681
|
p->stack[p->depth] = OBJECT_FUN;
|
|
678
682
|
p->map = key1_map;
|
|
679
683
|
break;
|
|
@@ -696,6 +700,10 @@ static void parse(ojParser p, const byte *json) {
|
|
|
696
700
|
p->cur = b - json;
|
|
697
701
|
p->funcs[p->stack[p->depth]].open_array(p);
|
|
698
702
|
p->depth++;
|
|
703
|
+
if ((int)sizeof(p->stack) <= p->depth) {
|
|
704
|
+
parse_error(p, "too deeply nested");
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
699
707
|
p->stack[p->depth] = ARRAY_FUN;
|
|
700
708
|
p->map = value_map;
|
|
701
709
|
break;
|
|
@@ -1182,6 +1190,8 @@ extern void oj_set_parser_validator(ojParser p);
|
|
|
1182
1190
|
extern void oj_set_parser_saj(ojParser p);
|
|
1183
1191
|
extern void oj_set_parser_usual(ojParser p);
|
|
1184
1192
|
extern void oj_set_parser_debug(ojParser p);
|
|
1193
|
+
extern void oj_set_parser_safe(ojParser p, VALUE options);
|
|
1194
|
+
extern void oj_safe_init(VALUE parser_class);
|
|
1185
1195
|
|
|
1186
1196
|
static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
|
|
1187
1197
|
ojParser p = (ojParser)ptr;
|
|
@@ -1376,7 +1386,6 @@ static void validate_non_primitives_are_complete(ojParser p) {
|
|
|
1376
1386
|
if (0 >= p->depth) {
|
|
1377
1387
|
return;
|
|
1378
1388
|
}
|
|
1379
|
-
|
|
1380
1389
|
if (OBJECT_FUN == p->stack[p->depth]) {
|
|
1381
1390
|
parse_error(p, "Object is not closed");
|
|
1382
1391
|
} else {
|
|
@@ -1398,14 +1407,19 @@ static void validate_document_end(ojParser p) {
|
|
|
1398
1407
|
*/
|
|
1399
1408
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
|
1400
1409
|
ojParser p;
|
|
1401
|
-
|
|
1410
|
+
int frozen = OBJ_FROZEN(json);
|
|
1411
|
+
const byte *ptr;
|
|
1412
|
+
|
|
1413
|
+
if (!frozen) {
|
|
1414
|
+
rb_str_freeze(json);
|
|
1415
|
+
}
|
|
1416
|
+
ptr = (const byte *)StringValuePtr(json);
|
|
1402
1417
|
|
|
1403
1418
|
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1404
1419
|
|
|
1405
1420
|
parser_reset(p);
|
|
1406
1421
|
p->start(p);
|
|
1407
|
-
parse(p, ptr);
|
|
1408
|
-
|
|
1422
|
+
parse(p, ptr, false);
|
|
1409
1423
|
validate_document_end(p);
|
|
1410
1424
|
|
|
1411
1425
|
return p->result(p);
|
|
@@ -1426,7 +1440,7 @@ static VALUE load(VALUE self) {
|
|
|
1426
1440
|
while (true) {
|
|
1427
1441
|
rb_funcall(p->reader, oj_readpartial_id, 2, INT2NUM(16385), rbuf);
|
|
1428
1442
|
if (0 < RSTRING_LEN(rbuf)) {
|
|
1429
|
-
parse(p, (byte *)StringValuePtr(rbuf));
|
|
1443
|
+
parse(p, (byte *)StringValuePtr(rbuf), true);
|
|
1430
1444
|
}
|
|
1431
1445
|
if (Qtrue == rb_funcall(p->reader, oj_eofq_id, 0)) {
|
|
1432
1446
|
if (0 < p->depth) {
|
|
@@ -1496,7 +1510,7 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
|
1496
1510
|
while (true) {
|
|
1497
1511
|
if (0 < (rsize = read(fd, buf, size))) {
|
|
1498
1512
|
buf[rsize] = '\0';
|
|
1499
|
-
parse(p, buf);
|
|
1513
|
+
parse(p, buf, true);
|
|
1500
1514
|
}
|
|
1501
1515
|
if (rsize <= 0) {
|
|
1502
1516
|
if (0 != rsize) {
|
|
@@ -1607,6 +1621,28 @@ static VALUE parser_validate(VALUE self) {
|
|
|
1607
1621
|
return validate_parser;
|
|
1608
1622
|
}
|
|
1609
1623
|
|
|
1624
|
+
static VALUE parser_safe(int argc, VALUE *argv, VALUE self) {
|
|
1625
|
+
VALUE options;
|
|
1626
|
+
|
|
1627
|
+
if (1 == argc) {
|
|
1628
|
+
options = argv[0];
|
|
1629
|
+
|
|
1630
|
+
Check_Type(options, T_HASH);
|
|
1631
|
+
} else {
|
|
1632
|
+
options = rb_hash_new();
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
|
1636
|
+
|
|
1637
|
+
memset(p, 0, sizeof(struct _ojParser));
|
|
1638
|
+
buf_init(&p->key);
|
|
1639
|
+
buf_init(&p->buf);
|
|
1640
|
+
p->map = value_map;
|
|
1641
|
+
oj_set_parser_safe(p, options);
|
|
1642
|
+
|
|
1643
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1610
1646
|
/* Document-class: Oj::Parser
|
|
1611
1647
|
*
|
|
1612
1648
|
* A reusable parser that makes use of named delegates to determine the
|
|
@@ -1634,4 +1670,7 @@ void oj_parser_init(void) {
|
|
|
1634
1670
|
rb_define_module_function(parser_class, "usual", parser_usual, 0);
|
|
1635
1671
|
rb_define_module_function(parser_class, "saj", parser_saj, 0);
|
|
1636
1672
|
rb_define_module_function(parser_class, "validate", parser_validate, 0);
|
|
1673
|
+
rb_define_module_function(parser_class, "safe", parser_safe, -1);
|
|
1674
|
+
|
|
1675
|
+
oj_safe_init(parser_class);
|
|
1637
1676
|
}
|
data/ext/oj/rxclass.c
CHANGED
data/ext/oj/rxclass.h
CHANGED
|
@@ -19,7 +19,7 @@ typedef struct _rxClass {
|
|
|
19
19
|
extern void oj_rxclass_init(RxClass rc);
|
|
20
20
|
extern void oj_rxclass_cleanup(RxClass rc);
|
|
21
21
|
extern int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas);
|
|
22
|
-
extern VALUE oj_rxclass_match(RxClass rc, const char *str,
|
|
22
|
+
extern VALUE oj_rxclass_match(RxClass rc, const char *str, size_t len);
|
|
23
23
|
extern void oj_rxclass_copy(RxClass src, RxClass dest);
|
|
24
24
|
extern void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas);
|
|
25
25
|
|
data/ext/oj/safe.c
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
|
|
2
|
+
#include "safe.h"
|
|
3
|
+
|
|
4
|
+
static VALUE max_hash_size_sym, max_array_size_sym, max_depth_sym, max_total_elements_sym, max_hash_size_error_class,
|
|
5
|
+
max_array_size_error_class, max_depth_error_class, max_total_elements_error_class;
|
|
6
|
+
|
|
7
|
+
static void check_object_size(safe_T safe) {
|
|
8
|
+
if (NIL_P(safe->max_hash_size)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
struct _usual usual = safe->usual;
|
|
13
|
+
Col current_object_location = usual.ctail - 1;
|
|
14
|
+
|
|
15
|
+
long int number_of_items_in_stack = usual.vtail - usual.vhead;
|
|
16
|
+
long int number_of_items_in_hash = (number_of_items_in_stack - current_object_location->vi - 1) / 2;
|
|
17
|
+
|
|
18
|
+
if (safe->max_hash_size > number_of_items_in_hash) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
rb_raise(max_hash_size_error_class, "Too many object items!");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static void check_array_size(safe_T safe) {
|
|
26
|
+
if (NIL_P(safe->max_array_size)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
struct _usual usual = safe->usual;
|
|
31
|
+
Col current_object_location = usual.ctail - 1;
|
|
32
|
+
|
|
33
|
+
long int number_of_items_in_stack = usual.vtail - usual.vhead;
|
|
34
|
+
long int number_of_items_in_array = number_of_items_in_stack - current_object_location->vi - 1;
|
|
35
|
+
|
|
36
|
+
if (safe->max_array_size > number_of_items_in_array) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
rb_raise(max_array_size_error_class, "Too many array items!");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static void check_max_depth(safe_T safe, ojParser p) {
|
|
44
|
+
if (NIL_P(safe->max_depth) || safe->max_depth >= (p->depth + 1)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
rb_raise(max_depth_error_class, "JSON is too deep!");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static void check_max_total_elements(safe_T safe) {
|
|
52
|
+
/*
|
|
53
|
+
* We check if `max_total_elements` is greater than `current_elements_count`
|
|
54
|
+
* (instead of greater than or equal) because top-level elements (e.g., [],
|
|
55
|
+
* null, true) are not counted. As a result, `current_elements_count`
|
|
56
|
+
* always holds one less than the actual total.
|
|
57
|
+
*/
|
|
58
|
+
if (NIL_P(safe->max_total_elements) || safe->max_total_elements > safe->current_elements_count) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
rb_raise(max_total_elements_error_class, "Too many elements!");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static void safe_start(ojParser p) {
|
|
66
|
+
safe_T safe = (safe_T)p->ctx;
|
|
67
|
+
|
|
68
|
+
safe->current_hash_size = 0;
|
|
69
|
+
safe->current_array_size = 0;
|
|
70
|
+
safe->current_elements_count = 0;
|
|
71
|
+
|
|
72
|
+
safe->delegated_start_func(p);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static void safe_open_object(ojParser p) {
|
|
76
|
+
safe_T safe = (safe_T)p->ctx;
|
|
77
|
+
|
|
78
|
+
safe->current_hash_size++;
|
|
79
|
+
safe->current_elements_count++;
|
|
80
|
+
|
|
81
|
+
check_array_size(safe);
|
|
82
|
+
check_max_depth(safe, p);
|
|
83
|
+
check_max_total_elements(safe);
|
|
84
|
+
|
|
85
|
+
safe->delegated_open_object_func(p);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static void safe_open_array(ojParser p) {
|
|
89
|
+
safe_T safe = (safe_T)p->ctx;
|
|
90
|
+
|
|
91
|
+
safe->current_array_size++;
|
|
92
|
+
safe->current_elements_count++;
|
|
93
|
+
|
|
94
|
+
check_array_size(safe);
|
|
95
|
+
check_max_depth(safe, p);
|
|
96
|
+
check_max_total_elements(safe);
|
|
97
|
+
|
|
98
|
+
safe->delegated_open_array_func(p);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
DEFINE_DELEGATED_FUNCTION(add_null);
|
|
102
|
+
DEFINE_DELEGATED_FUNCTION(add_true);
|
|
103
|
+
DEFINE_DELEGATED_FUNCTION(add_false);
|
|
104
|
+
DEFINE_DELEGATED_FUNCTION(add_int);
|
|
105
|
+
DEFINE_DELEGATED_FUNCTION(add_float);
|
|
106
|
+
DEFINE_DELEGATED_FUNCTION(add_big);
|
|
107
|
+
DEFINE_DELEGATED_FUNCTION(add_str);
|
|
108
|
+
|
|
109
|
+
static void safe_open_object_key(ojParser p) {
|
|
110
|
+
safe_T safe = (safe_T)p->ctx;
|
|
111
|
+
|
|
112
|
+
safe->current_hash_size++;
|
|
113
|
+
safe->current_elements_count += 2;
|
|
114
|
+
|
|
115
|
+
check_object_size(safe);
|
|
116
|
+
check_max_depth(safe, p);
|
|
117
|
+
check_max_total_elements(safe);
|
|
118
|
+
|
|
119
|
+
safe->delegated_open_object_key_func(p);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
static void safe_open_array_key(ojParser p) {
|
|
123
|
+
safe_T safe = (safe_T)p->ctx;
|
|
124
|
+
|
|
125
|
+
safe->current_array_size++;
|
|
126
|
+
safe->current_elements_count += 2;
|
|
127
|
+
|
|
128
|
+
check_object_size(safe);
|
|
129
|
+
check_max_depth(safe, p);
|
|
130
|
+
check_max_total_elements(safe);
|
|
131
|
+
|
|
132
|
+
safe->delegated_open_array_key_func(p);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_null);
|
|
136
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_true);
|
|
137
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_false);
|
|
138
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_int);
|
|
139
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_float);
|
|
140
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_big);
|
|
141
|
+
DEFINE_DELEGATED_OBJECT_FUNCTION(add_str);
|
|
142
|
+
|
|
143
|
+
void oj_init_safe_parser(ojParser p, safe_T safe, VALUE options) {
|
|
144
|
+
// Safe parser inherits all members of usual parser
|
|
145
|
+
oj_init_usual(p, &safe->usual);
|
|
146
|
+
|
|
147
|
+
safe->delegated_start_func = p->start;
|
|
148
|
+
p->start = safe_start;
|
|
149
|
+
|
|
150
|
+
Funcs f;
|
|
151
|
+
|
|
152
|
+
// Array parser functions
|
|
153
|
+
f = &p->funcs[ARRAY_FUN];
|
|
154
|
+
safe->delegated_open_object_func = f->open_object;
|
|
155
|
+
f->open_object = safe_open_object;
|
|
156
|
+
safe->delegated_open_array_func = f->open_array;
|
|
157
|
+
f->open_array = safe_open_array;
|
|
158
|
+
// The following overrides are done for counting objects
|
|
159
|
+
safe->delegated_add_null_func = f->add_null;
|
|
160
|
+
f->add_null = safe_add_null;
|
|
161
|
+
safe->delegated_add_true_func = f->add_true;
|
|
162
|
+
f->add_true = safe_add_true;
|
|
163
|
+
safe->delegated_add_false_func = f->add_false;
|
|
164
|
+
f->add_false = safe_add_false;
|
|
165
|
+
safe->delegated_add_int_func = f->add_int;
|
|
166
|
+
f->add_int = safe_add_int;
|
|
167
|
+
safe->delegated_add_float_func = f->add_float;
|
|
168
|
+
f->add_float = safe_add_float;
|
|
169
|
+
safe->delegated_add_big_func = f->add_big;
|
|
170
|
+
f->add_big = safe_add_big;
|
|
171
|
+
safe->delegated_add_str_func = f->add_str;
|
|
172
|
+
f->add_str = safe_add_str;
|
|
173
|
+
|
|
174
|
+
// Object parser functions
|
|
175
|
+
f = &p->funcs[OBJECT_FUN];
|
|
176
|
+
safe->delegated_open_object_key_func = f->open_object;
|
|
177
|
+
f->open_object = safe_open_object_key;
|
|
178
|
+
safe->delegated_open_array_key_func = f->open_array;
|
|
179
|
+
f->open_array = safe_open_array_key;
|
|
180
|
+
// The following overrides are done for counting objects
|
|
181
|
+
safe->delegated_add_null_key_func = f->add_null;
|
|
182
|
+
f->add_null = safe_add_null_key;
|
|
183
|
+
safe->delegated_add_true_key_func = f->add_true;
|
|
184
|
+
f->add_true = safe_add_true_key;
|
|
185
|
+
safe->delegated_add_false_key_func = f->add_false;
|
|
186
|
+
f->add_false = safe_add_false_key;
|
|
187
|
+
safe->delegated_add_int_key_func = f->add_int;
|
|
188
|
+
f->add_int = safe_add_int_key;
|
|
189
|
+
safe->delegated_add_float_key_func = f->add_float;
|
|
190
|
+
f->add_float = safe_add_float_key;
|
|
191
|
+
safe->delegated_add_big_key_func = f->add_big;
|
|
192
|
+
f->add_big = safe_add_big_key;
|
|
193
|
+
safe->delegated_add_str_key_func = f->add_str;
|
|
194
|
+
f->add_str = safe_add_str_key;
|
|
195
|
+
|
|
196
|
+
SET_CONFIG(max_hash_size);
|
|
197
|
+
SET_CONFIG(max_array_size);
|
|
198
|
+
SET_CONFIG(max_depth);
|
|
199
|
+
SET_CONFIG(max_total_elements);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
void oj_set_parser_safe(ojParser p, VALUE options) {
|
|
203
|
+
safe_T s = OJ_R_ALLOC(struct _safe_S);
|
|
204
|
+
|
|
205
|
+
oj_init_safe_parser(p, s, options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void oj_safe_init(VALUE parser_class) {
|
|
209
|
+
VALUE validation_error_class = rb_define_class_under(parser_class, "ValidationError", rb_eRuntimeError);
|
|
210
|
+
|
|
211
|
+
max_hash_size_error_class = rb_define_class_under(parser_class, "HashSizeError", validation_error_class);
|
|
212
|
+
max_array_size_error_class = rb_define_class_under(parser_class, "ArraySizeError", validation_error_class);
|
|
213
|
+
max_depth_error_class = rb_define_class_under(parser_class, "DepthError", validation_error_class);
|
|
214
|
+
max_total_elements_error_class = rb_define_class_under(parser_class, "TotalElementsError", validation_error_class);
|
|
215
|
+
|
|
216
|
+
rb_gc_register_address(&max_hash_size_error_class);
|
|
217
|
+
rb_gc_register_address(&max_array_size_error_class);
|
|
218
|
+
rb_gc_register_address(&max_depth_error_class);
|
|
219
|
+
rb_gc_register_address(&max_total_elements_error_class);
|
|
220
|
+
|
|
221
|
+
max_hash_size_sym = ID2SYM(rb_intern("max_hash_size"));
|
|
222
|
+
max_array_size_sym = ID2SYM(rb_intern("max_array_size"));
|
|
223
|
+
max_depth_sym = ID2SYM(rb_intern("max_depth"));
|
|
224
|
+
max_total_elements_sym = ID2SYM(rb_intern("max_total_elements"));
|
|
225
|
+
|
|
226
|
+
rb_gc_register_address(&max_hash_size_sym);
|
|
227
|
+
rb_gc_register_address(&max_array_size_sym);
|
|
228
|
+
rb_gc_register_address(&max_depth_sym);
|
|
229
|
+
rb_gc_register_address(&max_total_elements_sym);
|
|
230
|
+
}
|