X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/539689e74a3bcb04d29e4cd9396de91a81045b99..a2c0032b06b9fa4a6d26a50dc6e736c05e4fcb09:/pp.c?ds=sidebyside diff --git a/pp.c b/pp.c index 8b15b6e..9579503 100644 --- a/pp.c +++ b/pp.c @@ -712,8 +712,7 @@ PP(pp_study) RETPUSHYES; } s = (unsigned char*)(SvPV(sv, len)); - pos = len; - if (pos <= 0 || !SvPOK(sv) || SvUTF8(sv)) { + if (len == 0 || len > I32_MAX || !SvPOK(sv) || SvUTF8(sv)) { /* No point in studying a zero length string, and not safe to study anything that doesn't appear to be a simple scalar (and hence might change between now and when the regexp engine runs without our set @@ -721,6 +720,7 @@ PP(pp_study) stringification. */ RETPUSHNO; } + pos = len; if (PL_lastscream) { SvSCREAM_off(PL_lastscream); @@ -728,10 +728,6 @@ PP(pp_study) } PL_lastscream = SvREFCNT_inc_simple(sv); - s = (unsigned char*)(SvPV(sv, len)); - pos = len; - if (pos <= 0) - RETPUSHNO; if (pos > PL_maxscream) { if (PL_maxscream < 0) { PL_maxscream = pos + 80; @@ -4836,54 +4832,26 @@ PP(pp_rkeys) dSP; dPOPss; - if (!SvOK(sv)) - RETURN; - - if (SvROK(sv)) { - SvGETMAGIC(sv); - if (SvAMAGIC(sv)) { - /* N.B.: AMG macros return sv if no overloading is found */ - SV *maybe_hv = AMG_CALLunary(sv, to_hv_amg); - SV *maybe_av = AMG_CALLunary(sv, to_av_amg); - if ( maybe_hv != sv && maybe_av != sv ) { - Perl_ck_warner(aTHX_ packWARN(WARN_AMBIGUOUS), "%s", - Perl_form(aTHX_ "Ambiguous overloaded argument to %s resolved as %%{}", - PL_op_desc[PL_op->op_type] - ) - ); - sv = maybe_hv; - } - else if ( maybe_av != sv ) { - if ( SvTYPE(SvRV(sv)) == SVt_PVHV ) { - /* @{} overload, but underlying reftype is HV */ - Perl_ck_warner(aTHX_ packWARN(WARN_AMBIGUOUS), "%s", - Perl_form(aTHX_ "Ambiguous overloaded argument to %s resolved as @{}", - PL_op_desc[PL_op->op_type] - ) - ); - } - sv = maybe_av; - } - else if ( maybe_hv != sv ) { - if ( SvTYPE(SvRV(sv)) == SVt_PVAV ) { - /* %{} overload, but underlying reftype is AV */ - Perl_ck_warner(aTHX_ packWARN(WARN_AMBIGUOUS), "%s", - Perl_form(aTHX_ "Ambiguous overloaded argument to %s resolved as %%{}", - PL_op_desc[PL_op->op_type] - ) - ); - } - sv = maybe_hv; - } - } - sv = SvRV(sv); - } - - if ( SvTYPE(sv) != SVt_PVHV && SvTYPE(sv) != SVt_PVAV ) { - DIE(aTHX_ "Type of argument to %s must be hashref or arrayref", + SvGETMAGIC(sv); + + if ( + !SvROK(sv) + || (sv = SvRV(sv), + (SvTYPE(sv) != SVt_PVHV && SvTYPE(sv) != SVt_PVAV) + || SvOBJECT(sv) + ) + ) { + DIE(aTHX_ + "Type of argument to %s must be unblessed hashref or arrayref", PL_op_desc[PL_op->op_type] ); } + if (PL_op->op_flags & OPf_SPECIAL && SvTYPE(sv) == SVt_PVAV) + DIE(aTHX_ + "Can't modify %s in %s", + PL_op_desc[PL_op->op_type], PL_op_desc[PL_op->op_next->op_type] + ); + /* Delegate to correct function for op type */ PUSHs(sv); if (PL_op->op_type == OP_RKEYS || PL_op->op_type == OP_RVALUES) { @@ -5424,10 +5392,40 @@ PP(pp_anonhash) RETURN; } +static AV * +S_deref_plain_array(pTHX_ AV *ary) +{ + if (SvTYPE(ary) == SVt_PVAV) return ary; + SvGETMAGIC((SV *)ary); + if (!SvROK(ary) || SvTYPE(SvRV(ary)) != SVt_PVAV) + Perl_die(aTHX_ "Not an ARRAY reference"); + else if (SvOBJECT(SvRV(ary))) + Perl_die(aTHX_ "Not an unblessed ARRAY reference"); + return (AV *)SvRV(ary); +} + +#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) +# define DEREF_PLAIN_ARRAY(ary) \ + ({ \ + AV *aRrRay = ary; \ + SvTYPE(aRrRay) == SVt_PVAV \ + ? aRrRay \ + : S_deref_plain_array(aTHX_ aRrRay); \ + }) +#else +# define DEREF_PLAIN_ARRAY(ary) \ + ( \ + PL_Sv = (SV *)(ary), \ + SvTYPE(PL_Sv) == SVt_PVAV \ + ? (AV *)PL_Sv \ + : S_deref_plain_array(aTHX_ (AV *)PL_Sv) \ + ) +#endif + PP(pp_splice) { dVAR; dSP; dMARK; dORIGMARK; - register AV *ary = MUTABLE_AV(*++MARK); + register AV *ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK)); register SV **src; register SV **dst; register I32 i; @@ -5630,7 +5628,7 @@ PP(pp_splice) PP(pp_push) { dVAR; dSP; dMARK; dORIGMARK; dTARGET; - register AV * const ary = MUTABLE_AV(*++MARK); + register AV * const ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK)); const MAGIC * const mg = SvTIED_mg((const SV *)ary, PERL_MAGIC_tied); if (mg) { @@ -5667,7 +5665,7 @@ PP(pp_shift) dVAR; dSP; AV * const av = PL_op->op_flags & OPf_SPECIAL - ? MUTABLE_AV(GvAV(PL_defgv)) : MUTABLE_AV(POPs); + ? MUTABLE_AV(GvAV(PL_defgv)) : DEREF_PLAIN_ARRAY(MUTABLE_AV(POPs)); SV * const sv = PL_op->op_type == OP_SHIFT ? av_shift(av) : av_pop(av); EXTEND(SP, 1); assert (sv); @@ -5680,7 +5678,7 @@ PP(pp_shift) PP(pp_unshift) { dVAR; dSP; dMARK; dORIGMARK; dTARGET; - register AV *ary = MUTABLE_AV(*++MARK); + register AV *ary = DEREF_PLAIN_ARRAY(MUTABLE_AV(*++MARK)); const MAGIC * const mg = SvTIED_mg((const SV *)ary, PERL_MAGIC_tied); if (mg) { @@ -6337,7 +6335,7 @@ PP(pp_boolkeys) } } - XPUSHs(boolSV(HvKEYS(hv) != 0)); + XPUSHs(boolSV(HvUSEDKEYS(hv) != 0)); RETURN; }