diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-11-23 17:54:09 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-11-23 17:54:09 -0800 |
commit | b899e89d91e81e631e553a5b805e8d068828dbf0 (patch) | |
tree | 4c885aac1730e34c7d01b8814cd4c26c628cd61f /toke.c | |
parent | eed484f95050ad51c720521f68c6341a14bf5638 (diff) | |
download | perl-b899e89d91e81e631e553a5b805e8d068828dbf0.tar.gz |
Stop toke.c:S_scan_const from leaking
Fatal warnings and errors can cause the string buffer used when
scanning a quote-like operator to leak. This commit fixes it
by using the savestack. There are still a few leaks from that
code path that are not fixed by this.
Diffstat (limited to 'toke.c')
-rw-r--r-- | toke.c | 10 |
1 files changed, 6 insertions, 4 deletions
@@ -2966,6 +2966,9 @@ S_scan_const(pTHX_ char *start) this_utf8 = PL_sublex_info.sub_op->op_private & (PL_lex_repl ? OPpTRANS_FROM_UTF : OPpTRANS_TO_UTF); } + /* Protect sv from errors and fatal warnings. */ + ENTER_with_name("scan_const"); + SAVEFREESV(sv); while (s < send || dorange) { @@ -3037,7 +3040,6 @@ S_scan_const(pTHX_ char *start) #endif if (min > max) { - SvREFCNT_dec(sv); Perl_croak(aTHX_ "Invalid range \"%c-%c\" in transliteration operator", (char)min, (char)max); @@ -3096,7 +3098,6 @@ S_scan_const(pTHX_ char *start) /* range begins (ignore - as first or last char) */ else if (*s == '-' && s+1 < send && s != start) { if (didrange) { - SvREFCNT_dec(sv); Perl_croak(aTHX_ "Ambiguous range in transliteration operator"); } if (has_utf8 @@ -3723,6 +3724,7 @@ S_scan_const(pTHX_ char *start) /* return the substring (via pl_yylval) only if we parsed anything */ if (s > PL_bufptr) { + SvREFCNT_inc_simple_void_NN(sv); if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) ) { const char *const key = PL_lex_inpat ? "qr" : "q"; const STRLEN keylen = PL_lex_inpat ? 2 : 1; @@ -3747,8 +3749,8 @@ S_scan_const(pTHX_ char *start) type, typelen); } pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv); - } else - SvREFCNT_dec(sv); + } + LEAVE_with_name("scan_const"); return s; } |