summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2012-02-01 19:37:34 +0000
committerÆvar Arnfjörð Bjarmason <avar@cpan.org>2012-02-11 22:22:25 +0000
commitcb6fe7a068e66c90514327b21407ae06469ce598 (patch)
tree22970f3669ffd1d40e9962216c07c74115037d6a
parentd3043e2c050ac9f2d11d4cb8c1470b3ce0241dc1 (diff)
downloadperl-cb6fe7a068e66c90514327b21407ae06469ce598.tar.gz
When strptime() receives a reference, ensure it's a mutable scalar
-rw-r--r--ext/POSIX/POSIX.xs8
-rw-r--r--ext/POSIX/t/time.t20
2 files changed, 26 insertions, 2 deletions
diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs
index 64fe3fb575..2250f03491 100644
--- a/ext/POSIX/POSIX.xs
+++ b/ext/POSIX/POSIX.xs
@@ -1876,9 +1876,12 @@ strptime(str, fmt, sec=-1, min=-1, hour=-1, mday=-1, mon=-1, year=-1, wday=-1, y
tm.tm_yday = yday;
tm.tm_isdst = isdst;
- if(SvROK(str)) {
+ if(SvROK(str) && !SvOBJECT(SvRV(str))) {
strref = SvRV(str);
+ if(SvTYPE(strref) > SVt_PVMG || SvREADONLY(strref))
+ croak("str is not a reference to a mutable scalar");
+
str_base = str_c = SvPV_nolen(strref);
if(SvTYPE(strref) >= SVt_PVMG && SvMAGIC(strref))
@@ -1887,6 +1890,9 @@ strptime(str, fmt, sec=-1, min=-1, hour=-1, mday=-1, mon=-1, year=-1, wday=-1, y
if(posmg)
str_c += posmg->mg_len;
}
+ else if(SvROK(str) && SvTYPE(SvRV(str)) == SVt_REGEXP) {
+ croak("str is not a reference to a mutable scalar");
+ }
else {
str_c = SvPV_nolen(str);
}
diff --git a/ext/POSIX/t/time.t b/ext/POSIX/t/time.t
index bbf2c50d9a..959f675e4d 100644
--- a/ext/POSIX/t/time.t
+++ b/ext/POSIX/t/time.t
@@ -4,7 +4,7 @@ use strict;
use Config;
use POSIX;
-use Test::More tests => 29;
+use Test::More tests => 33;
# go to UTC to avoid DST issues around the world when testing. SUS3 says that
# null should get you UTC, but some environments want the explicit names.
@@ -98,6 +98,24 @@ pos($str) = 10;
is_deeply(\@time, [0, 0, 0, 1, 12-1, 2012-1900, 6, 335, 0], 'strptime() starts SCALAR ref at pos()');
is(pos($str), 20, 'strptime() updates pos() magic on SCALAR ref');
+eval { POSIX::strptime({}, "format") };
+like($@, qr/not a reference to a mutable scalar/, 'strptime() dies on HASH ref');
+
+eval { POSIX::strptime(\"boo", "format") };
+like($@, qr/not a reference to a mutable scalar/, 'strptime() dies on const literal ref');
+
+eval { POSIX::strptime(qr/boo!/, "format") };
+like($@, qr/not a reference to a mutable scalar/, 'strptime() dies on Regexp');
+
+$str = bless [], "WithStringOverload";
+{
+ package WithStringOverload;
+ use overload '""' => sub { return "2012-02-01" };
+}
+
+@time = POSIX::strptime($str, "%Y-%m-%d", 0, 0, 0);
+is_deeply(\@time, [0, 0, 0, 1, 2-1, 2012-1900, 3, 31, 0], 'strptime() allows object with string overload');
+
setlocale(LC_TIME, $orig_loc) || die "Cannot setlocale() back to orig: $!";
# clock() seems to have different definitions of what it does between POSIX