From 41f32396eee9395a40f9ed80145c37622560de9b Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Tue, 21 Feb 2023 09:01:13 +0100 Subject: [PATCH] fix decode out-of-bounds on hash keys without : security: could leak secrets. Fixes GH 208 --- XS.xs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/XS.xs b/XS.xs index 419e07e..bbe1a8b 100644 --- a/XS.xs +++ b/XS.xs @@ -2724,6 +2724,8 @@ decode_comment (dec_t *dec) INLINE void decode_ws (dec_t *dec) { + if (dec->cur >= dec->end) + return; for (;;) { char ch = *dec->cur; @@ -2750,7 +2752,7 @@ decode_ws (dec_t *dec) #define ERR(reason) SB dec->err = reason; goto fail; SE -#define EXPECT_CH(ch) SB \ +#define EXPECT_CH(ch) SB \ if (*dec->cur != ch) \ ERR (# ch " expected"); \ ++dec->cur; \ @@ -3923,7 +3925,8 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) } } // else overwrite it below } - decode_ws (dec); EXPECT_CH (':'); + decode_ws (dec); + EXPECT_CH (':'); decode_ws (dec); if (typesv) @@ -3995,7 +3998,10 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) } dec->cur = p + 1; - decode_ws (dec); if (*p != ':') EXPECT_CH (':'); + if (dec->cur >= dec->end) + EXPECT_CH (':'); + decode_ws (dec); + if (*p != ':') EXPECT_CH (':'); decode_ws (dec); if (typesv) @@ -4026,6 +4032,10 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) break; } ++p; + if (p > dec->end) { + dec->cur = p; + EXPECT_CH (':'); + } } } @@ -4485,11 +4495,16 @@ decode_json (pTHX_ SV *string, JSON *json, STRLEN *offset_return, SV *typesv) if (!sv) { SV *uni = sv_newmortal (); - + COP cop = *PL_curcop; + if (dec.cur >= dec.end) // overshoot + { + croak ("%s, at character offset %d", + dec.err, + (int)ptr_to_index (aTHX_ string, dec.cur - SvPVX(string))); + } #if PERL_VERSION >= 8 /* horrible hack to silence warning inside pv_uni_display */ /* TODO: Can be omitted with newer perls */ - COP cop = *PL_curcop; cop.cop_warnings = pWARN_NONE; ENTER; SAVEVPTR (PL_curcop); @@ -4500,7 +4515,7 @@ decode_json (pTHX_ SV *string, JSON *json, STRLEN *offset_return, SV *typesv) croak ("%s, at character offset %d (before \"%s\")", dec.err, (int)ptr_to_index (aTHX_ string, dec.cur - SvPVX(string)), - dec.cur != dec.end ? SvPV_nolen (uni) : "(end of string)"); + dec.cur < dec.end ? SvPV_nolen (uni) : "(end of string)"); } if (!(dec.json.flags & F_ALLOW_NONREF) && json_nonref(aTHX_ sv)) {