diff --git a/op.c b/op.c index f616532c491c..b74c3a5bc560 100644 --- a/op.c +++ b/op.c @@ -10368,12 +10368,31 @@ Perl_cv_ckproto_len_flags(pTHX_ const CV *cv, const GV *gv, const char *p, else if (SvPOK(gv) && *SvPVX((SV *)gv) == '&') name = newSVpvn_flags(SvPVX((SV *)gv)+1, SvCUR(gv)-1, SvUTF8(gv)|SVs_TEMP); else if (flags & CV_CKPROTO_CURSTASH || SvROK(gv)) { - name = newSVhek_mortal(HvNAME_HEK(PL_curstash)); - sv_catpvs(name, "::"); + HEK* const stashname = HvNAME_HEK(PL_curstash); + HEK* cvname_hek; + U32 cat_len; + if (SvROK(gv)) { assert (SvTYPE(SvRV_const(gv)) == SVt_PVCV); assert (CvNAMED(SvRV_const(gv))); - sv_cathek(name, CvNAME_HEK(MUTABLE_CV(SvRV_const(gv)))); + cvname_hek = CvNAME_HEK(MUTABLE_CV(SvRV_const(gv))); + cat_len = HEK_LEN(cvname_hek); + } + else { + cvname_hek = NULL; + cat_len = 0; + } + I32 hek_len = HEK_LEN(stashname); + STRLEN total_len = hek_len + STRLENs("::") + cat_len + 1; + name = sv_2mortal(newSVpvz(total_len)); + sv_cathek(name, stashname); + assert(SvCUR(name) == hek_len); + char * pv = SvPVX(name) + hek_len; + SvCUR_set(name, hek_len + STRLENs("::")); + Copy("::", pv, STRLENs("::"), char); + + if (cvname_hek) { + sv_cathek(name, cvname_hek); } else sv_catsv(name, (SV *)gv); } @@ -14247,12 +14266,18 @@ Perl_ck_sort(pTHX_ OP *o) off = pad_findmy_pvn(tmpbuf, len+1, 0); if (off != NOT_IN_PAD) { if (PAD_COMPNAME_FLAGS_isOUR(off)) { - SV * const fq = - newSVhek(HvNAME_HEK(PAD_COMPNAME_OURSTASH(off))); - sv_catpvs(fq, "::"); - sv_catsv(fq, kSVOP_sv); - SvREFCNT_dec_NN(kSVOP_sv); + HEK* hek = HvNAME_HEK(PAD_COMPNAME_OURSTASH(off)); + SV * const kid_sv = kSVOP_sv; + I32 hek_len = HEK_LEN(hek); + STRLEN cat_len = SvPOK(kid_sv) ? SvCUR(kid_sv) : 0; + SV * const fq = newSVpvz(hek_len + STRLENs("::") + cat_len + 1); + sv_cathek(fq, hek); + char * pv = SvPVX(fq) + hek_len; + SvCUR_set(fq, hek_len + STRLENs("::")); + Copy("::", pv, STRLENs("::"), char); + sv_catsv(fq, kid_sv); kSVOP->op_sv = fq; + SvREFCNT_dec_NN(kid_sv); } else { /* replace the const op with the pad op */ diff --git a/toke.c b/toke.c index 5759c7890d32..c5afce7aa6ee 100644 --- a/toke.c +++ b/toke.c @@ -7723,10 +7723,15 @@ yyl_just_a_word(pTHX_ char *s, STRLEN len, I32 orig_keyword, struct code c) if (!c.sv) c.sv = S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len); if (c.gvp) { - SV *sv = newSVpvs("CORE::GLOBAL::"); + /* SvPOK() + SvCUR() is a good guess, but not a guarantee. */ + SV *sv = newSVpvz( STRLENs("CORE::GLOBAL::") + + (SvPOK(c.sv) ? SvCUR(c.sv) : 0) + 1); + SvCUR_set(sv, STRLENs("CORE::GLOBAL::")); + Copy("CORE::GLOBAL::", SvPVX(sv), sizeof("CORE::GLOBAL::"), char); sv_catsv(sv, c.sv); - SvREFCNT_dec(c.sv); + SV *oldsv = c.sv; c.sv = sv; + SvREFCNT_dec_NN(oldsv); } /* Presume this is going to be a bareword of some sort. */ @@ -9038,10 +9043,16 @@ yyl_keylookup(pTHX_ char *s, GV *gv) if (PAD_COMPNAME_FLAGS_isOUR(c.off)) { HV * const stash = PAD_COMPNAME_OURSTASH(c.off); HEK * const stashname = HvNAME_HEK(stash); - c.sv = newSVhek(stashname); - sv_catpvs(c.sv, "::"); - sv_catpvn_flags(c.sv, PL_tokenbuf, len, + I32 hek_len = HEK_LEN(stashname); + SV * sym = newSVpvz(hek_len + STRLENs("::") + len + 1); + sv_cathek(sym, stashname); + char * pv = SvPVX(sym) + hek_len; + SvCUR_set(sym, hek_len + STRLENs("::")); + Copy("::", pv, STRLENs("::"), char); + + sv_catpvn_flags(sym, PL_tokenbuf, len, (UTF ? SV_CATUTF8 : SV_CATBYTES)); + c.sv = sym; c.gv = gv_fetchsv(c.sv, GV_NOADD_NOINIT | SvUTF8(c.sv), SVt_PVCV); c.off = 0; @@ -10023,9 +10034,16 @@ S_pending_ident(pTHX) /* build ops for a bareword */ HV * const stash = PAD_COMPNAME_OURSTASH(tmp); HEK * const stashname = HvNAME_HEK(stash); - SV * const sym = newSVhek(stashname); - sv_catpvs(sym, "::"); - sv_catpvn_flags(sym, PL_tokenbuf+1, tokenbuf_len > 0 ? tokenbuf_len - 1 : 0, (UTF ? SV_CATUTF8 : SV_CATBYTES )); + /* terminating COW/'\0' bytes, pvz +1, we +1, total = 2 */ + I32 hek_len = HEK_LEN(stashname); + STRLEN cat_len = tokenbuf_len > 0 ? tokenbuf_len - 1 : 0; + SV * const sym = newSVpvz(hek_len + STRLENs("::") + cat_len + 1); + sv_cathek(sym, stashname); + char * pv = SvPVX(sym) + hek_len; + SvCUR_set(sym, hek_len + STRLENs("::")); + Copy("::", pv, sizeof("::"), char); + + sv_catpvn_flags(sym, PL_tokenbuf+1, cat_len, (UTF ? SV_CATUTF8 : SV_CATBYTES )); pl_yylval.opval = newSVOP(OP_CONST, 0, sym); pl_yylval.opval->op_private = OPpCONST_ENTERED; if (pit != '&') @@ -11477,9 +11495,16 @@ S_scan_inputsymbol(pTHX_ char *start) if (PAD_COMPNAME_FLAGS_isOUR(tmp)) { HV * const stash = PAD_COMPNAME_OURSTASH(tmp); HEK * const stashname = HvNAME_HEK(stash); - SV * const sym = newSVhek_mortal(stashname); - sv_catpvs(sym, "::"); - sv_catpv(sym, d+1); + STRLEN cat_len = strlen(d=(d+1)); + I32 hek_len = HEK_LEN(stashname); + STRLEN total_len = hek_len + STRLENs("::") + cat_len + 1; + SV * const sym = sv_2mortal(newSVpvz(total_len)); + sv_cathek(sym, stashname); + char * pv = SvPVX(sym) + hek_len; + SvCUR_set(sym, hek_len + STRLENs("::")); + Copy("::", pv, STRLENs("::"), char); + + sv_catpvn(sym, d, cat_len); d = SvPVX(sym); goto intro_sym; }