summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-02-22 22:30:19 +0000
committerNicholas Clark <nick@ccl4.org>2006-02-22 22:30:19 +0000
commita4f4e9060b702ac8bd69a560b36e93c3c44a5c97 (patch)
tree4ee4a8ea31e1dfb8dd217cbb98c9bc6d1cd9e47c
parentdb95ebb4c2fb7673862097bfdbfe3b9bb6d28ea5 (diff)
downloadperl-a4f4e9060b702ac8bd69a560b36e93c3c44a5c97.tar.gz
Avoid C<study>ing any strings that might change underneath us, such
as tied scalars and scalars with overloaded stringification. p4raw-id: //depot/perl@27273
-rw-r--r--pp.c21
-rw-r--r--t/op/studytied.t12
2 files changed, 18 insertions, 15 deletions
diff --git a/pp.c b/pp.c
index f9f9e7b82d..d41dd57d3c 100644
--- a/pp.c
+++ b/pp.c
@@ -639,13 +639,22 @@ PP(pp_study)
if (SvSCREAM(sv))
RETPUSHYES;
}
- else {
- if (PL_lastscream) {
- SvSCREAM_off(PL_lastscream);
- SvREFCNT_dec(PL_lastscream);
- }
- PL_lastscream = SvREFCNT_inc(sv);
+ s = (unsigned char*)(SvPV(sv, len));
+ pos = len;
+ if (pos <= 0 || !SvPOK(sv)) {
+ /* No point in studying a zero length string, and not safe to study
+ anything that doesn't appear to be a simple scalar (and hence might
+ change between now and when the regexp engine runs without our set
+ magic ever running, such as a reference to an object with overloaded
+ stringification. */
+ RETPUSHNO;
+ }
+
+ if (PL_lastscream) {
+ SvSCREAM_off(PL_lastscream);
+ SvREFCNT_dec(PL_lastscream);
}
+ PL_lastscream = SvREFCNT_inc(sv);
s = (unsigned char*)(SvPV(sv, len));
pos = len;
diff --git a/t/op/studytied.t b/t/op/studytied.t
index 2a78c8c2e2..d50c964744 100644
--- a/t/op/studytied.t
+++ b/t/op/studytied.t
@@ -41,16 +41,10 @@ for my $do_study qw( 0 1 ) {
is( index( $x, 'f' ), -1, qq{"next" doesn't contain "f"} );
# Subsequent references to $x are "next", so should match /n/
- TODO: {
- local $TODO = $do_study ? 'not yet fixed' : 0;
- ok( $x =~ /n/, qq{"next" matches /n/} );
- }
+ ok( $x =~ /n/, qq{"next" matches /n/} );
is( index( $x, 'n' ), 0, qq{"next" contains "n" at pos 0} );
# The letter "t" is in both, but in different positions
- TODO: {
- local $TODO = $do_study ? 'not yet fixed' : 0;
- ok( $x =~ /t/, qq{"next" matches /t/} );
- }
- is( index( $x, 't' ), 3, qq{"next" contains "t" at pos 3} );
+ ok( $x =~ /t/, qq{"next" matches /x/} );
+ is( index( $x, 't' ), 3, qq{"next" contains "x" at pos 3} );
}