mini_racer 0.17.0.pre5 → 0.17.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,747 @@
1
+ #include <err.h>
2
+ #include <math.h>
3
+ #include <stdbool.h>
4
+ #include <stdint.h>
5
+ #include <stdlib.h>
6
+ #include <stdio.h>
7
+ #include <string.h>
8
+
9
+ static void des_null(void *arg);
10
+ static void des_undefined(void *arg);
11
+ static void des_bool(void *arg, int v);
12
+ static void des_int(void *arg, int64_t v);
13
+ static void des_num(void *arg, double v);
14
+ static void des_date(void *arg, double v);
15
+ // des_bigint: |p| points to |n|/8 quadwords in little-endian order
16
+ // des_bigint: |p| is not quadword aligned
17
+ // des_bigint: |n| is in bytes, not quadwords
18
+ // des_bigint: |n| is zero when bigint is zero
19
+ // des_bigint: |sign| is 1 or -1
20
+ static void des_bigint(void *arg, const void *p, size_t n, int sign);
21
+ static void des_string(void *arg, const char *s, size_t n);
22
+ static void des_string8(void *arg, const uint8_t *s, size_t n);
23
+ // des_string16: |s| is not word aligned
24
+ // des_string16: |n| is in bytes, not code points
25
+ static void des_string16(void *arg, const void *s, size_t n);
26
+ static void des_arraybuffer(void *arg, const void *s, size_t n);
27
+ static void des_array_begin(void *arg);
28
+ static void des_array_end(void *arg);
29
+ // called if e.g. an array object has named properties
30
+ static void des_named_props_begin(void *arg);
31
+ static void des_named_props_end(void *arg);
32
+ static void des_object_begin(void *arg);
33
+ static void des_object_end(void *arg);
34
+ static void des_object_ref(void *arg, uint32_t id);
35
+ // des_error_begin: followed by des_object_begin + des_object_end calls
36
+ static void des_error_begin(void *arg);
37
+ static void des_error_end(void *arg);
38
+
39
+ // dynamically sized buffer with inline storage so we don't
40
+ // have to worry about allocation failures for small payloads
41
+ typedef struct Buf {
42
+ uint8_t *buf;
43
+ uint32_t len, cap;
44
+ uint8_t buf_s[48];
45
+ } Buf;
46
+
47
+ typedef struct Ser {
48
+ Buf b;
49
+ char err[64];
50
+ } Ser;
51
+
52
+ static const uint8_t the_nan[8] = {0,0,0,0,0,0,0xF8,0x7F}; // canonical nan
53
+
54
+ // note: returns |v| if v in [0,1,2]
55
+ static inline uint32_t next_power_of_two(uint32_t v) {
56
+ v -= 1;
57
+ v |= v >> 1;
58
+ v |= v >> 2;
59
+ v |= v >> 4;
60
+ v |= v >> 8;
61
+ v |= v >> 16;
62
+ v += 1;
63
+ return v;
64
+ }
65
+
66
+ static inline void buf_init(Buf *b)
67
+ {
68
+ b->len = 0;
69
+ b->buf = b->buf_s;
70
+ b->cap = sizeof(b->buf_s);
71
+ }
72
+
73
+ static inline void buf_reset(Buf *b)
74
+ {
75
+ if (b->buf != b->buf_s)
76
+ free(b->buf);
77
+ buf_init(b);
78
+ }
79
+
80
+ static inline void buf_move(Buf *s, Buf *d)
81
+ {
82
+ if (s == d)
83
+ return;
84
+ *d = *s;
85
+ if (s->buf == s->buf_s)
86
+ d->buf = d->buf_s;
87
+ buf_init(s);
88
+ }
89
+
90
+ static inline int buf_grow(Buf *b, size_t n)
91
+ {
92
+ void *p;
93
+
94
+ if ((uint64_t)n + b->len > UINT32_MAX)
95
+ return -1;
96
+ n += b->len;
97
+ if (n < b->cap)
98
+ return 0;
99
+ n = next_power_of_two(n);
100
+ p = NULL;
101
+ if (b->buf != b->buf_s)
102
+ p = b->buf;
103
+ p = realloc(p, n);
104
+ if (!p)
105
+ return -1;
106
+ if (b->buf == b->buf_s)
107
+ memcpy(p, b->buf_s, b->len);
108
+ b->buf = p;
109
+ b->cap = n;
110
+ return 0;
111
+ }
112
+
113
+ static inline int buf_put(Buf *b, const void *p, size_t n)
114
+ {
115
+ if (n == 0)
116
+ return 0;
117
+ if (buf_grow(b, n))
118
+ return -1;
119
+ memcpy(&b->buf[b->len], p, n);
120
+ b->len += n;
121
+ return 0;
122
+ }
123
+
124
+ static inline int buf_putc(Buf *b, uint8_t c)
125
+ {
126
+ return buf_put(b, &c, 1);
127
+ }
128
+
129
+ static inline void w(Ser *s, const void *p, size_t n)
130
+ {
131
+ if (*s->err)
132
+ return;
133
+ if (buf_put(&s->b, p, n))
134
+ snprintf(s->err, sizeof(s->err), "out of memory");
135
+ }
136
+
137
+ static inline void w_byte(Ser *s, uint8_t c)
138
+ {
139
+ w(s, &c, 1);
140
+ }
141
+
142
+ static inline void w_varint(Ser *s, uint64_t v)
143
+ {
144
+ uint8_t b[10]; // 10 == 1 + 64/7
145
+ size_t n;
146
+
147
+ for (n = 0; v > 127; v >>= 7)
148
+ b[n++] = 128 | (v & 127);
149
+ b[n++] = v;
150
+ w(s, b, n);
151
+ }
152
+
153
+ static inline void w_zigzag(Ser *s, int64_t v)
154
+ {
155
+ uint64_t t;
156
+
157
+ if (v < 0) {
158
+ t = -v;
159
+ } else {
160
+ t = v;
161
+ }
162
+ t += t;
163
+ t -= (v < 0);
164
+ w_varint(s, t);
165
+ }
166
+
167
+ static inline int r_varint(const uint8_t **p, const uint8_t *pe, uint64_t *r)
168
+ {
169
+ int i, k;
170
+
171
+ for (i = 0; i < 5; i++) {
172
+ if (*p+i == pe)
173
+ return -1;
174
+ if ((*p)[i] < 128)
175
+ goto ok;
176
+ }
177
+ return -1;
178
+ ok:
179
+ *r = 0;
180
+ for (k = 0; k <= i; k++, (*p)++)
181
+ *r |= (uint64_t)(**p & 127) << 7*k;
182
+ return 0;
183
+ }
184
+
185
+ static inline int r_zigzag(const uint8_t **p, const uint8_t *pe, int64_t *r)
186
+ {
187
+ uint64_t v;
188
+
189
+ if (r_varint(p, pe, &v))
190
+ return -1;
191
+ *r = v&1 ? -(v/2)-1 : v/2;
192
+ return 0;
193
+ }
194
+
195
+ static inline void ser_init(Ser *s)
196
+ {
197
+ memset(s, 0, sizeof(*s));
198
+ buf_init(&s->b);
199
+ w(s, "\xFF\x0F", 2);
200
+ }
201
+
202
+ static void ser_init1(Ser *s, uint8_t c)
203
+ {
204
+ memset(s, 0, sizeof(*s));
205
+ buf_init(&s->b);
206
+ w_byte(s, c);
207
+ w(s, "\xFF\x0F", 2);
208
+ }
209
+
210
+ static void ser_reset(Ser *s)
211
+ {
212
+ buf_reset(&s->b);
213
+ }
214
+
215
+ static void ser_null(Ser *s)
216
+ {
217
+ w_byte(s, '0');
218
+ }
219
+
220
+ static void ser_undefined(Ser *s)
221
+ {
222
+ w_byte(s, '_');
223
+ }
224
+
225
+ static void ser_bool(Ser *s, int v)
226
+ {
227
+ w_byte(s, "TF"[!v]);
228
+ }
229
+
230
+ static void ser_num(Ser *s, double v)
231
+ {
232
+ w_byte(s, 'N');
233
+ if (isnan(v)) {
234
+ w(s, the_nan, sizeof(the_nan));
235
+ } else {
236
+ w(s, &v, sizeof(v));
237
+ }
238
+ }
239
+
240
+ static void ser_int(Ser *s, int64_t v)
241
+ {
242
+ if (*s->err)
243
+ return;
244
+ if (v < INT32_MIN || v > INT32_MAX) {
245
+ if (v > INT64_MIN/1024)
246
+ if (v <= INT64_MAX/1024)
247
+ return ser_num(s, v);
248
+ snprintf(s->err, sizeof(s->err), "out of range: %lld", (long long)v);
249
+ } else {
250
+ w_byte(s, 'I');
251
+ w_zigzag(s, v);
252
+ }
253
+ }
254
+
255
+ // |v| is the timestamp in milliseconds since the UNIX epoch
256
+ static void ser_date(Ser *s, double v)
257
+ {
258
+ w_byte(s, 'D');
259
+ if (isfinite(v)) {
260
+ w(s, &v, sizeof(v));
261
+ } else {
262
+ w(s, the_nan, sizeof(the_nan));
263
+ }
264
+ }
265
+
266
+ // ser_bigint: |n| is in bytes, not quadwords
267
+ static void ser_bigint(Ser *s, const uint64_t *p, size_t n, int sign)
268
+ {
269
+ if (*s->err)
270
+ return;
271
+ if (n % 8) {
272
+ snprintf(s->err, sizeof(s->err), "bad bigint");
273
+ return;
274
+ }
275
+ w_byte(s, 'Z');
276
+ // chop off high all-zero words
277
+ n /= 8;
278
+ while (n--)
279
+ if (p[n])
280
+ break;
281
+ if (n == (size_t)-1) {
282
+ w_byte(s, 0); // normalized zero
283
+ } else {
284
+ n = 8*n + 8;
285
+ w_varint(s, 2*n + (sign < 0));
286
+ w(s, p, n);
287
+ }
288
+ }
289
+
290
+ // string must be utf8
291
+ static void ser_string(Ser *s, const char *p, size_t n)
292
+ {
293
+ w_byte(s, 'S');
294
+ w_varint(s, n);
295
+ w(s, p, n);
296
+ }
297
+
298
+ // string must be latin1
299
+ static void ser_string8(Ser *s, const uint8_t *p, size_t n)
300
+ {
301
+ w_byte(s, '"');
302
+ w_varint(s, n);
303
+ w(s, p, n);
304
+ }
305
+
306
+ static void ser_object_begin(Ser *s)
307
+ {
308
+ w_byte(s, 'o');
309
+ }
310
+
311
+ // |count| is the property count
312
+ static void ser_object_end(Ser *s, uint32_t count)
313
+ {
314
+ w_byte(s, '{');
315
+ w_varint(s, count);
316
+ }
317
+
318
+ static void ser_object_ref(Ser *s, uint32_t id)
319
+ {
320
+ w_byte(s, '^');
321
+ w_varint(s, id);
322
+ }
323
+
324
+ static void ser_array_begin(Ser *s, uint32_t count)
325
+ {
326
+ w_byte(s, 'A'); // 'A'=dense, 'a'=sparse
327
+ w_varint(s, count); // element count
328
+ }
329
+
330
+ // |count| is the element count
331
+ static void ser_array_end(Ser *s, uint32_t count)
332
+ {
333
+ w_byte(s, '$');
334
+ w_varint(s, 0); // property count, always zero
335
+ w_varint(s, count); // element count
336
+ }
337
+
338
+ static int bail(char (*err)[64], const char *str)
339
+ {
340
+ snprintf(*err, sizeof(*err), "%s", str);
341
+ return -1;
342
+ }
343
+
344
+ static int des1_num(const uint8_t **p, const uint8_t *pe, double *d)
345
+ {
346
+ if (pe-*p < (int)sizeof(*d))
347
+ return -1;
348
+ memcpy(d, *p, sizeof(*d));
349
+ *p += sizeof(*d);
350
+ if (isnan(*d))
351
+ memcpy(d, the_nan, sizeof(the_nan));
352
+ return 0;
353
+ }
354
+
355
+ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
356
+ void *arg, int depth)
357
+ {
358
+ uint64_t s, t, u;
359
+ uint8_t c;
360
+ int64_t i;
361
+ double d;
362
+
363
+ if (depth < 0)
364
+ return bail(err, "too much recursion");
365
+ if (*p >= pe)
366
+ goto too_short;
367
+ switch ((c = *(*p)++)) {
368
+ default:
369
+ if (c > 32 && c < 127) {
370
+ snprintf(*err, sizeof(*err), "bad tag: %c", c);
371
+ } else {
372
+ snprintf(*err, sizeof(*err), "bad tag: %02x", c);
373
+ }
374
+ return -1;
375
+ case '\0': // padding
376
+ break;
377
+ case '^':
378
+ if (r_varint(p, pe, &u))
379
+ goto bad_varint;
380
+ des_object_ref(arg, u);
381
+ // object refs can (but need not be) followed by a typed array
382
+ // that is a view over the arraybufferview
383
+ goto typed_array;
384
+ case '0':
385
+ des_null(arg);
386
+ break;
387
+ case '_':
388
+ des_undefined(arg);
389
+ break;
390
+ case 'A': // dense array
391
+ if (r_varint(p, pe, &u))
392
+ goto bad_varint;
393
+ t = u;
394
+ des_array_begin(arg);
395
+ while (u--) {
396
+ if (*p >= pe)
397
+ goto too_short;
398
+ // '-' is 'the hole', a marker for representing absent
399
+ // elements that is inserted when a dense array turns
400
+ // sparse during serialization; we replace it with undefined
401
+ if (**p == '-') {
402
+ (*p)++;
403
+ des_undefined(arg);
404
+ } else {
405
+ if (des1(err, p, pe, arg, depth-1))
406
+ return -1;
407
+ }
408
+ }
409
+ for (s = 0; /*empty*/; s++) {
410
+ if (*p >= pe)
411
+ goto too_short;
412
+ if (**p == '$')
413
+ break;
414
+ if (s < 1)
415
+ des_named_props_begin(arg);
416
+ if (des1(err, p, pe, arg, depth-1)) // key
417
+ return -1;
418
+ if (des1(err, p, pe, arg, depth-1)) // value
419
+ return -1;
420
+ }
421
+ (*p)++;
422
+ if (s > 0)
423
+ des_named_props_end(arg);
424
+ if (r_varint(p, pe, &u))
425
+ goto bad_varint;
426
+ if (s != u)
427
+ return bail(err, "array property count mismatch");
428
+ if (r_varint(p, pe, &u))
429
+ goto bad_varint;
430
+ if (t != u)
431
+ return bail(err, "array element count mismatch");
432
+ des_array_end(arg);
433
+ break;
434
+ case 'B': // arraybuffer
435
+ case '~': // resizable arraybuffer (RAB)
436
+ if (r_varint(p, pe, &u))
437
+ goto bad_varint;
438
+ if (c == '~')
439
+ if (r_varint(p, pe, &t)) // maxByteLength, unused
440
+ goto bad_varint;
441
+ if (pe-*p < (int64_t)u)
442
+ goto too_short;
443
+ des_arraybuffer(arg, *p, u);
444
+ *p += u;
445
+ // arraybuffers can (but need not be) followed by a typed array
446
+ // that is a view over the arraybufferview
447
+ // typed arrays aren't efficiently representable in ruby, and the
448
+ // concept of a memory view is wholly unrepresentable, so we
449
+ // simply skip over them; callers get just the arraybuffer
450
+ typed_array:
451
+ if (pe-*p < 2)
452
+ break;
453
+ if (**p != 'V')
454
+ break;
455
+ (*p)++;
456
+ c = *(*p)++;
457
+ // ? DataView
458
+ // B Uint8Array
459
+ // C Uint8ClampedArray
460
+ // D Uint32Array
461
+ // F Float64Array
462
+ // Q BigUint64Array
463
+ // W Uint16Array
464
+ // b Int8Array
465
+ // d Int32Array
466
+ // f Float32Array
467
+ // h Float16Array
468
+ // q BigInt64Array
469
+ // w Int16Array
470
+ if (!strchr("?BCDFQWbdfhqw", **p))
471
+ return bail(err, "bad typed array");
472
+ if (r_varint(p, pe, &t)) // byteOffset
473
+ goto bad_varint;
474
+ if (r_varint(p, pe, &t)) // byteLength
475
+ goto bad_varint;
476
+ if (r_varint(p, pe, &t)) // flags, only non-zero when backed by RAB
477
+ goto bad_varint;
478
+ break;
479
+ case 'a': // sparse array
480
+ // total element count; ignored because we drop sparse entries
481
+ if (r_varint(p, pe, &t))
482
+ goto bad_varint;
483
+ des_array_begin(arg);
484
+ for (u = s = 0;;) {
485
+ if (*p >= pe)
486
+ goto too_short;
487
+ c = **p;
488
+ if (c == '@')
489
+ break;
490
+ if (c == 'I' && !s) {
491
+ u++, (*p)++;
492
+ if (r_zigzag(p, pe, &i)) // array index, ignored
493
+ goto bad_varint;
494
+ if (des1(err, p, pe, arg, depth-1))
495
+ return -1;
496
+ } else {
497
+ if (!s++)
498
+ des_named_props_begin(arg);
499
+ if (des1(err, p, pe, arg, depth-1)) // key
500
+ return -1;
501
+ if (des1(err, p, pe, arg, depth-1)) // value
502
+ return -1;
503
+ }
504
+ }
505
+ (*p)++;
506
+ if (s > 0)
507
+ des_named_props_end(arg);
508
+ if (r_varint(p, pe, &t))
509
+ goto bad_varint;
510
+ if (t != u+s)
511
+ return bail(err, "element count mismatch");
512
+ // total element count; ignored because we drop sparse entries
513
+ if (r_varint(p, pe, &t))
514
+ goto bad_varint;
515
+ des_array_end(arg);
516
+ break;
517
+ case 'D':
518
+ if (des1_num(p, pe, &d))
519
+ goto too_short;
520
+ des_date(arg, d);
521
+ break;
522
+ case 'F': // primitive boolean
523
+ case 'x': // new Boolean(...)
524
+ des_bool(arg, 0);
525
+ break;
526
+ case 'T': // primitive boolean
527
+ case 'y': // new Boolean(...)
528
+ des_bool(arg, 1);
529
+ break;
530
+ case 'I':
531
+ if (r_zigzag(p, pe, &i))
532
+ goto bad_varint;
533
+ des_int(arg, i);
534
+ break;
535
+ case 'N': // primitive number
536
+ case 'n': // new Number(...)
537
+ if (des1_num(p, pe, &d))
538
+ goto too_short;
539
+ des_num(arg, d);
540
+ break;
541
+ case 'Z':
542
+ if (r_varint(p, pe, &u))
543
+ goto bad_varint;
544
+ t = u & 1;
545
+ u = u >> 1;
546
+ if (u & 7)
547
+ return bail(err, "bad bigint");
548
+ // V8's serializer never emits -0n;
549
+ // its deserializer rejects it with DataCloneError
550
+ if (t && !u)
551
+ return bail(err, "negative zero bigint");
552
+ if (pe-*p < (int64_t)u)
553
+ goto too_short;
554
+ des_bigint(arg, *p, u, 1-2*t);
555
+ *p += u;
556
+ break;
557
+ case 'R': // RegExp, deserialized as string
558
+ if (*p >= pe)
559
+ goto too_short;
560
+ switch (**p) {
561
+ default:
562
+ return bail(err, "bad regexp");
563
+ case '"':
564
+ case 'S':
565
+ case 'c':
566
+ break;
567
+ }
568
+ if (des1(err, p, pe, arg, depth-1)) // pattern
569
+ return -1;
570
+ if (r_varint(p, pe, &t)) // flags; ignored
571
+ goto bad_varint;
572
+ break;
573
+ case 's': // string object, decoded as primitive string
574
+ if (*p >= pe)
575
+ goto too_short;
576
+ switch (*(*p)++) {
577
+ case '"':
578
+ goto s_string8;
579
+ case 'S':
580
+ goto s_string;
581
+ case 'c':
582
+ goto s_string16;
583
+ }
584
+ return bail(err, "bad string object");
585
+ case '"': // ascii/latin1
586
+ s_string8:
587
+ if (r_varint(p, pe, &u))
588
+ goto bad_varint;
589
+ if (pe-*p < (int64_t)u)
590
+ goto too_short;
591
+ des_string8(arg, *p, u);
592
+ *p += u;
593
+ break;
594
+ case 'S': // utf8
595
+ s_string:
596
+ if (r_varint(p, pe, &u))
597
+ goto bad_varint;
598
+ if (pe-*p < (int64_t)u)
599
+ goto too_short;
600
+ des_string(arg, (void *)*p, u);
601
+ *p += u;
602
+ break;
603
+ case 'c': // utf16-le
604
+ s_string16:
605
+ if (r_varint(p, pe, &u))
606
+ goto bad_varint;
607
+ if (pe-*p < (int64_t)u)
608
+ goto too_short;
609
+ if (u & 1)
610
+ return bail(err, "bad utf16 string size");
611
+ des_string16(arg, *p, u);
612
+ *p += u;
613
+ break;
614
+ case 'o':
615
+ des_object_begin(arg);
616
+ for (u = 0;; u++) {
617
+ if (pe-*p < 1)
618
+ goto too_short;
619
+ if (**p == '{')
620
+ break;
621
+ if (des1(err, p, pe, arg, depth-1)) // key
622
+ return -1;
623
+ if (des1(err, p, pe, arg, depth-1)) // value
624
+ return -1;
625
+ }
626
+ (*p)++;
627
+ if (r_varint(p, pe, &t))
628
+ goto bad_varint;
629
+ if (t != u)
630
+ return bail(err, "object properties count mismatch");
631
+ des_object_end(arg);
632
+ break;
633
+ case ';': // Map
634
+ des_object_begin(arg);
635
+ for (u = 0; /*empty*/; u++) {
636
+ if (*p >= pe)
637
+ goto too_short;
638
+ if (**p == ':')
639
+ break;
640
+ if (des1(err, p, pe, arg, depth-1)) // key
641
+ return -1;
642
+ if (des1(err, p, pe, arg, depth-1)) // value
643
+ return -1;
644
+ }
645
+ (*p)++;
646
+ if (r_varint(p, pe, &t))
647
+ goto bad_varint;
648
+ if (t != 2*u)
649
+ return bail(err, "map element count mismatch");
650
+ des_object_end(arg);
651
+ break;
652
+ case '\'': // Set
653
+ des_array_begin(arg);
654
+ for (u = 0; /*empty*/; u++) {
655
+ if (*p >= pe)
656
+ goto too_short;
657
+ if (**p == ',')
658
+ break;
659
+ if (des1(err, p, pe, arg, depth-1)) // value
660
+ return -1;
661
+ }
662
+ (*p)++;
663
+ if (r_varint(p, pe, &t))
664
+ goto bad_varint;
665
+ if (t != u)
666
+ return bail(err, "set element count mismatch");
667
+ des_array_end(arg);
668
+ break;
669
+ case 'r':
670
+ // shortest error is /r[.]/ - Error with no message, cause, or stack
671
+ // longest error is /r[EFRSTU]m<string>c<any>s<string>[.]/ where
672
+ // EFRSTU is one of {Eval,Reference,Range,Syntax,Type,URI}Error
673
+ des_error_begin(arg);
674
+ des_object_begin(arg);
675
+ if (*p >= pe)
676
+ goto too_short;
677
+ c = *(*p)++;
678
+ if (!strchr("EFRSTU", c))
679
+ goto r_message;
680
+ if (*p >= pe)
681
+ goto too_short;
682
+ c = *(*p)++;
683
+ r_message:
684
+ if (c != 'm')
685
+ goto r_stack;
686
+ des_string(arg, "message", sizeof("message")-1);
687
+ if (*p >= pe)
688
+ goto too_short;
689
+ if (!strchr("\"Sc", **p))
690
+ return bail(err, "error .message is not a string");
691
+ if (des1(err, p, pe, arg, depth-1))
692
+ return -1;
693
+ if (*p >= pe)
694
+ goto too_short;
695
+ c = *(*p)++;
696
+ r_stack:
697
+ if (c != 's')
698
+ goto r_cause;
699
+ des_string(arg, "stack", sizeof("stack")-1);
700
+ if (*p >= pe)
701
+ goto too_short;
702
+ if (!strchr("\"Sc", **p))
703
+ return bail(err, "error .stack is not a string");
704
+ if (des1(err, p, pe, arg, depth-1))
705
+ return -1;
706
+ if (*p >= pe)
707
+ goto too_short;
708
+ c = *(*p)++;
709
+ r_cause:
710
+ if (c != 'c')
711
+ goto r_end;
712
+ des_string(arg, "cause", sizeof("cause")-1);
713
+ if (des1(err, p, pe, arg, depth-1))
714
+ return -1;
715
+ if (*p >= pe)
716
+ goto too_short;
717
+ c = *(*p)++;
718
+ r_end:
719
+ if (c != '.')
720
+ return bail(err, "bad error object");
721
+ des_object_end(arg);
722
+ des_error_end(arg);
723
+ break;
724
+ }
725
+ return 0;
726
+ too_short:
727
+ return bail(err, "input too short");
728
+ bad_varint:
729
+ return bail(err, "bad varint");
730
+ }
731
+
732
+ int des(char (*err)[64], const void *b, size_t n, void *arg)
733
+ {
734
+ const uint8_t *p, *pe;
735
+
736
+ p = b, pe = p + n;
737
+ if (n < 2)
738
+ return bail(err, "input too short");
739
+ if (*p++ != 255)
740
+ return bail(err, "bad header");
741
+ if (*p++ != 15)
742
+ return bail(err, "bad version");
743
+ while (p < pe)
744
+ if (des1(err, &p, pe, arg, /*depth*/96))
745
+ return -1;
746
+ return 0;
747
+ }