Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace some sv_2mortal() instances with more direct equivalents #23153

Open
wants to merge 5 commits into
base: blead
Choose a base branch
from

Conversation

richardleach
Copy link
Contributor

A few commits making this sort of change:

  • sv_2mortal(newSVpvn_utf8(SvPVX(sv), namelen, do_utf8));
    -> newSVpvn_flags(SvPVX(sv), namelen, SVs_TEMP|do_utf8);
  • newSVpvn_utf8(key, klen, TRUE); + sv_2mortal()
    -> newSVpvn_flags(key, klen, SVf_UTF8|SVs_TEMP);
  • (AV *) sv_2mortal((SV *) newAV())
    -> MUTABLE_AV(newSV_type_mortal(SVt_PVAV));

The changes are intended to be functionally equivalent but do the work
through one function call rather than two.


  • This set of changes does not require a perldelta entry.

@@ -4189,7 +4189,8 @@ Perl_do_readline(pTHX)
}
else {
/* XXX on RC builds, push on stack rather than mortalize ? */
sv = sv_2mortal(newSV(80));
sv = newSV_type(SVt_PV);
sv_grow_fresh(sv, 81);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What end the life of the sv head now that mortal is missing?
Why 81 bytes when old was 80?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What end the life of the sv head now that mortal is missing?

Thanks, it was meant to be newSV_type_mortal, I'll change that now.

Why 81 bytes when old was 80?

It's to keep the allocation size consistent: Perl_newSV calls sv_grow_fresh(sv, len + 1);.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 81 bytes when old was 80?

It's to keep the allocation size consistent: Perl_newSV calls sv_grow_fresh(sv, len + 1);.

Be very very careful and single step it line by line if your making assumptions about +1s and perl's PV/NewX API. This class of bugs already is sitting in stable and blead perl. "can't introduce an exploit" "safe than sorry" +1 +1, another 16 or 32 bytes just disappeared times a couple 1000. All these +1s and the PERL_STR_RNDUP macro are very fragile. Open PR with this class of bug

#22879

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update:
the off by 1 in

#23153

goes back to your commit at

64b4056614429bb6fc7d35118e19a220459358fd

I suggest you single step the C code and verify what integer from the interp is entering glibc.so func since you/nobody else (including me) understands this area of the SVPV API anymore. Short made up demo math of the details in #23153

80/8=10, aligned!
(81+7)&(~7)=88
(81+15)&(~15)=96

Atleast use bytes 82-95 on a PP C level if you paided for them from libc, but this 1+1+15 then !0xF mask over and ever. needs to be stopped.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The +1 is done by the normal Perl_sv_grow() for the default COW build as well, sv_grow_fresh simply duplicates that.

That said, the exact value doesn't matter too much.

@richardleach richardleach force-pushed the unnecessary_sv2mortal branch from 89e85e9 to 981d0f7 Compare March 25, 2025 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants