… | |
… | |
661 | U32 depth; // recursion depth |
661 | U32 depth; // recursion depth |
662 | U32 maxdepth; // recursion depth limit |
662 | U32 maxdepth; // recursion depth limit |
663 | AV *shareable; |
663 | AV *shareable; |
664 | AV *stringref; |
664 | AV *stringref; |
665 | SV *decode_tagged; |
665 | SV *decode_tagged; |
|
|
666 | SV *err_sv; // optional sv for error, needs to be freed |
666 | } dec_t; |
667 | } dec_t; |
667 | |
668 | |
668 | #define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE |
669 | // set dec->err to ERRSV |
|
|
670 | ecb_cold static void |
|
|
671 | err_errsv (dec_t *dec) |
|
|
672 | { |
|
|
673 | if (!dec->err) |
|
|
674 | { |
|
|
675 | dec->err_sv = newSVsv (ERRSV); |
669 | |
676 | |
|
|
677 | // chop off the trailing \n |
|
|
678 | SvCUR_set (dec->err_sv, SvCUR (dec->err_sv) - 1); |
|
|
679 | *SvEND (dec->err_sv) = 0; |
|
|
680 | |
|
|
681 | dec->err = SvPVutf8_nolen (dec->err_sv); |
|
|
682 | } |
|
|
683 | } |
|
|
684 | |
|
|
685 | // the following functions are used to reduce code size and help the compiler to optimise |
|
|
686 | ecb_cold static void |
|
|
687 | err_set (dec_t *dec, const char *reason) |
|
|
688 | { |
|
|
689 | if (!dec->err) |
|
|
690 | dec->err = reason; |
|
|
691 | } |
|
|
692 | |
|
|
693 | ecb_cold static void |
|
|
694 | err_unexpected_end (dec_t *dec) |
|
|
695 | { |
|
|
696 | err_set (dec, "unexpected end of CBOR data"); |
|
|
697 | } |
|
|
698 | |
|
|
699 | ecb_cold static void |
|
|
700 | err_nesting_exceeded (dec_t *dec) |
|
|
701 | { |
|
|
702 | err_set (dec, ERR_NESTING_EXCEEDED); |
|
|
703 | } |
|
|
704 | |
|
|
705 | #define ERR_DO(do) SB do; goto fail; SE |
|
|
706 | #define ERR(reason) ERR_DO (err_set (dec, reason)) |
|
|
707 | #define ERR_ERRSV ERR_DO (err_errsv (dec)) |
|
|
708 | |
670 | #define WANT(len) if (ecb_expect_false ((UV)(dec->end - dec->cur) < (UV)len)) ERR ("unexpected end of CBOR data") |
709 | #define WANT(len) if (ecb_expect_false ((UV)(dec->end - dec->cur) < (UV)len)) ERR_DO (err_unexpected_end (dec)) |
671 | |
710 | |
672 | #define DEC_INC_DEPTH if (ecb_expect_false (++dec->depth > dec->cbor.max_depth)) ERR (ERR_NESTING_EXCEEDED) |
711 | #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 |
712 | #define DEC_DEC_DEPTH --dec->depth |
674 | |
713 | |
675 | static UV |
714 | static UV |
… | |
… | |
811 | } |
850 | } |
812 | |
851 | |
813 | SV *k = decode_sv (dec); |
852 | SV *k = decode_sv (dec); |
814 | SV *v = decode_sv (dec); |
853 | SV *v = decode_sv (dec); |
815 | |
854 | |
|
|
855 | // we leak memory if uncaught exceptions are thrown by random magical |
|
|
856 | // methods, and this is hopefully the only place where it can happen, |
|
|
857 | // so if there is a chance of an exception, take the very slow path. |
|
|
858 | // since catching exceptions is "undocumented/internal/forbidden" by |
|
|
859 | // the new p5p powers, we need to call out to a perl function :/ |
|
|
860 | if (ecb_expect_false (SvAMAGIC (k))) |
|
|
861 | { |
|
|
862 | dSP; |
|
|
863 | |
|
|
864 | ENTER; SAVETMPS; |
|
|
865 | PUSHMARK (SP); |
|
|
866 | EXTEND (SP, 3); |
|
|
867 | PUSHs (sv_2mortal (newRV_inc ((SV *)hv))); |
|
|
868 | PUSHs (sv_2mortal (k)); |
|
|
869 | PUSHs (sv_2mortal (v)); |
|
|
870 | |
|
|
871 | PUTBACK; |
|
|
872 | call_pv ("CBOR::XS::_hv_store", G_VOID | G_DISCARD | G_EVAL); |
|
|
873 | SPAGAIN; |
|
|
874 | |
|
|
875 | FREETMPS; LEAVE; |
|
|
876 | |
|
|
877 | if (SvTRUE (ERRSV)) |
|
|
878 | ERR_ERRSV; |
|
|
879 | |
|
|
880 | return; |
|
|
881 | } |
|
|
882 | |
816 | hv_store_ent (hv, k, v, 0); |
883 | hv_store_ent (hv, k, v, 0); |
817 | SvREFCNT_dec (k); |
884 | SvREFCNT_dec (k); |
818 | |
885 | |
819 | fail: |
886 | fail: |
820 | ; |
887 | ; |
… | |
… | |
1052 | SPAGAIN; |
1119 | SPAGAIN; |
1053 | |
1120 | |
1054 | if (SvTRUE (ERRSV)) |
1121 | if (SvTRUE (ERRSV)) |
1055 | { |
1122 | { |
1056 | FREETMPS; LEAVE; |
1123 | FREETMPS; LEAVE; |
1057 | ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV)))); |
1124 | ERR_ERRSV; |
1058 | } |
1125 | } |
1059 | |
1126 | |
1060 | SvREFCNT_dec (sv); |
1127 | SvREFCNT_dec (sv); |
1061 | sv = SvREFCNT_inc (POPs); |
1128 | sv = SvREFCNT_inc (POPs); |
1062 | |
1129 | |
… | |
… | |
1086 | |
1153 | |
1087 | if (SvTRUE (ERRSV)) |
1154 | if (SvTRUE (ERRSV)) |
1088 | { |
1155 | { |
1089 | SvREFCNT_dec (tag_sv); |
1156 | SvREFCNT_dec (tag_sv); |
1090 | FREETMPS; LEAVE; |
1157 | FREETMPS; LEAVE; |
1091 | ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV)))); |
1158 | ERR_ERRSV; |
1092 | } |
1159 | } |
1093 | |
1160 | |
1094 | if (count) |
1161 | if (count) |
1095 | { |
1162 | { |
1096 | SvREFCNT_dec (tag_sv); |
1163 | SvREFCNT_dec (tag_sv); |
… | |
… | |
1247 | if ((svp = av_fetch (dec.shareable, i, 0))) |
1314 | if ((svp = av_fetch (dec.shareable, i, 0))) |
1248 | sv_setsv (*svp, &PL_sv_undef); |
1315 | sv_setsv (*svp, &PL_sv_undef); |
1249 | } |
1316 | } |
1250 | |
1317 | |
1251 | SvREFCNT_dec (sv); |
1318 | SvREFCNT_dec (sv); |
|
|
1319 | |
|
|
1320 | if (dec.err_sv) |
|
|
1321 | sv_2mortal (dec.err_sv); |
|
|
1322 | |
1252 | croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); |
1323 | croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); |
1253 | } |
1324 | } |
1254 | |
1325 | |
1255 | sv = sv_2mortal (sv); |
1326 | sv = sv_2mortal (sv); |
1256 | |
1327 | |