… | |
… | |
665 | SV *decode_tagged; |
665 | SV *decode_tagged; |
666 | } dec_t; |
666 | } dec_t; |
667 | |
667 | |
668 | #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE |
668 | #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE |
669 | |
669 | |
670 | #define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") |
670 | #define WANT(len) if (ecb_expect_false ((UV)(dec->end - dec->cur) < (UV)len)) ERR ("unexpected end of CBOR data") |
671 | |
671 | |
672 | #define DEC_INC_DEPTH if (++dec->depth > dec->cbor.max_depth) ERR (ERR_NESTING_EXCEEDED) |
672 | #define DEC_INC_DEPTH if (ecb_expect_false (++dec->depth > dec->cbor.max_depth)) ERR (ERR_NESTING_EXCEEDED) |
673 | #define DEC_DEC_DEPTH --dec->depth |
673 | #define DEC_DEC_DEPTH --dec->depth |
674 | |
674 | |
675 | static UV |
675 | static UV |
676 | decode_uint (dec_t *dec) |
676 | decode_uint (dec_t *dec) |
677 | { |
677 | { |
… | |
… | |
754 | av_push (av, decode_sv (dec)); |
754 | av_push (av, decode_sv (dec)); |
755 | } |
755 | } |
756 | } |
756 | } |
757 | else |
757 | else |
758 | { |
758 | { |
759 | int i, len = decode_uint (dec); |
759 | UV i, len = decode_uint (dec); |
760 | |
760 | |
761 | WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays |
761 | WANT (len); // complexity check for av_fill - need at least one byte per value, do not allow supersize arrays |
762 | av_fill (av, len - 1); |
762 | av_fill (av, len - 1); |
763 | |
763 | |
764 | for (i = 0; i < len; ++i) |
764 | for (i = 0; i < len; ++i) |
… | |
… | |
781 | // byte or utf-8 strings as keys, but only when !stringref |
781 | // byte or utf-8 strings as keys, but only when !stringref |
782 | |
782 | |
783 | if (ecb_expect_true (!dec->stringref)) |
783 | if (ecb_expect_true (!dec->stringref)) |
784 | if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8)) |
784 | if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8)) |
785 | { |
785 | { |
786 | I32 len = decode_uint (dec); |
786 | STRLEN len = decode_uint (dec); |
787 | char *key = (char *)dec->cur; |
787 | char *key = (char *)dec->cur; |
788 | |
788 | |
789 | WANT (len); |
789 | WANT (len); |
790 | dec->cur += len; |
790 | dec->cur += len; |
791 | |
791 | |
… | |
… | |
793 | |
793 | |
794 | return; |
794 | return; |
795 | } |
795 | } |
796 | else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8)) |
796 | else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8)) |
797 | { |
797 | { |
798 | I32 len = decode_uint (dec); |
798 | STRLEN len = decode_uint (dec); |
799 | char *key = (char *)dec->cur; |
799 | char *key = (char *)dec->cur; |
800 | |
800 | |
801 | WANT (len); |
801 | WANT (len); |
802 | dec->cur += len; |
802 | dec->cur += len; |
803 | |
803 | |
… | |
… | |
844 | decode_he (dec, hv); |
844 | decode_he (dec, hv); |
845 | } |
845 | } |
846 | } |
846 | } |
847 | else |
847 | else |
848 | { |
848 | { |
849 | int pairs = decode_uint (dec); |
849 | UV pairs = decode_uint (dec); |
|
|
850 | |
|
|
851 | WANT (pairs); // complexity check - need at least one byte per value, do not allow supersize hashes |
850 | |
852 | |
851 | while (pairs--) |
853 | while (pairs--) |
852 | decode_he (dec, hv); |
854 | decode_he (dec, hv); |
853 | } |
855 | } |
854 | |
856 | |
… | |
… | |
942 | sv = newRV_noinc (decode_sv (dec)); |
944 | sv = newRV_noinc (decode_sv (dec)); |
943 | break; |
945 | break; |
944 | |
946 | |
945 | case CBOR_TAG_STRINGREF_NAMESPACE: |
947 | case CBOR_TAG_STRINGREF_NAMESPACE: |
946 | { |
948 | { |
|
|
949 | // do nmot use SAVETMPS/FREETMPS, as these will |
|
|
950 | // erase mortalised caches, e.g. "shareable" |
947 | ENTER; SAVETMPS; |
951 | ENTER; |
948 | |
952 | |
949 | SAVESPTR (dec->stringref); |
953 | SAVESPTR (dec->stringref); |
950 | dec->stringref = (AV *)sv_2mortal ((SV *)newAV ()); |
954 | dec->stringref = (AV *)sv_2mortal ((SV *)newAV ()); |
951 | |
955 | |
952 | sv = decode_sv (dec); |
956 | sv = decode_sv (dec); |
953 | |
957 | |
954 | FREETMPS; LEAVE; |
958 | LEAVE; |
955 | } |
959 | } |
956 | break; |
960 | break; |
957 | |
961 | |
958 | case CBOR_TAG_STRINGREF: |
962 | case CBOR_TAG_STRINGREF: |
959 | { |
963 | { |
… | |
… | |
1392 | |
1396 | |
1393 | default_filter = newSVpv ("CBOR::XS::default_filter", 0); |
1397 | default_filter = newSVpv ("CBOR::XS::default_filter", 0); |
1394 | |
1398 | |
1395 | sv_cbor = newSVpv ("CBOR", 0); |
1399 | sv_cbor = newSVpv ("CBOR", 0); |
1396 | SvREADONLY_on (sv_cbor); |
1400 | SvREADONLY_on (sv_cbor); |
|
|
1401 | |
|
|
1402 | assert (("STRLEN must be an unsigned type", 0 <= (STRLEN)-1)); |
1397 | } |
1403 | } |
1398 | |
1404 | |
1399 | PROTOTYPES: DISABLE |
1405 | PROTOTYPES: DISABLE |
1400 | |
1406 | |
1401 | void CLONE (...) |
1407 | void CLONE (...) |