diff options
author | Tony Cook <tony@develop-help.com> | 2016-11-07 11:22:55 +1100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2016-11-07 11:22:55 +1100 |
commit | dc529e655355bff17b35ddec08d5bc5cbbdd206a (patch) | |
tree | b1573b8277ac360bcce0ecc60a58f9a66daa3dfc /doop.c | |
parent | a75f6a0b013c6142133284dab143f1ad0e581b10 (diff) | |
download | perl-dc529e655355bff17b35ddec08d5bc5cbbdd206a.tar.gz |
(perl #129995) avoid sv_catpvn() in do_vop() when unneeded
This could call sv_catpvn() with the source string being within the
destination SV, which caused a freed memory access if do_vop() and
sv_catpvn_flags() had different ideas about the ideal size of the
target SV's buffer.
Diffstat (limited to 'doop.c')
-rw-r--r-- | doop.c | 13 |
1 files changed, 11 insertions, 2 deletions
@@ -1218,8 +1218,17 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) len = lensave; if (rightlen > len) sv_catpvn_nomg(sv, rsave + len, rightlen - len); - else if (leftlen > (STRLEN)len) - sv_catpvn_nomg(sv, lsave + len, leftlen - len); + else if (leftlen > (STRLEN)len) { + if (sv == left) { + /* sv_catpvn() might move the source from under us, + and the data is already in place, just adjust to + include it */ + SvCUR_set(sv, leftlen); + *SvEND(sv) = '\0'; + } + else + sv_catpvn_nomg(sv, lsave + len, leftlen - len); + } else *SvEND(sv) = '\0'; break; |