diff options
author | Paul "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 |
commit | cb6fe7a068e66c90514327b21407ae06469ce598 (patch) | |
tree | 22970f3669ffd1d40e9962216c07c74115037d6a | |
parent | d3043e2c050ac9f2d11d4cb8c1470b3ce0241dc1 (diff) | |
download | perl-cb6fe7a068e66c90514327b21407ae06469ce598.tar.gz |
When strptime() receives a reference, ensure it's a mutable scalar
-rw-r--r-- | ext/POSIX/POSIX.xs | 8 | ||||
-rw-r--r-- | ext/POSIX/t/time.t | 20 |
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 |