summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2010-01-15 17:13:17 +0100
committerRafael Garcia-Suarez <rgs@consttype.org>2010-01-15 17:14:17 +0100
commitb6d1426f94a845fb8fece8b6ad0b7d9f35f2d62e (patch)
tree54fe1920392ae403777a861a34c9946a65685764
parent75080c809516a97a6560fd6463b6574c254662f7 (diff)
downloadperl-b6d1426f94a845fb8fece8b6ad0b7d9f35f2d62e.tar.gz
[perl #62646] Maximum string length with substr
(This is only a partial fix, since it doesn't handle lvalue substr)
-rw-r--r--pp.c14
-rw-r--r--t/re/substr.t17
2 files changed, 23 insertions, 8 deletions
diff --git a/pp.c b/pp.c
index c659b13a1f..4735c94cfb 100644
--- a/pp.c
+++ b/pp.c
@@ -3079,12 +3079,12 @@ PP(pp_substr)
{
dVAR; dSP; dTARGET;
SV *sv;
- I32 len = 0;
+ IV len = 0;
STRLEN curlen;
STRLEN utf8_curlen;
- I32 pos;
- I32 rem;
- I32 fail;
+ IV pos;
+ IV rem;
+ IV fail;
const I32 lvalue = PL_op->op_flags & OPf_MOD || LVRET;
const char *tmps;
const I32 arybase = CopARYBASE_get(PL_curcop);
@@ -3147,7 +3147,7 @@ PP(pp_substr)
rem = curlen;
else if (len >= 0) {
rem = pos+len;
- if (rem > (I32)curlen)
+ if (rem > (IV)curlen)
rem = curlen;
}
else {
@@ -3167,8 +3167,8 @@ PP(pp_substr)
RETPUSHUNDEF;
}
else {
- const I32 upos = pos;
- const I32 urem = rem;
+ const IV upos = pos;
+ const IV urem = rem;
if (utf8_curlen)
sv_pos_u2b(sv, &pos, &rem);
tmps += pos;
diff --git a/t/re/substr.t b/t/re/substr.t
index c3fa6e10e7..49fd97bea7 100644
--- a/t/re/substr.t
+++ b/t/re/substr.t
@@ -24,7 +24,7 @@ $SIG{__WARN__} = sub {
require './test.pl';
-plan(334);
+plan(338);
run_tests() unless caller;
@@ -682,4 +682,19 @@ is($x, "\x{100}\x{200}\xFFb");
is(substr($a,1,1), 'b');
}
+# [perl #62646] offsets exceeding 32 bits on 64-bit system
+SKIP: {
+ skip("32-bit system", 4) unless ~0 > 0xffffffff;
+ my $a = "abc";
+ my $r;
+ $w = 0;
+ $r = substr($a, 0xffffffff, 1);
+ is($r, undef);
+ is($w, 1);
+ $w = 0;
+ $r = substr($a, 0xffffffff+1, 1);
+ is($r, undef);
+ is($w, 1);
+}
+
}