summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-11-23 17:54:09 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-11-23 17:54:09 -0800
commitb899e89d91e81e631e553a5b805e8d068828dbf0 (patch)
tree4c885aac1730e34c7d01b8814cd4c26c628cd61f /toke.c
parenteed484f95050ad51c720521f68c6341a14bf5638 (diff)
downloadperl-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.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/toke.c b/toke.c
index 902f83cbc6..32367bc524 100644
--- a/toke.c
+++ b/toke.c
@@ -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;
}