summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2007-01-27 00:45:30 +0000
committerNicholas Clark <nick@ccl4.org>2007-01-27 00:45:30 +0000
commit448670305e91e35ff5a396a7d764ec8b1844012e (patch)
tree4f4152259d965908371ed3451b41240a9177ce48 /toke.c
parent6ef8aa7c9cfbc9b6bc5d5b07d6e1506e3058b4aa (diff)
downloadperl-448670305e91e35ff5a396a7d764ec8b1844012e.tar.gz
A test to exercise the smallbuf overflow code in S_incline, and a
refactoring of that code to use only one 128 char array, not two. p4raw-id: //depot/perl@30024
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/toke.c b/toke.c
index 51c0cf751c..8f6c5ce7d6 100644
--- a/toke.c
+++ b/toke.c
@@ -788,25 +788,40 @@ S_incline(pTHX_ const char *s)
if (tmplen > 7 && strnEQ(cf, "(eval ", 6)) {
/* must copy *{"::_<(eval N)[oldfilename:L]"}
* to *{"::_<newfilename"} */
- char smallbuf[128], smallbuf2[128];
- char *tmpbuf, *tmpbuf2;
- GV **gvp, *gv2;
+ /* However, the long form of evals is only turned on by the
+ debugger - usually they're "(eval %lu)" */
+ char smallbuf[128];
+ char *tmpbuf;
+ GV **gvp;
STRLEN tmplen2 = len;
if (tmplen + 2 <= sizeof smallbuf)
tmpbuf = smallbuf;
else
Newx(tmpbuf, tmplen + 2, char);
- if (tmplen2 + 2 <= sizeof smallbuf2)
- tmpbuf2 = smallbuf2;
- else
- Newx(tmpbuf2, tmplen2 + 2, char);
- tmpbuf[0] = tmpbuf2[0] = '_';
- tmpbuf[1] = tmpbuf2[1] = '<';
+ tmpbuf[0] = '_';
+ tmpbuf[1] = '<';
memcpy(tmpbuf + 2, cf, tmplen);
- memcpy(tmpbuf2 + 2, s, tmplen2);
- tmplen += 2; tmplen2 += 2;
+ tmplen += 2;
gvp = (GV**)hv_fetch(PL_defstash, tmpbuf, tmplen, FALSE);
if (gvp) {
+ char *tmpbuf2;
+ GV *gv2;
+
+ if (tmplen2 + 2 <= sizeof smallbuf)
+ tmpbuf2 = smallbuf;
+ else
+ Newx(tmpbuf2, tmplen2 + 2, char);
+
+ if (tmpbuf2 != smallbuf || tmpbuf != smallbuf) {
+ /* Either they malloc'd it, or we malloc'd it,
+ so no prefix is present in ours. */
+ tmpbuf2[0] = '_';
+ tmpbuf2[1] = '<';
+ }
+
+ memcpy(tmpbuf2 + 2, s, tmplen2);
+ tmplen2 += 2;
+
gv2 = *(GV**)hv_fetch(PL_defstash, tmpbuf2, tmplen2, TRUE);
if (!isGV(gv2)) {
gv_init(gv2, PL_defstash, tmpbuf2, tmplen2, FALSE);
@@ -815,9 +830,10 @@ S_incline(pTHX_ const char *s)
GvHV(gv2) = (HV*)SvREFCNT_inc(GvHV(*gvp));
GvAV(gv2) = (AV*)SvREFCNT_inc(GvAV(*gvp));
}
+
+ if (tmpbuf2 != smallbuf) Safefree(tmpbuf2);
}
if (tmpbuf != smallbuf) Safefree(tmpbuf);
- if (tmpbuf2 != smallbuf2) Safefree(tmpbuf2);
}
#endif
CopFILE_free(PL_curcop);