File Coverage

XS.xs
Criterion Covered Total %
statement 597 782 76.3
branch 322 760 42.3
condition n/a
subroutine n/a
pod n/a
total 919 1542 59.6


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include
6             #include
7             #include
8             #include
9             #include
10             #include
11             #include
12              
13             #define ECB_NO_THREADS 1
14             #include "ecb.h"
15              
16             // compatibility with perl <5.18
17             #ifndef HvNAMELEN_get
18             # define HvNAMELEN_get(hv) strlen (HvNAME (hv))
19             #endif
20             #ifndef HvNAMELEN
21             # define HvNAMELEN(hv) HvNAMELEN_get (hv)
22             #endif
23             #ifndef HvNAMEUTF8
24             # define HvNAMEUTF8(hv) 0
25             #endif
26             #ifndef SvREFCNT_inc_NN
27             # define SvREFCNT_inc_NN(sv) SvREFCNT_inc (sv)
28             #endif
29             #ifndef SvREFCNT_dec_NN
30             # define SvREFCNT_dec_NN(sv) SvREFCNT_dec (sv)
31             #endif
32              
33             // perl's is_utf8_string interprets len=0 as "calculate len", but we want it to mean 0
34             #define cbor_is_utf8_string(str,len) (!(len) || is_utf8_string ((str), (len)))
35              
36             // known major and minor types
37             enum cbor_type
38             {
39             MAJOR_SHIFT = 5,
40             MINOR_MASK = 0x1f,
41              
42             MAJOR_POS_INT = 0 << MAJOR_SHIFT,
43             MAJOR_NEG_INT = 1 << MAJOR_SHIFT,
44             MAJOR_BYTES = 2 << MAJOR_SHIFT,
45             MAJOR_TEXT = 3 << MAJOR_SHIFT,
46             MAJOR_ARRAY = 4 << MAJOR_SHIFT,
47             MAJOR_MAP = 5 << MAJOR_SHIFT,
48             MAJOR_TAG = 6 << MAJOR_SHIFT,
49             MAJOR_MISC = 7 << MAJOR_SHIFT,
50              
51             // INT/STRING/ARRAY/MAP subtypes
52             LENGTH_EXT1 = 24,
53             LENGTH_EXT2 = 25,
54             LENGTH_EXT4 = 26,
55             LENGTH_EXT8 = 27,
56              
57             // SIMPLE types (effectively MISC subtypes)
58             SIMPLE_FALSE = 20,
59             SIMPLE_TRUE = 21,
60             SIMPLE_NULL = 22,
61             SIMPLE_UNDEF = 23,
62              
63             // MISC subtype (unused)
64             MISC_EXT1 = 24,
65             MISC_FLOAT16 = 25,
66             MISC_FLOAT32 = 26,
67             MISC_FLOAT64 = 27,
68              
69             // BYTES/TEXT/ARRAY/MAP
70             MINOR_INDEF = 31,
71             };
72              
73             // known tags
74             enum cbor_tag
75             {
76             // extensions
77             CBOR_TAG_STRINGREF = 25, // http://cbor.schmorp.de/stringref
78             CBOR_TAG_PERL_OBJECT = 26, // http://cbor.schmorp.de/perl-object
79             CBOR_TAG_GENERIC_OBJECT = 27, // http://cbor.schmorp.de/generic-object
80             CBOR_TAG_VALUE_SHAREABLE = 28, // http://cbor.schmorp.de/value-sharing
81             CBOR_TAG_VALUE_SHAREDREF = 29, // http://cbor.schmorp.de/value-sharing
82             CBOR_TAG_STRINGREF_NAMESPACE = 256, // http://cbor.schmorp.de/stringref
83             CBOR_TAG_INDIRECTION = 22098, // http://cbor.schmorp.de/indirection
84              
85             // rfc7049
86             CBOR_TAG_DATETIME = 0, // rfc4287, utf-8
87             CBOR_TAG_TIMESTAMP = 1, // unix timestamp, any
88             CBOR_TAG_POS_BIGNUM = 2, // byte string
89             CBOR_TAG_NEG_BIGNUM = 3, // byte string
90             CBOR_TAG_DECIMAL = 4, // decimal fraction, array
91             CBOR_TAG_BIGFLOAT = 5, // array
92              
93             CBOR_TAG_CONV_B64U = 21, // base64url, any
94             CBOR_TAG_CONV_B64 = 22, // base64, any
95             CBOR_TAG_CONV_HEX = 23, // base16, any
96             CBOR_TAG_CBOR = 24, // embedded cbor, byte string
97              
98             CBOR_TAG_URI = 32, // URI rfc3986, utf-8
99             CBOR_TAG_B64U = 33, // base64url rfc4648, utf-8
100             CBOR_TAG_B64 = 34, // base6 rfc46484, utf-8
101             CBOR_TAG_REGEX = 35, // regex pcre/ecma262, utf-8
102             CBOR_TAG_MIME = 36, // mime message rfc2045, utf-8
103              
104             CBOR_TAG_MAGIC = 55799, // self-describe cbor
105             };
106              
107             // known forced types, also hardcoded in CBOR.pm
108             enum
109             {
110             AS_CBOR = 0,
111             AS_INT = 1,
112             AS_BYTES = 2,
113             AS_TEXT = 3,
114             AS_FLOAT16 = 4,
115             AS_FLOAT32 = 5,
116             AS_FLOAT64 = 6,
117             AS_MAP = 7,
118             // possibly future enhancements: (generic) float, (generic) string
119             };
120              
121             #define F_SHRINK 0x00000001UL
122             #define F_ALLOW_UNKNOWN 0x00000002UL
123             #define F_ALLOW_SHARING 0x00000004UL
124             #define F_ALLOW_CYCLES 0x00000008UL
125             #define F_ALLOW_WEAK_CYCLES 0x00000010UL
126             #define F_FORBID_OBJECTS 0x00000020UL
127             #define F_PACK_STRINGS 0x00000040UL
128             #define F_TEXT_KEYS 0x00000080UL
129             #define F_TEXT_STRINGS 0x00000100UL
130             #define F_VALIDATE_UTF8 0x00000200UL
131              
132             #define INIT_SIZE 32 // initial scalar size to be allocated
133              
134             #define SB do {
135             #define SE } while (0)
136              
137             #define IN_RANGE_INC(type,val,beg,end) \
138             ((unsigned type)((unsigned type)(val) - (unsigned type)(beg)) \
139             <= (unsigned type)((unsigned type)(end) - (unsigned type)(beg)))
140              
141             #define ERR_NESTING_EXCEEDED "cbor text or perl structure exceeds maximum nesting level (max_depth set too low?)"
142              
143             #ifdef USE_ITHREADS
144             # define CBOR_SLOW 1
145             # define CBOR_STASH (cbor_stash ? cbor_stash : gv_stashpv ("CBOR::XS", 1))
146             #else
147             # define CBOR_SLOW 0
148             # define CBOR_STASH cbor_stash
149             #endif
150              
151             static HV *cbor_stash, *types_boolean_stash, *types_error_stash, *cbor_tagged_stash; // CBOR::XS::
152             static SV *types_true, *types_false, *types_error, *sv_cbor, *default_filter;
153              
154             typedef struct {
155             U32 flags;
156             U32 max_depth;
157             STRLEN max_size;
158             SV *filter;
159              
160             // for the incremental parser
161             STRLEN incr_pos; // the current offset into the text
162             STRLEN incr_need; // minimum bytes needed to decode
163             AV *incr_count; // for every nesting level, the number of outstanding values, or -1 for indef.
164             } CBOR;
165              
166             ecb_inline void
167 12865           cbor_init (CBOR *cbor)
168             {
169 12865           Zero (cbor, 1, CBOR);
170 12865           cbor->max_depth = 512;
171 12865           }
172              
173             ecb_inline void
174 9238           cbor_free (CBOR *cbor)
175             {
176 9238           SvREFCNT_dec (cbor->filter);
177 9238           SvREFCNT_dec (cbor->incr_count);
178 9238           }
179              
180             /////////////////////////////////////////////////////////////////////////////
181             // utility functions
182              
183             ecb_inline SV *
184 33           get_bool (const char *name)
185             {
186 33           SV *sv = get_sv (name, 1);
187              
188 33           SvREADONLY_on (sv);
189 33           SvREADONLY_on (SvRV (sv));
190              
191 33           return sv;
192             }
193              
194             ecb_inline void
195 3072           shrink (SV *sv)
196             {
197 3072           sv_utf8_downgrade (sv, 1);
198              
199 3072 100         if (SvLEN (sv) > SvCUR (sv) + 1)
200             {
201             #ifdef SvPV_shrink_to_cur
202 3069           SvPV_shrink_to_cur (sv);
203             #elif defined (SvPV_renew)
204             SvPV_renew (sv, SvCUR (sv) + 1);
205             #endif
206             }
207 3072           }
208              
209             // minimum length of a string to be registered for stringref
210             ecb_inline STRLEN
211 0           minimum_string_length (UV idx)
212             {
213 0 0         return idx <= 23 ? 3
    0          
    0          
    0          
214             : idx <= 0xffU ? 4
215             : idx <= 0xffffU ? 5
216             : idx <= 0xffffffffU ? 7
217             : 11;
218             }
219              
220             /////////////////////////////////////////////////////////////////////////////
221             // encoder
222              
223             // structure used for encoding CBOR
224             typedef struct
225             {
226             char *cur; // SvPVX (sv) + current output position
227             char *end; // SvEND (sv)
228             SV *sv; // result scalar
229             CBOR cbor;
230             U32 depth; // recursion level
231             HV *stringref[2]; // string => index, or 0 ([0] = bytes, [1] = utf-8)
232             UV stringref_idx;
233             HV *shareable; // ptr => index, or 0
234             UV shareable_idx;
235             } enc_t;
236              
237             ecb_inline void
238 19624           need (enc_t *enc, STRLEN len)
239             {
240 19624 100         if (ecb_expect_false ((uintptr_t)(enc->end - enc->cur) < len))
241             {
242 12523           STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
243 12523 50         SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1);
    100          
244 12523           enc->cur = SvPVX (enc->sv) + cur;
245 12523           enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1;
246             }
247 19624           }
248              
249             static void encode_sv (enc_t *enc, SV *sv);
250              
251             ecb_inline void
252 17           encode_ch (enc_t *enc, char ch)
253             {
254 17           need (enc, 1);
255 17           *enc->cur++ = ch;
256 17           }
257              
258             // used for tags, intregers, element counts and so on
259             static void
260 13182           encode_uint (enc_t *enc, int major, UV len)
261             {
262 13182           need (enc, 9);
263              
264 13182 100         if (ecb_expect_true (len < LENGTH_EXT1))
265 7003           *enc->cur++ = major | len;
266 6179 100         else if (ecb_expect_true (len <= 0xffU))
267             {
268 1236           *enc->cur++ = major | LENGTH_EXT1;
269 1236           *enc->cur++ = len;
270             }
271 4943 100         else if (len <= 0xffffU)
272             {
273 4834           *enc->cur++ = major | LENGTH_EXT2;
274 4834           *enc->cur++ = len >> 8;
275 4834           *enc->cur++ = len;
276             }
277 109 50         else if (len <= 0xffffffffU)
278             {
279 109           *enc->cur++ = major | LENGTH_EXT4;
280 109           *enc->cur++ = len >> 24;
281 109           *enc->cur++ = len >> 16;
282 109           *enc->cur++ = len >> 8;
283 109           *enc->cur++ = len;
284             }
285             else
286             {
287 0           *enc->cur++ = major | LENGTH_EXT8;
288 0           *enc->cur++ = len >> 56;
289 0           *enc->cur++ = len >> 48;
290 0           *enc->cur++ = len >> 40;
291 0           *enc->cur++ = len >> 32;
292 0           *enc->cur++ = len >> 24;
293 0           *enc->cur++ = len >> 16;
294 0           *enc->cur++ = len >> 8;
295 0           *enc->cur++ = len;
296             }
297 13182           }
298              
299             // encodes a perl value into a CBOR integer
300             ecb_inline void
301 242           encode_int (enc_t *enc, SV *sv)
302             {
303 242 50         if (SvIsUV (sv))
304 0           encode_uint (enc, MAJOR_POS_INT, SvUVX (sv));
305 242 100         else if (SvIVX (sv) >= 0)
306 182           encode_uint (enc, MAJOR_POS_INT, SvIVX (sv));
307             else
308 60           encode_uint (enc, MAJOR_NEG_INT, -(SvIVX (sv) + 1));
309 242           }
310              
311             ecb_inline void
312 11           encode_tag (enc_t *enc, UV tag)
313             {
314 11           encode_uint (enc, MAJOR_TAG, tag);
315 11           }
316              
317             // exceptional (hopefully) slow path for byte strings that need to be utf8-encoded
318             ecb_noinline static void
319 9           encode_str_utf8 (enc_t *enc, int utf8, char *str, STRLEN len)
320             {
321 9           STRLEN ulen = len;
322 9           U8 *p, *pend = (U8 *)str + len;
323              
324 32 100         for (p = (U8 *)str; p < pend; ++p)
325 23           ulen += *p >> 7; // count set high bits
326              
327 9           encode_uint (enc, MAJOR_TEXT, ulen);
328              
329 9           need (enc, ulen);
330 32 100         for (p = (U8 *)str; p < pend; ++p)
331 23 100         if (*p < 0x80)
332 14           *enc->cur++ = *p;
333             else
334             {
335 9           *enc->cur++ = 0xc0 + (*p >> 6);
336 9           *enc->cur++ = 0x80 + (*p & 63);
337             }
338 9           }
339              
340             ecb_inline void
341 6403           encode_str (enc_t *enc, int upgrade_utf8, int utf8, char *str, STRLEN len)
342             {
343 6403 100         if (ecb_expect_false (upgrade_utf8))
344 9 50         if (!utf8)
345             {
346 9           encode_str_utf8 (enc, utf8, str, len);
347 9           return;
348             }
349              
350 6394 100         encode_uint (enc, utf8 ? MAJOR_TEXT : MAJOR_BYTES, len);
351 6394           need (enc, len);
352 6394           memcpy (enc->cur, str, len);
353 6394           enc->cur += len;
354             }
355              
356             ecb_inline void
357 6403           encode_strref (enc_t *enc, int upgrade_utf8, int utf8, char *str, STRLEN len)
358             {
359 6403 50         if (ecb_expect_false (enc->cbor.flags & F_PACK_STRINGS))
360             {
361 0           SV **svp = hv_fetch (enc->stringref[!!utf8], str, len, 1);
362              
363 0 0         if (SvOK (*svp))
    0          
    0          
364             {
365             // already registered, use stringref
366 0           encode_tag (enc, CBOR_TAG_STRINGREF);
367 0 0         encode_uint (enc, MAJOR_POS_INT, SvUV (*svp));
368 0           return;
369             }
370 0 0         else if (len >= minimum_string_length (enc->stringref_idx))
371             {
372             // register only
373 0           sv_setuv (*svp, enc->stringref_idx);
374 0           ++enc->stringref_idx;
375             }
376             }
377              
378 6403           encode_str (enc, upgrade_utf8, utf8, str, len);
379             }
380              
381             ecb_inline void
382 0           encode_float16 (enc_t *enc, NV nv)
383             {
384 0           need (enc, 1+2);
385              
386 0           *enc->cur++ = MAJOR_MISC | MISC_FLOAT16;
387              
388 0           uint16_t fp = ecb_float_to_binary16 (nv);
389              
390 0 0         if (!ecb_big_endian ())
391 0           fp = ecb_bswap16 (fp);
392              
393 0           memcpy (enc->cur, &fp, 2);
394 0           enc->cur += 2;
395 0           }
396              
397             ecb_inline void
398 3           encode_float32 (enc_t *enc, NV nv)
399             {
400 3           need (enc, 1+4);
401              
402 3           *enc->cur++ = MAJOR_MISC | MISC_FLOAT32;
403              
404 3           uint32_t fp = ecb_float_to_binary32 (nv);
405              
406 3 50         if (!ecb_big_endian ())
407 3           fp = ecb_bswap32 (fp);
408              
409 3           memcpy (enc->cur, &fp, 4);
410 3           enc->cur += 4;
411 3           }
412              
413             ecb_inline void
414 8           encode_float64 (enc_t *enc, NV nv)
415             {
416 8           need (enc, 1+8);
417              
418 8           *enc->cur++ = MAJOR_MISC | MISC_FLOAT64;
419              
420 8           uint64_t fp = ecb_double_to_binary64 (nv);
421              
422 8 50         if (!ecb_big_endian ())
423 8           fp = ecb_bswap64 (fp);
424              
425 8           memcpy (enc->cur, &fp, 8);
426 8           enc->cur += 8;
427 8           }
428              
429             ecb_inline void
430 6           encode_bool (enc_t *enc, int istrue)
431             {
432 6 100         encode_ch (enc, istrue ? MAJOR_MISC | SIMPLE_TRUE : MAJOR_MISC | SIMPLE_FALSE);
433 6           }
434              
435             // encodes an arrayref containing key-value pairs as CBOR map
436             ecb_inline void
437 0           encode_array_as_map (enc_t *enc, SV *sv)
438             {
439 0 0         if (enc->depth >= enc->cbor.max_depth)
440 0           croak (ERR_NESTING_EXCEEDED);
441              
442 0           ++enc->depth;
443              
444             // as_map does error checking for us, but we re-check in case
445             // things have changed.
446              
447 0 0         if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
    0          
448 0           croak ("CBOR::XS::as_map requires an array reference (did you change the array after calling as_map?)");
449              
450 0           AV *av = (AV *)SvRV (sv);
451 0           int i, len = av_len (av);
452              
453 0 0         if (!(len & 1))
454 0           croak ("CBOR::XS::as_map requires an even number of elements (did you change the array after calling as_map?)");
455              
456 0           encode_uint (enc, MAJOR_MAP, (len + 1) >> 1);
457              
458 0 0         for (i = 0; i <= len; ++i)
459             {
460 0           SV **svp = av_fetch (av, i, 0);
461 0 0         encode_sv (enc, svp ? *svp : &PL_sv_undef);
462             }
463              
464 0           --enc->depth;
465 0           }
466              
467             ecb_inline void
468 0           encode_forced (enc_t *enc, UV type, SV *sv)
469             {
470 0           switch (type)
471             {
472             case AS_CBOR:
473             {
474             STRLEN len;
475 0 0         char *str = SvPVbyte (sv, len);
476              
477 0           need (enc, len);
478 0           memcpy (enc->cur, str, len);
479 0           enc->cur += len;
480             }
481 0           break;
482              
483             case AS_BYTES:
484             {
485             STRLEN len;
486 0 0         char *str = SvPVbyte (sv, len);
487 0           encode_strref (enc, 0, 0, str, len);
488             }
489 0           break;
490              
491             case AS_TEXT:
492             {
493             STRLEN len;
494 0 0         char *str = SvPVutf8 (sv, len);
495 0           encode_strref (enc, 1, 1, str, len);
496             }
497 0           break;
498              
499 0           case AS_INT: encode_int (enc, sv); break;
500              
501 0 0         case AS_FLOAT16: encode_float16 (enc, SvNV (sv)); break;
502 0 0         case AS_FLOAT32: encode_float32 (enc, SvNV (sv)); break;
503 0 0         case AS_FLOAT64: encode_float64 (enc, SvNV (sv)); break;
504              
505 0           case AS_MAP: encode_array_as_map (enc, sv); break;
506              
507             default:
508 0           croak ("encountered malformed CBOR::XS::Tagged object");
509             }
510 0           }
511              
512             static void
513 6291           encode_av (enc_t *enc, AV *av)
514             {
515 6291           int i, len = av_len (av);
516              
517 6291 50         if (enc->depth >= enc->cbor.max_depth)
518 0           croak (ERR_NESTING_EXCEEDED);
519              
520 6291           ++enc->depth;
521              
522 6291           encode_uint (enc, MAJOR_ARRAY, len + 1);
523              
524 6291 50         if (ecb_expect_false (SvMAGICAL (av)))
525 0 0         for (i = 0; i <= len; ++i)
526             {
527 0           SV **svp = av_fetch (av, i, 0);
528 0 0         encode_sv (enc, svp ? *svp : &PL_sv_undef);
529             }
530             else
531 12706 100         for (i = 0; i <= len; ++i)
532             {
533 6415           SV *sv = AvARRAY (av)[i];
534 6415 50         encode_sv (enc, sv ? sv : &PL_sv_undef);
535             }
536              
537 6291           --enc->depth;
538 6291           }
539              
540             static void
541 16           encode_hv (enc_t *enc, HV *hv)
542             {
543             HE *he;
544              
545 16 50         if (enc->depth >= enc->cbor.max_depth)
546 0           croak (ERR_NESTING_EXCEEDED);
547              
548 16           ++enc->depth;
549              
550 16           int pairs = hv_iterinit (hv);
551 16           int mg = SvMAGICAL (hv);
552              
553 16 50         if (ecb_expect_false (mg))
554 0           encode_ch (enc, MAJOR_MAP | MINOR_INDEF);
555             else
556 16           encode_uint (enc, MAJOR_MAP, pairs);
557              
558 31 100         while ((he = hv_iternext (hv)))
559             {
560 15 50         if (HeKLEN (he) == HEf_SVKEY)
561 0 0         encode_sv (enc, HeSVKEY (he));
    0          
562             else
563 15           encode_strref (enc, enc->cbor.flags & (F_TEXT_KEYS | F_TEXT_STRINGS), HeKUTF8 (he), HeKEY (he), HeKLEN (he));
564              
565 15 50         encode_sv (enc, ecb_expect_false (mg) ? hv_iterval (hv, he) : HeVAL (he));
566             }
567              
568 16 50         if (ecb_expect_false (mg))
569 0           encode_ch (enc, MAJOR_MISC | MINOR_INDEF);
570              
571 16           --enc->depth;
572 16           }
573              
574             // encode objects, arrays and special \0=false and \1=true values.
575             static void
576 6746           encode_rv (enc_t *enc, SV *sv)
577             {
578 6746 50         SvGETMAGIC (sv);
    0          
579              
580 6746           svtype svt = SvTYPE (sv);
581              
582 6746 100         if (ecb_expect_false (SvOBJECT (sv)))
583             {
584 437           HV *boolean_stash = !CBOR_SLOW || types_boolean_stash
585             ? types_boolean_stash
586             : gv_stashpv ("Types::Serialiser::Boolean", 1);
587 437           HV *error_stash = !CBOR_SLOW || types_error_stash
588             ? types_error_stash
589             : gv_stashpv ("Types::Serialiser::Error", 1);
590 437           HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
591             ? cbor_tagged_stash
592             : gv_stashpv ("CBOR::XS::Tagged" , 1);
593              
594 437           HV *stash = SvSTASH (sv);
595              
596 437 100         if (stash == boolean_stash)
597             {
598 6 50         encode_bool (enc, SvIV (sv));
599 6           return;
600             }
601 431 100         else if (stash == error_stash)
602             {
603 3           encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
604 3           return;
605             }
606 428 100         else if (stash == tagged_stash)
607             {
608 212 50         if (svt != SVt_PVAV)
609 0           croak ("encountered CBOR::XS::Tagged object that isn't an array");
610              
611 212           switch (av_len ((AV *)sv))
612             {
613             case 2-1:
614             // actually a tagged value
615 212 50         encode_uint (enc, MAJOR_TAG, SvUV (*av_fetch ((AV *)sv, 0, 1)));
616 212           encode_sv (enc, *av_fetch ((AV *)sv, 1, 1));
617 212           break;
618              
619             case 3-1:
620             // a forced type [value, type, undef]
621 0 0         encode_forced (enc, SvUV (*av_fetch ((AV *)sv, 1, 1)), *av_fetch ((AV *)sv, 0, 1));
622 0           break;
623              
624             default:
625 0           croak ("encountered malformed CBOR::XS::Tagged object");
626             }
627              
628 212           return;
629             }
630             }
631              
632 6525 100         if (ecb_expect_false (SvREFCNT (sv) > 1)
633 113 100         && ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING))
634             {
635 6 100         if (ecb_expect_false (!enc->shareable))
636 2           enc->shareable = (HV *)sv_2mortal ((SV *)newHV ());
637              
638 6           SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1);
639              
640 6 100         if (SvOK (*svp))
    50          
    50          
641             {
642 4           encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF);
643 4 50         encode_uint (enc, MAJOR_POS_INT, SvUV (*svp));
644 4           return;
645             }
646             else
647             {
648 2           sv_setuv (*svp, enc->shareable_idx);
649 2           ++enc->shareable_idx;
650 2           encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE);
651             }
652             }
653              
654 6521 100         if (ecb_expect_false (SvOBJECT (sv)))
655             {
656 212           HV *stash = SvSTASH (sv);
657             GV *method;
658              
659 212 50         if (enc->cbor.flags & F_FORBID_OBJECTS)
660 0 0         croak ("encountered object '%s', but forbid_objects is enabled",
661 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
662 212 100         else if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0)))
663             {
664 209           dSP;
665              
666 209           ENTER; SAVETMPS;
667 209 50         PUSHMARK (SP);
668             // we re-bless the reference to get overload and other niceties right
669 209 50         XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
670              
671 209           PUTBACK;
672             // G_SCALAR ensures that return value is 1
673 209           call_sv ((SV *)GvCV (method), G_SCALAR);
674 209           SPAGAIN;
675              
676             // catch this surprisingly common error
677 209 100         if (SvROK (TOPs) && SvRV (TOPs) == sv)
    50          
678 0 0         croak ("%s::TO_CBOR method returned same object as was passed instead of a new one", HvNAME (stash));
    0          
    0          
    0          
    0          
    0          
679              
680 209           encode_sv (enc, POPs);
681              
682 209           PUTBACK;
683              
684 209 50         FREETMPS; LEAVE;
685             }
686 3 50         else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0)
687             {
688 3           dSP;
689              
690 3           ENTER; SAVETMPS;
691 3 50         PUSHMARK (SP);
692 3 50         EXTEND (SP, 2);
693             // we re-bless the reference to get overload and other niceties right
694 3           PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
695 3           PUSHs (sv_cbor);
696              
697 3           PUTBACK;
698 3           int count = call_sv ((SV *)GvCV (method), G_ARRAY);
699 3           SPAGAIN;
700              
701             // catch this surprisingly common error
702 3 100         if (count == 1 && SvROK (TOPs) && SvRV (TOPs) == sv)
    50          
    0          
703 0 0         croak ("%s::FREEZE(CBOR) method returned same object as was passed instead of a new one", HvNAME (stash));
    0          
    0          
    0          
    0          
    0          
704              
705 3           encode_tag (enc, CBOR_TAG_PERL_OBJECT);
706 3           encode_uint (enc, MAJOR_ARRAY, count + 1);
707 3 50         encode_strref (enc, 0, HvNAMEUTF8 (stash), HvNAME (stash), HvNAMELEN (stash));
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
708              
709             {
710             int i;
711              
712 8 100         for (i = 0; i < count; ++i)
713 5           encode_sv (enc, SP[i + 1 - count]);
714              
715 3           SP -= count;
716             }
717              
718 3           PUTBACK;
719              
720 3 50         FREETMPS; LEAVE;
721             }
722             else
723 212 0         croak ("encountered object '%s', but no TO_CBOR or FREEZE methods available on it",
724 0           SvPV_nolen (sv_2mortal (newRV_inc (sv))));
725             }
726 6309 100         else if (svt == SVt_PVHV)
727 16           encode_hv (enc, (HV *)sv);
728 6293 100         else if (svt == SVt_PVAV)
729 6291           encode_av (enc, (AV *)sv);
730             else
731             {
732 2           encode_tag (enc, CBOR_TAG_INDIRECTION);
733 2           encode_sv (enc, sv);
734             }
735             }
736              
737             static void
738 11           encode_nv (enc_t *enc, SV *sv)
739             {
740 11           double nv = SvNVX (sv);
741              
742 11           need (enc, 9);
743              
744 11 50         if (ecb_expect_false (nv == (NV)(U32)nv))
745 0           encode_uint (enc, MAJOR_POS_INT, (U32)nv);
746             //TODO: maybe I32?
747 11 100         else if (ecb_expect_false (nv == (float)nv))
748 3           encode_float32 (enc, nv);
749             else
750 8           encode_float64 (enc, nv);
751 11           }
752              
753             static void
754 13392           encode_sv (enc_t *enc, SV *sv)
755             {
756 13392 50         SvGETMAGIC (sv);
    0          
757              
758 13392 100         if (SvPOKp (sv))
759             {
760             STRLEN len;
761 6385 50         char *str = SvPV (sv, len);
762 6385           encode_strref (enc, enc->cbor.flags & F_TEXT_STRINGS, SvUTF8 (sv), str, len);
763             }
764 7007 100         else if (SvNOKp (sv))
765 11           encode_nv (enc, sv);
766 6996 100         else if (SvIOKp (sv))
767 242           encode_int (enc, sv);
768 6754 100         else if (SvROK (sv))
769 6746           encode_rv (enc, SvRV (sv));
770 8 50         else if (!SvOK (sv))
    50          
    50          
771 8           encode_ch (enc, MAJOR_MISC | SIMPLE_NULL);
772 0 0         else if (enc->cbor.flags & F_ALLOW_UNKNOWN)
773 0           encode_ch (enc, MAJOR_MISC | SIMPLE_UNDEF);
774             else
775 0 0         croak ("encountered perl type (%s,0x%x) that CBOR cannot handle, check your input data",
776 0           SvPV_nolen (sv), (unsigned int)SvFLAGS (sv));
777 13392           }
778              
779             static SV *
780 6534           encode_cbor (SV *scalar, CBOR *cbor)
781             {
782 6534           enc_t enc = { 0 };
783              
784 6534           enc.cbor = *cbor;
785 6534           enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
786 6534           enc.cur = SvPVX (enc.sv);
787 6534           enc.end = SvEND (enc.sv);
788              
789 6534           SvPOK_only (enc.sv);
790              
791 6534 50         if (cbor->flags & F_PACK_STRINGS)
792             {
793 0           encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE);
794 0           enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ());
795 0           enc.stringref[1]= (HV *)sv_2mortal ((SV *)newHV ());
796             }
797              
798 6534           encode_sv (&enc, scalar);
799              
800 6534           SvCUR_set (enc.sv, enc.cur - SvPVX (enc.sv));
801 6534           *SvEND (enc.sv) = 0; // many xs functions expect a trailing 0 for text strings
802              
803 6534 100         if (enc.cbor.flags & F_SHRINK)
804 3072           shrink (enc.sv);
805              
806 6534           return enc.sv;
807             }
808              
809             /////////////////////////////////////////////////////////////////////////////
810             // decoder
811              
812             // structure used for decoding CBOR
813             typedef struct
814             {
815             U8 *cur; // current parser pointer
816             U8 *end; // end of input string
817             const char *err; // parse error, if != 0
818             CBOR cbor;
819             U32 depth; // recursion depth
820             U32 maxdepth; // recursion depth limit
821             AV *shareable;
822             AV *stringref;
823             SV *decode_tagged;
824             SV *err_sv; // optional sv for error, needs to be freed
825             } dec_t;
826              
827             // set dec->err to ERRSV
828             ecb_cold static void
829 0           err_errsv (dec_t *dec)
830             {
831 0 0         if (!dec->err)
832             {
833 0 0         dec->err_sv = newSVsv (ERRSV);
834              
835             // chop off the trailing \n
836 0           SvCUR_set (dec->err_sv, SvCUR (dec->err_sv) - 1);
837 0           *SvEND (dec->err_sv) = 0;
838              
839 0 0         dec->err = SvPVutf8_nolen (dec->err_sv);
840             }
841 0           }
842              
843             // the following functions are used to reduce code size and help the compiler to optimise
844             ecb_cold static void
845 5           err_set (dec_t *dec, const char *reason)
846             {
847 5 50         if (!dec->err)
848 5           dec->err = reason;
849 5           }
850              
851             ecb_cold static void
852 0           err_unexpected_end (dec_t *dec)
853             {
854 0           err_set (dec, "unexpected end of CBOR data");
855 0           }
856              
857             #define ERR_DO(do) SB do; goto fail; SE
858             #define ERR(reason) ERR_DO (err_set (dec, reason))
859             #define ERR_ERRSV ERR_DO (err_errsv (dec))
860              
861             #define WANT(len) if (ecb_expect_false ((uintptr_t)(dec->end - dec->cur) < (STRLEN)len)) ERR_DO (err_unexpected_end (dec))
862              
863             #define DEC_INC_DEPTH if (ecb_expect_false (++dec->depth > dec->cbor.max_depth)) ERR (ERR_NESTING_EXCEEDED)
864             #define DEC_DEC_DEPTH --dec->depth
865              
866             static UV
867 13254           decode_uint (dec_t *dec)
868             {
869 13254           U8 m = *dec->cur & MINOR_MASK;
870 13254           ++dec->cur;
871              
872 13254 100         if (ecb_expect_true (m < LENGTH_EXT1))
873 6964           return m;
874 6290 100         else if (ecb_expect_true (m == LENGTH_EXT1))
875             {
876 1275 50         WANT (1);
877 1275           dec->cur += 1;
878 1275           return dec->cur[-1];
879             }
880 5015 100         else if (ecb_expect_true (m == LENGTH_EXT2))
881             {
882 4856 50         WANT (2);
883 4856           dec->cur += 2;
884 4856           return (((UV)dec->cur[-2]) << 8)
885 4856           | ((UV)dec->cur[-1]);
886             }
887 159 100         else if (ecb_expect_true (m == LENGTH_EXT4))
888             {
889 134 50         WANT (4);
890 134           dec->cur += 4;
891 134           return (((UV)dec->cur[-4]) << 24)
892 134           | (((UV)dec->cur[-3]) << 16)
893 134           | (((UV)dec->cur[-2]) << 8)
894 134           | ((UV)dec->cur[-1]);
895             }
896 25 50         else if (ecb_expect_true (m == LENGTH_EXT8))
897             {
898 25 50         WANT (8);
899 25           dec->cur += 8;
900              
901             return
902             #if UVSIZE < 8
903             0
904             #else
905 25           (((UV)dec->cur[-8]) << 56)
906 25           | (((UV)dec->cur[-7]) << 48)
907 25           | (((UV)dec->cur[-6]) << 40)
908 25           | (((UV)dec->cur[-5]) << 32)
909             #endif
910 25           | (((UV)dec->cur[-4]) << 24)
911 25           | (((UV)dec->cur[-3]) << 16)
912 25           | (((UV)dec->cur[-2]) << 8)
913 25           | ((UV)dec->cur[-1]);
914             }
915             else
916 0           ERR ("corrupted CBOR data (unsupported integer minor encoding)");
917              
918             fail:
919 0           return 0;
920             }
921              
922             static SV *decode_sv (dec_t *dec);
923              
924             static SV *
925 6312           decode_av (dec_t *dec)
926             {
927 6312           AV *av = newAV ();
928              
929 6312 50         DEC_INC_DEPTH;
930              
931 6312 100         if (*dec->cur == (MAJOR_ARRAY | MINOR_INDEF))
932             {
933 8           ++dec->cur;
934              
935             for (;;)
936             {
937 47 50         WANT (1);
938              
939 47 100         if (*dec->cur == (MAJOR_MISC | MINOR_INDEF) || dec->err)
    50          
940             {
941 8           ++dec->cur;
942 8           break;
943             }
944              
945 39           av_push (av, decode_sv (dec));
946 47           }
947             }
948             else
949             {
950 6304           UV i, len = decode_uint (dec);
951              
952 6304 50         WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays
953 6304           av_fill (av, len - 1);
954              
955 12745 100         for (i = 0; i < len; ++i)
956 6441           AvARRAY (av)[i] = decode_sv (dec);
957             }
958              
959 6312           DEC_DEC_DEPTH;
960 6312           return newRV_noinc ((SV *)av);
961              
962             fail:
963 0           SvREFCNT_dec_NN (av);
964 0           DEC_DEC_DEPTH;
965 0           return &PL_sv_undef;
966             }
967              
968             static void
969 17           decode_he (dec_t *dec, HV *hv)
970             {
971             // for speed reasons, we specialcase single-string
972             // byte or utf-8 strings as keys, but only when !stringref
973              
974 17 50         if (ecb_expect_true (!dec->stringref))
975 17 100         if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
976             {
977 1           STRLEN len = decode_uint (dec);
978 1           char *key = (char *)dec->cur;
979              
980 1 50         WANT (len);
981 1           dec->cur += len;
982              
983 1           hv_store (hv, key, len, decode_sv (dec), 0);
984              
985 1           return;
986             }
987 16 50         else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
988             {
989 16           STRLEN len = decode_uint (dec);
990 16           char *key = (char *)dec->cur;
991              
992 16 50         WANT (len);
993 16           dec->cur += len;
994              
995 16 100         if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
996 1 50         if (!cbor_is_utf8_string ((U8 *)key, len))
    50          
997 1           ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
998              
999 15           hv_store (hv, key, -len, decode_sv (dec), 0);
1000              
1001 15           return;
1002             }
1003              
1004 0           SV *k = decode_sv (dec);
1005 0           SV *v = decode_sv (dec);
1006              
1007             // we leak memory if uncaught exceptions are thrown by random magical
1008             // methods, and this is hopefully the only place where it can happen,
1009             // so if there is a chance of an exception, take the very slow path.
1010             // since catching exceptions is "undocumented/internal/forbidden" by
1011             // the new p5p powers, we need to call out to a perl function :/
1012 0 0         if (ecb_expect_false (SvAMAGIC (k)))
    0          
    0          
    0          
1013             {
1014 0           dSP;
1015              
1016 0           ENTER; SAVETMPS;
1017 0 0         PUSHMARK (SP);
1018 0 0         EXTEND (SP, 3);
1019 0           PUSHs (sv_2mortal (newRV_inc ((SV *)hv)));
1020 0           PUSHs (sv_2mortal (k));
1021 0           PUSHs (sv_2mortal (v));
1022              
1023 0           PUTBACK;
1024 0           call_pv ("CBOR::XS::_hv_store", G_VOID | G_DISCARD | G_EVAL);
1025 0           SPAGAIN;
1026              
1027 0 0         FREETMPS; LEAVE;
1028              
1029 0 0         if (SvTRUE (ERRSV))
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1030 0           ERR_ERRSV;
1031              
1032 0           return;
1033             }
1034              
1035 0           hv_store_ent (hv, k, v, 0);
1036 0           SvREFCNT_dec_NN (k);
1037              
1038             fail:
1039             ;
1040             }
1041              
1042             static SV *
1043 12           decode_hv (dec_t *dec)
1044             {
1045 12           HV *hv = newHV ();
1046              
1047 12 50         DEC_INC_DEPTH;
1048              
1049 12 100         if (*dec->cur == (MAJOR_MAP | MINOR_INDEF))
1050             {
1051 2           ++dec->cur;
1052              
1053             for (;;)
1054             {
1055 5 50         WANT (1);
1056              
1057 5 100         if (*dec->cur == (MAJOR_MISC | MINOR_INDEF) || dec->err)
    50          
1058             {
1059 2           ++dec->cur;
1060 2           break;
1061             }
1062              
1063 3           decode_he (dec, hv);
1064 5           }
1065             }
1066             else
1067             {
1068 10           UV pairs = decode_uint (dec);
1069              
1070 10 50         WANT (pairs); // complexity check - need at least one byte per value, do not allow supersize hashes
1071              
1072 24 100         while (pairs--)
1073 14           decode_he (dec, hv);
1074             }
1075              
1076 12           DEC_DEC_DEPTH;
1077 12           return newRV_noinc ((SV *)hv);
1078              
1079             fail:
1080 0           SvREFCNT_dec_NN (hv);
1081 0           DEC_DEC_DEPTH;
1082 0           return &PL_sv_undef;
1083             }
1084              
1085             static SV *
1086 6391           decode_str (dec_t *dec, int utf8)
1087             {
1088 6391           SV *sv = 0;
1089              
1090 6391 100         if (ecb_expect_false ((*dec->cur & MINOR_MASK) == MINOR_INDEF))
1091             {
1092             // indefinite length strings
1093 10           ++dec->cur;
1094              
1095 10           U8 major = *dec->cur & MAJOR_MISC;
1096              
1097 10           sv = newSVpvn ("", 0);
1098              
1099             for (;;)
1100             {
1101 39 50         WANT (1);
1102              
1103 39 100         if ((*dec->cur - major) > LENGTH_EXT8)
1104 10 50         if (*dec->cur == (MAJOR_MISC | MINOR_INDEF))
1105             {
1106 10           ++dec->cur;
1107 10           break;
1108             }
1109             else
1110 0           ERR ("corrupted CBOR data (invalid chunks in indefinite length string)");
1111              
1112 29           STRLEN len = decode_uint (dec);
1113              
1114 29 50         WANT (len);
1115 29           sv_catpvn (sv, dec->cur, len);
1116 29           dec->cur += len;
1117 39           }
1118             }
1119             else
1120             {
1121 6381           STRLEN len = decode_uint (dec);
1122              
1123 6381 50         WANT (len);
1124 6381           sv = newSVpvn (dec->cur, len);
1125 6381           dec->cur += len;
1126              
1127 6381 50         if (ecb_expect_false (dec->stringref)
1128 0 0         && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
1129 0           av_push (dec->stringref, SvREFCNT_inc_NN (sv));
1130             }
1131              
1132 6391 100         if (utf8)
1133             {
1134 3090 100         if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
1135 2 50         if (!cbor_is_utf8_string (SvPVX (sv), SvCUR (sv)))
    50          
1136 2           ERR ("corrupted CBOR data (invalid UTF-8 in text string)");
1137              
1138 3088           SvUTF8_on (sv);
1139             }
1140              
1141 6389           return sv;
1142              
1143             fail:
1144 2           SvREFCNT_dec (sv);
1145 2           return &PL_sv_undef;
1146             }
1147              
1148             static SV *
1149 220           decode_tagged (dec_t *dec)
1150             {
1151 220           SV *sv = 0;
1152 220           UV tag = decode_uint (dec);
1153              
1154 220 50         WANT (1);
1155              
1156 220           switch (tag)
1157             {
1158             case CBOR_TAG_MAGIC:
1159 0           sv = decode_sv (dec);
1160 0           break;
1161              
1162             case CBOR_TAG_INDIRECTION:
1163 0           sv = newRV_noinc (decode_sv (dec));
1164 0           break;
1165              
1166             case CBOR_TAG_STRINGREF_NAMESPACE:
1167             {
1168             // do not use SAVETMPS/FREETMPS, as these will
1169             // erase mortalised caches, e.g. "shareable"
1170 0           ENTER;
1171              
1172 0           SAVESPTR (dec->stringref);
1173 0           dec->stringref = (AV *)sv_2mortal ((SV *)newAV ());
1174              
1175 0           sv = decode_sv (dec);
1176              
1177 0           LEAVE;
1178             }
1179 0           break;
1180              
1181             case CBOR_TAG_STRINGREF:
1182             {
1183 0 0         if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
1184 0           ERR ("corrupted CBOR data (stringref index not an unsigned integer)");
1185              
1186 0           UV idx = decode_uint (dec);
1187              
1188 0 0         if (!dec->stringref || idx >= (UV)(1 + AvFILLp (dec->stringref)))
    0          
1189 0           ERR ("corrupted CBOR data (stringref index out of bounds or outside namespace)");
1190              
1191 0           sv = newSVsv (AvARRAY (dec->stringref)[idx]);
1192             }
1193 0           break;
1194              
1195             case CBOR_TAG_VALUE_SHAREABLE:
1196             {
1197 4 50         if (ecb_expect_false (!dec->shareable))
1198 4           dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
1199              
1200 4 100         if (ecb_expect_false (dec->cbor.flags & (F_ALLOW_CYCLES | F_ALLOW_WEAK_CYCLES)))
1201             {
1202             // if cycles are allowed, then we store an AV as value
1203             // while it is being decoded, and gather unresolved
1204             // references in it, to be re4solved after decoding.
1205             int idx, i;
1206 2           AV *av = newAV ();
1207 2           av_push (dec->shareable, (SV *)av);
1208 2           idx = AvFILLp (dec->shareable);
1209              
1210 2           sv = decode_sv (dec);
1211              
1212             // the AV now contains \undef for all unresolved references,
1213             // so we fix them up here.
1214 4 100         for (i = 0; i <= AvFILLp (av); ++i)
1215 2           SvRV_set (AvARRAY (av)[i], SvREFCNT_inc_NN (SvRV (sv)));
1216              
1217             // weaken all recursive references
1218 2 100         if (dec->cbor.flags & F_ALLOW_WEAK_CYCLES)
1219 2 100         for (i = 0; i <= AvFILLp (av); ++i)
1220 1           sv_rvweaken (AvARRAY (av)[i]);
1221              
1222             // now replace the AV by a reference to the completed value
1223 2           SvREFCNT_dec_NN ((SV *)av);
1224 2           AvARRAY (dec->shareable)[idx] = SvREFCNT_inc_NN (sv);
1225             }
1226             else
1227             {
1228 2           av_push (dec->shareable, &PL_sv_undef);
1229 2           int idx = AvFILLp (dec->shareable);
1230 2           sv = decode_sv (dec);
1231 2           AvARRAY (dec->shareable)[idx] = SvREFCNT_inc_NN (sv);
1232             }
1233             }
1234 4           break;
1235              
1236             case CBOR_TAG_VALUE_SHAREDREF:
1237             {
1238 6 50         if ((*dec->cur >> MAJOR_SHIFT) != (MAJOR_POS_INT >> MAJOR_SHIFT))
1239 0           ERR ("corrupted CBOR data (sharedref index not an unsigned integer)");
1240              
1241 6           UV idx = decode_uint (dec);
1242              
1243 6 50         if (!dec->shareable || idx >= (UV)(1 + AvFILLp (dec->shareable)))
    50          
1244 0           ERR ("corrupted CBOR data (sharedref index out of bounds)");
1245              
1246 6           sv = AvARRAY (dec->shareable)[idx];
1247              
1248             // reference to cycle, we create a new \undef and use that, and also
1249             // registerr it in the AV for later fixing
1250 6 100         if (ecb_expect_false (SvTYPE (sv) == SVt_PVAV))
1251             {
1252 2           AV *av = (AV *)sv;
1253 2           sv = newRV_noinc (&PL_sv_undef);
1254 2           av_push (av, SvREFCNT_inc_NN (sv));
1255             }
1256 4 100         else if (ecb_expect_false (sv == &PL_sv_undef)) // not yet decoded, but cycles not allowed
1257 1           ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled");
1258             else // we decoded the object earlier, no cycle
1259 3           sv = newSVsv (sv);
1260             }
1261 5           break;
1262              
1263             case CBOR_TAG_PERL_OBJECT:
1264             {
1265 2 50         if (dec->cbor.flags & F_FORBID_OBJECTS)
1266 0           goto filter;
1267              
1268 2           sv = decode_sv (dec);
1269              
1270 2 50         if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
    50          
1271 0           ERR ("corrupted CBOR data (non-array perl object)");
1272              
1273 2           AV *av = (AV *)SvRV (sv);
1274 2           int len = av_len (av) + 1;
1275 2           HV *stash = gv_stashsv (*av_fetch (av, 0, 1), 0);
1276              
1277 2 50         if (!stash)
1278 0           ERR ("cannot decode perl-object (package does not exist)");
1279              
1280 2           GV *method = gv_fetchmethod_autoload (stash, "THAW", 0);
1281            
1282 2 50         if (!method)
1283 0           ERR ("cannot decode perl-object (package does not have a THAW method)");
1284            
1285 2           dSP;
1286              
1287 2           ENTER; SAVETMPS;
1288 2 50         PUSHMARK (SP);
1289 2 50         EXTEND (SP, len + 1);
    50          
1290             // we re-bless the reference to get overload and other niceties right
1291 2           PUSHs (*av_fetch (av, 0, 1));
1292 2           PUSHs (sv_cbor);
1293              
1294             int i;
1295              
1296 6 100         for (i = 1; i < len; ++i)
1297 4           PUSHs (*av_fetch (av, i, 1));
1298              
1299 2           PUTBACK;
1300 2           call_sv ((SV *)GvCV (method), G_SCALAR | G_EVAL);
1301 2           SPAGAIN;
1302              
1303 2 50         if (SvTRUE (ERRSV))
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
1304             {
1305 0 0         FREETMPS; LEAVE;
1306 0           ERR_ERRSV;
1307             }
1308              
1309 2           SvREFCNT_dec_NN (sv);
1310 2           sv = SvREFCNT_inc (POPs);
1311              
1312 2           PUTBACK;
1313              
1314 2 50         FREETMPS; LEAVE;
1315             }
1316 2           break;
1317              
1318             default:
1319             filter:
1320             {
1321 208           SV *tag_sv = newSVuv (tag);
1322              
1323 208           sv = decode_sv (dec);
1324              
1325 208           dSP;
1326 208           ENTER; SAVETMPS;
1327 208 50         PUSHMARK (SP);
1328 208 50         EXTEND (SP, 2);
1329 208           PUSHs (tag_sv);
1330 208           PUSHs (sv);
1331              
1332 208           PUTBACK;
1333 208 50         int count = call_sv (dec->cbor.filter ? dec->cbor.filter : default_filter, G_ARRAY | G_EVAL);
1334 208           SPAGAIN;
1335              
1336 208 50         if (SvTRUE (ERRSV))
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
1337             {
1338 0           SvREFCNT_dec_NN (tag_sv);
1339 0 0         FREETMPS; LEAVE;
1340 0           ERR_ERRSV;
1341             }
1342              
1343 208 100         if (count)
1344             {
1345 207           SvREFCNT_dec_NN (tag_sv);
1346 207           SvREFCNT_dec_NN (sv);
1347 207           sv = SvREFCNT_inc_NN (TOPs);
1348 207           SP -= count;
1349             }
1350             else
1351             {
1352 1           AV *av = newAV ();
1353 1           av_push (av, tag_sv);
1354 1           av_push (av, sv);
1355              
1356 1           HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
1357             ? cbor_tagged_stash
1358             : gv_stashpv ("CBOR::XS::Tagged" , 1);
1359 1           sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash);
1360             }
1361              
1362 208           PUTBACK;
1363              
1364 208 100         FREETMPS; LEAVE;
1365             }
1366 208           break;
1367             }
1368              
1369 219           return sv;
1370              
1371             fail:
1372 1           SvREFCNT_dec (sv);
1373 1           return &PL_sv_undef;
1374             }
1375              
1376             static SV *
1377 13257           decode_sv (dec_t *dec)
1378             {
1379 13257 50         WANT (1);
1380              
1381 13257           switch (*dec->cur >> MAJOR_SHIFT)
1382             {
1383 227           case MAJOR_POS_INT >> MAJOR_SHIFT: return newSVuv (decode_uint (dec));
1384 60           case MAJOR_NEG_INT >> MAJOR_SHIFT: return newSViv (-1 - (IV)decode_uint (dec));
1385 3301           case MAJOR_BYTES >> MAJOR_SHIFT: return decode_str (dec, 0);
1386 3090           case MAJOR_TEXT >> MAJOR_SHIFT: return decode_str (dec, 1);
1387 6312           case MAJOR_ARRAY >> MAJOR_SHIFT: return decode_av (dec);
1388 12           case MAJOR_MAP >> MAJOR_SHIFT: return decode_hv (dec);
1389 220           case MAJOR_TAG >> MAJOR_SHIFT: return decode_tagged (dec);
1390              
1391             case MAJOR_MISC >> MAJOR_SHIFT:
1392 35           switch (*dec->cur++ & MINOR_MASK)
1393             {
1394             case SIMPLE_FALSE:
1395             #if CBOR_SLOW
1396             types_false = get_bool ("Types::Serialiser::false");
1397             #endif
1398 3           return newSVsv (types_false);
1399             case SIMPLE_TRUE:
1400             #if CBOR_SLOW
1401             types_true = get_bool ("Types::Serialiser::true");
1402             #endif
1403 3           return newSVsv (types_true);
1404             case SIMPLE_NULL:
1405 8           return newSVsv (&PL_sv_undef);
1406             case SIMPLE_UNDEF:
1407             #if CBOR_SLOW
1408             types_error = get_bool ("Types::Serialiser::error");
1409             #endif
1410 3           return newSVsv (types_error);
1411              
1412             case MISC_FLOAT16:
1413             {
1414 5 50         WANT (2);
1415              
1416 5           uint16_t fp = (dec->cur[0] << 8) | dec->cur[1];
1417 5           dec->cur += 2;
1418              
1419 5           return newSVnv (ecb_binary16_to_float (fp));
1420             }
1421              
1422             case MISC_FLOAT32:
1423             {
1424             uint32_t fp;
1425 4 50         WANT (4);
1426 4           memcpy (&fp, dec->cur, 4);
1427 4           dec->cur += 4;
1428              
1429 4 50         if (!ecb_big_endian ())
1430 4           fp = ecb_bswap32 (fp);
1431              
1432 4           return newSVnv (ecb_binary32_to_float (fp));
1433             }
1434              
1435             case MISC_FLOAT64:
1436             {
1437             uint64_t fp;
1438 8 50         WANT (8);
1439 8           memcpy (&fp, dec->cur, 8);
1440 8           dec->cur += 8;
1441              
1442 8 50         if (!ecb_big_endian ())
1443 8           fp = ecb_bswap64 (fp);
1444              
1445 8           return newSVnv (ecb_binary64_to_double (fp));
1446             }
1447              
1448             // 0..19 unassigned simple
1449             // 24 reserved + unassigned simple (reserved values are not encodable)
1450             // 28-30 unassigned misc
1451             // 31 break code
1452             default:
1453 1           ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1454             }
1455              
1456             break;
1457             }
1458              
1459             fail:
1460 1           return &PL_sv_undef;
1461             }
1462              
1463             static SV *
1464 6547           decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1465             {
1466 6547           dec_t dec = { 0 };
1467             SV *sv;
1468             STRLEN len;
1469 6547 50         char *data = SvPVbyte (string, len);
1470              
1471 6547 100         if (len > cbor->max_size && cbor->max_size)
    50          
1472 0           croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1473 0           (unsigned long)len, (unsigned long)cbor->max_size);
1474              
1475 6547           dec.cbor = *cbor;
1476 6547           dec.cur = (U8 *)data;
1477 6547           dec.end = (U8 *)data + len;
1478              
1479 6547           sv = decode_sv (&dec);
1480              
1481 6547 100         if (offset_return)
1482 213           *offset_return = dec.cur;
1483              
1484 6547 100         if (!(offset_return || !sv))
    50          
1485 6334 100         if (dec.cur != dec.end && !dec.err)
    50          
1486 0           dec.err = "garbage after CBOR object";
1487              
1488 6547 100         if (dec.err)
1489             {
1490 5 100         if (dec.shareable)
1491             {
1492             // need to break cyclic links, which would all be in shareable
1493             int i;
1494             SV **svp;
1495              
1496 2 100         for (i = av_len (dec.shareable) + 1; i--; )
1497 1 50         if ((svp = av_fetch (dec.shareable, i, 0)))
1498 1           sv_setsv (*svp, &PL_sv_undef);
1499             }
1500              
1501 5           SvREFCNT_dec_NN (sv);
1502              
1503 5 50         if (dec.err_sv)
1504 0           sv_2mortal (dec.err_sv);
1505              
1506 5           croak ("%s, at offset %ld (octet 0x%02x)", dec.err, (long)(dec.cur - (U8 *)data), (int)(uint8_t)*dec.cur);
1507             }
1508              
1509 6542           sv = sv_2mortal (sv);
1510              
1511 6542           return sv;
1512             }
1513              
1514             /////////////////////////////////////////////////////////////////////////////
1515             // incremental parser
1516              
1517             #define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1518              
1519             // returns 0 for notyet, 1 for success or error
1520             static int
1521 428           incr_parse (CBOR *self, SV *cborstr)
1522             {
1523             STRLEN cur;
1524 428 50         SvPV (cborstr, cur);
1525              
1526 488 100         while (ecb_expect_true (self->incr_need <= cur))
1527             {
1528             // table of integer count bytes
1529             static I8 incr_len[MINOR_MASK + 1] = {
1530             0, 0, 0, 0, 0, 0, 0, 0,
1531             0, 0, 0, 0, 0, 0, 0, 0,
1532             0, 0, 0, 0, 0, 0, 0, 0,
1533             1, 2, 4, 8,-1,-1,-1,-2
1534             };
1535              
1536 370           const U8 *p = SvPVX (cborstr) + self->incr_pos;
1537 370           U8 m = *p & MINOR_MASK;
1538 370           IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1539 370           I8 ilen = incr_len[m];
1540              
1541 370           self->incr_need = self->incr_pos + 1;
1542              
1543 370 100         if (ecb_expect_false (ilen < 0))
1544             {
1545 19 50         if (m != MINOR_INDEF)
1546 0           return 1; // error
1547              
1548 19 100         if (*p == (MAJOR_MISC | MINOR_INDEF))
1549             {
1550 10 100         if (count >= 0)
1551 1           return 1; // error
1552              
1553 9           count = 1;
1554             }
1555             else
1556             {
1557 9           av_push (self->incr_count, newSViv (-1)); //TODO: nest
1558 18           count = -1;
1559             }
1560             }
1561             else
1562             {
1563 351           self->incr_need += ilen;
1564 351 100         if (ecb_expect_false (self->incr_need > cur))
1565 64           return 0;
1566              
1567 287           int major = *p >> MAJOR_SHIFT;
1568              
1569 287           switch (major)
1570             {
1571             case MAJOR_TAG >> MAJOR_SHIFT:
1572 0           ++count; // tags merely prefix another value
1573 0           break;
1574              
1575             case MAJOR_BYTES >> MAJOR_SHIFT:
1576             case MAJOR_TEXT >> MAJOR_SHIFT:
1577             case MAJOR_ARRAY >> MAJOR_SHIFT:
1578             case MAJOR_MAP >> MAJOR_SHIFT:
1579             {
1580             UV len;
1581              
1582 206 100         if (ecb_expect_false (ilen))
1583             {
1584 118           len = 0;
1585              
1586             do {
1587 453           len = (len << 8) | *++p;
1588 453 100         } while (--ilen);
1589             }
1590             else
1591 88           len = m;
1592              
1593 206           switch (major)
1594             {
1595             case MAJOR_BYTES >> MAJOR_SHIFT:
1596             case MAJOR_TEXT >> MAJOR_SHIFT:
1597 170           self->incr_need += len;
1598 170 100         if (ecb_expect_false (self->incr_need > cur))
1599 33           return 0;
1600              
1601 137           break;
1602              
1603             case MAJOR_MAP >> MAJOR_SHIFT:
1604 0           len <<= 1;
1605             /* FALLTHROUGH */
1606             case MAJOR_ARRAY >> MAJOR_SHIFT:
1607 36 100         if (len)
1608             {
1609 18           av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1610 18           count = len + 1;
1611             }
1612 36           break;
1613             }
1614             }
1615             }
1616             }
1617              
1618 272           self->incr_pos = self->incr_need;
1619              
1620 272 100         if (count > 0)
1621             {
1622 263 100         while (!--count)
1623             {
1624 239 100         if (!AvFILLp (self->incr_count))
1625 212           return 1; // done
1626              
1627 27           SvREFCNT_dec_NN (av_pop (self->incr_count));
1628 27           count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1629             }
1630              
1631 24           SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1632             }
1633             }
1634              
1635 428           return 0;
1636             }
1637              
1638            
1639             /////////////////////////////////////////////////////////////////////////////
1640             // XS interface functions
1641              
1642             MODULE = CBOR::XS PACKAGE = CBOR::XS
1643              
1644             BOOT:
1645             {
1646 11           cbor_stash = gv_stashpv ("CBOR::XS" , 1);
1647 11           cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1);
1648              
1649 11           types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1);
1650 11           types_error_stash = gv_stashpv ("Types::Serialiser::Error" , 1);
1651              
1652 11           types_true = get_bool ("Types::Serialiser::true" );
1653 11           types_false = get_bool ("Types::Serialiser::false");
1654 11           types_error = get_bool ("Types::Serialiser::error");
1655              
1656 11           default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1657              
1658 11           sv_cbor = newSVpv ("CBOR", 0);
1659 11           SvREADONLY_on (sv_cbor);
1660              
1661             assert (("STRLEN must be an unsigned type", 0 <= (STRLEN)-1));
1662             }
1663              
1664             PROTOTYPES: DISABLE
1665              
1666             void CLONE (...)
1667             CODE:
1668 0           cbor_stash = 0;
1669 0           cbor_tagged_stash = 0;
1670 0           types_error_stash = 0;
1671 0           types_boolean_stash = 0;
1672              
1673             void new (char *klass)
1674             PPCODE:
1675             {
1676 9238           SV *pv = NEWSV (0, sizeof (CBOR));
1677 9238           SvPOK_only (pv);
1678 9238           cbor_init ((CBOR *)SvPVX (pv));
1679 9238 50         XPUSHs (sv_2mortal (sv_bless (
    50          
1680             newRV_noinc (pv),
1681             strEQ (klass, "CBOR::XS") ? CBOR_STASH : gv_stashpv (klass, 1)
1682             )));
1683             }
1684              
1685             void shrink (CBOR *self, int enable = 1)
1686             ALIAS:
1687             shrink = F_SHRINK
1688             allow_unknown = F_ALLOW_UNKNOWN
1689             allow_sharing = F_ALLOW_SHARING
1690             allow_cycles = F_ALLOW_CYCLES
1691             allow_weak_cycles = F_ALLOW_WEAK_CYCLES
1692             forbid_objects = F_FORBID_OBJECTS
1693             pack_strings = F_PACK_STRINGS
1694             text_keys = F_TEXT_KEYS
1695             text_strings = F_TEXT_STRINGS
1696             validate_utf8 = F_VALIDATE_UTF8
1697             PPCODE:
1698             {
1699 6153 50         if (enable)
1700 6153           self->flags |= ix;
1701             else
1702 0           self->flags &= ~ix;
1703              
1704 6153 50         XPUSHs (ST (0));
1705             }
1706              
1707             void get_shrink (CBOR *self)
1708             ALIAS:
1709             get_shrink = F_SHRINK
1710             get_allow_unknown = F_ALLOW_UNKNOWN
1711             get_allow_sharing = F_ALLOW_SHARING
1712             get_allow_cycles = F_ALLOW_CYCLES
1713             get_allow_weak_cycles = F_ALLOW_WEAK_CYCLES
1714             get_forbid_objects = F_FORBID_OBJECTS
1715             get_pack_strings = F_PACK_STRINGS
1716             get_text_keys = F_TEXT_KEYS
1717             get_text_strings = F_TEXT_STRINGS
1718             get_validate_utf8 = F_VALIDATE_UTF8
1719             PPCODE:
1720 0 0         XPUSHs (boolSV (self->flags & ix));
    0          
1721              
1722             void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1723             PPCODE:
1724 0           self->max_depth = max_depth;
1725 0 0         XPUSHs (ST (0));
1726              
1727             U32 get_max_depth (CBOR *self)
1728             CODE:
1729 0           RETVAL = self->max_depth;
1730             OUTPUT:
1731             RETVAL
1732              
1733             void max_size (CBOR *self, U32 max_size = 0)
1734             PPCODE:
1735 2           self->max_size = max_size;
1736 2 50         XPUSHs (ST (0));
1737              
1738             int get_max_size (CBOR *self)
1739             CODE:
1740 0           RETVAL = self->max_size;
1741             OUTPUT:
1742             RETVAL
1743              
1744             void filter (CBOR *self, SV *filter = 0)
1745             PPCODE:
1746 0           SvREFCNT_dec (self->filter);
1747 0 0         self->filter = filter ? newSVsv (filter) : filter;
1748 0 0         XPUSHs (ST (0));
1749              
1750             SV *get_filter (CBOR *self)
1751             CODE:
1752 0 0         RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1753             OUTPUT:
1754             RETVAL
1755              
1756             void encode (CBOR *self, SV *scalar)
1757             PPCODE:
1758 6155           PUTBACK; scalar = encode_cbor (scalar, self); SPAGAIN;
1759 6155 50         XPUSHs (scalar);
1760              
1761             void decode (CBOR *self, SV *cborstr)
1762             PPCODE:
1763 3086           PUTBACK; cborstr = decode_cbor (cborstr, self, 0); SPAGAIN;
1764 3083 50         XPUSHs (cborstr);
1765              
1766             void decode_prefix (CBOR *self, SV *cborstr)
1767             PPCODE:
1768             {
1769             SV *sv;
1770             char *offset;
1771 0           PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1772 0 0         EXTEND (SP, 2);
1773 0           PUSHs (sv);
1774 0           PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1775             }
1776              
1777             void incr_parse (CBOR *self, SV *cborstr)
1778             ALIAS:
1779             incr_parse_multiple = 1
1780             PPCODE:
1781             {
1782 216 50         if (SvUTF8 (cborstr))
1783 0           sv_utf8_downgrade (cborstr, 0);
1784              
1785 216 100         if (!self->incr_count)
1786             {
1787 62           self->incr_count = newAV ();
1788 62           self->incr_pos = 0;
1789 62           self->incr_need = 1;
1790              
1791 62           av_push (self->incr_count, newSViv (1));
1792             }
1793              
1794             do
1795             {
1796 428 100         if (!incr_parse (self, cborstr))
1797             {
1798 215 50         if (self->incr_need > self->max_size && self->max_size)
    100          
1799 1           croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1800 1           (unsigned long)self->incr_need, (unsigned long)self->max_size);
1801              
1802 214           break;
1803             }
1804              
1805             SV *sv;
1806             char *offset;
1807              
1808 213           PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1809 212 50         XPUSHs (sv);
1810              
1811 212           sv_chop (cborstr, offset);
1812              
1813 212           av_clear (self->incr_count);
1814 212           av_push (self->incr_count, newSViv (1));
1815              
1816 212           self->incr_pos = 0;
1817 212           self->incr_need = self->incr_pos + 1;
1818             }
1819 212 50         while (ix);
1820             }
1821              
1822             void incr_reset (CBOR *self)
1823             CODE:
1824             {
1825 60           SvREFCNT_dec (self->incr_count);
1826 60           self->incr_count = 0;
1827             }
1828              
1829             void DESTROY (CBOR *self)
1830             PPCODE:
1831 9238           cbor_free (self);
1832              
1833             PROTOTYPES: ENABLE
1834              
1835             void encode_cbor (SV *scalar)
1836             ALIAS:
1837             encode_cbor = 0
1838             encode_cbor_sharing = F_ALLOW_SHARING
1839             PPCODE:
1840             {
1841             CBOR cbor;
1842 379           cbor_init (&cbor);
1843 379           cbor.flags |= ix;
1844 379           PUTBACK; scalar = encode_cbor (scalar, &cbor); SPAGAIN;
1845 379 50         XPUSHs (scalar);
1846             }
1847              
1848             void decode_cbor (SV *cborstr)
1849             PPCODE:
1850             {
1851             CBOR cbor;
1852 3248           cbor_init (&cbor);
1853 3248           PUTBACK; cborstr = decode_cbor (cborstr, &cbor, 0); SPAGAIN;
1854 3247 50         XPUSHs (cborstr);
1855             }
1856              
1857             #ifdef __AFL_COMPILER
1858              
1859             void
1860             afl_init ()
1861             CODE:
1862             __AFL_INIT ();
1863              
1864             int
1865             afl_loop (unsigned int count = 10000)
1866             CODE:
1867             RETVAL = __AFL_LOOP (count);
1868             OUTPUT:
1869             RETVAL
1870              
1871             #endif
1872