--- CBOR-XS/XS.xs 2013/11/30 17:37:45 1.36 +++ CBOR-XS/XS.xs 2013/12/01 14:45:03 1.39 @@ -99,7 +99,9 @@ #define F_SHRINK 0x00000001UL #define F_ALLOW_UNKNOWN 0x00000002UL #define F_ALLOW_SHARING 0x00000004UL -#define F_PACK_STRINGS 0x00000008UL +#define F_ALLOW_CYCLES 0x00000008UL +#define F_PACK_STRINGS 0x00000010UL +#define F_VALIDATE_UTF8 0x00000020UL #define INIT_SIZE 32 // initial scalar size to be allocated @@ -737,9 +739,6 @@ dec->cur += len; - if (ecb_expect_false (dec->stringref)) - av_push (dec->stringref, newSVpvn (key, len)); - hv_store (hv, key, len, decode_sv (dec), 0); return; @@ -751,8 +750,9 @@ dec->cur += len; - if (ecb_expect_false (dec->stringref)) - av_push (dec->stringref, newSVpvn_utf8 (key, len, 1)); + if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8)) + if (!is_utf8_string (key, len)) + ERR ("corrupted CBOR data (invalid UTF-8 in map key)"); hv_store (hv, key, -len, decode_sv (dec), 0); @@ -764,6 +764,9 @@ hv_store_ent (hv, k, v, 0); SvREFCNT_dec (k); + +fail: + ; } static SV * @@ -855,7 +858,13 @@ } if (utf8) - SvUTF8_on (sv); + { + if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8)) + if (!is_utf8_string (SvPVX (sv), SvCUR (sv))) + ERR ("corrupted CBOR data (invalid UTF-8 in text string)"); + + SvUTF8_on (sv); + } return sv; @@ -914,12 +923,22 @@ if (ecb_expect_false (!dec->shareable)) dec->shareable = (AV *)sv_2mortal ((SV *)newAV ()); - sv = newSV (0); - av_push (dec->shareable, SvREFCNT_inc_NN (sv)); + if (dec->cbor.flags & F_ALLOW_CYCLES) + { + sv = newSV (0); + av_push (dec->shareable, SvREFCNT_inc_NN (sv)); - SV *osv = decode_sv (dec); - sv_setsv (sv, osv); - SvREFCNT_dec_NN (osv); + SV *osv = decode_sv (dec); + sv_setsv (sv, osv); + SvREFCNT_dec_NN (osv); + } + else + { + av_push (dec->shareable, &PL_sv_undef); + int idx = AvFILLp (dec->shareable); + sv = decode_sv (dec); + av_store (dec->shareable, idx, SvREFCNT_inc_NN (sv)); + } } break; @@ -934,6 +953,9 @@ ERR ("corrupted CBOR data (sharedref index out of bounds)"); sv = SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]); + + if (sv == &PL_sv_undef) + ERR ("cyclic CBOR data structure found, but allow_cycles is not enabled"); } break; @@ -1151,6 +1173,17 @@ if (dec.err) { + if (dec.shareable) + { + // need to break cyclic links, which whould all be in shareable + int i; + SV **svp; + + for (i = av_len (dec.shareable) + 1; i--; ) + if ((svp = av_fetch (dec.shareable, i, 0))) + sv_setsv (*svp, &PL_sv_undef); + } + SvREFCNT_dec (sv); croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); } @@ -1209,7 +1242,9 @@ shrink = F_SHRINK allow_unknown = F_ALLOW_UNKNOWN allow_sharing = F_ALLOW_SHARING + allow_cycles = F_ALLOW_CYCLES pack_strings = F_PACK_STRINGS + validate_utf8 = F_VALIDATE_UTF8 PPCODE: { if (enable) @@ -1225,7 +1260,9 @@ get_shrink = F_SHRINK get_allow_unknown = F_ALLOW_UNKNOWN get_allow_sharing = F_ALLOW_SHARING + get_allow_cycles = F_ALLOW_CYCLES get_pack_strings = F_PACK_STRINGS + get_validate_utf8 = F_VALIDATE_UTF8 PPCODE: XPUSHs (boolSV (self->flags & ix));