Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite recursion related to die, overloading, s/// and \x{...} #8804

Closed
p5pRT opened this issue Feb 26, 2007 · 7 comments
Closed

Infinite recursion related to die, overloading, s/// and \x{...} #8804

p5pRT opened this issue Feb 26, 2007 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 26, 2007

Migrated from rt.perl.org#41618 (status was 'resolved')

Searchable as RT41618$

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2007

From @cpansprout

If the following hold true--

  - die is called outside an eval
  - its argument is an object with overloaded stringification
  - while the stringification subroutine is on the call stack a
substitution is performed
  - the substitution's regexp contains [\x{d800}-\x{dbff}]

--then the substitution operator will automagically call the
stringification routine again with the same arguments, thereby
causing infinite recursion.

Here is a test script​:

#!/usr/bin/perl -lw

no warnings 'once';

use Carp 'longmess';
use overload '""' => sub {
  warn longmess if ++$count == 10;

  my $x = 'thing'; # any string will trigger the bug
  $x =~ s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
  chr 0x10000 + (ord($1) - 0xD800) * 0x400 +
  (ord($2) - 0xDC00)
  /ge;
  $x
};

$thing = bless [];
die $thing;
# die "$thing"; # this one works, because 'die' is not doing the
stringification

__END__

If I use s/[a-e]/b/g for the substitution, the bug is not triggered.
It's the [\x{d800}-\x{dbff}] that does it.

This bug exists in 5.9.4 as well as 5.8.8.

This is a really obscure bug--it took me a while to reproduce it. :-)


Flags​:
  category=core
  severity=


Site configuration information for perl v5.8.8​:

Configured by neo at Tue Jan 9 16​:06​:53 PST 2007.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration​:
  Platform​:
  osname=darwin, osvers=8.8.0, archname=darwin-thread-multi-2level
  uname='darwin treebeard.local 8.8.0 darwin kernel version 8.8.0​:
fri sep 8 17​:18​:57 pdt 2006; root​:xnu-792.12.6.obj~1release_ppc power
macintosh powerpc '
  config_args=''
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=undef use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-g -pipe -fno-common -DPERL_DARWIN -no-cpp-
precomp -fno-strict-aliasing -I/usr/local/include',
  optimize='-O3',
  cppflags='-no-cpp-precomp -g -pipe -fno-common -DPERL_DARWIN -no-
cpp-precomp -fno-strict-aliasing -I/usr/local/include'
  ccversion='', gccversion='4.0.0 20041026 (Apple Computer, Inc.
build 4061)', gccosandvers='darwin8'
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=4, nvtype='double', nvsize=8,
Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -L/usr/
local/lib'
  libpth=/usr/local/lib /usr/lib
  libs=-ldbm -ldl -lm -lc
  perllibs=-ldl -lm -lc
  libc=, so=dylib, useshrplib=false, libperl=libperl.a
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/
usr/local/lib'

Locally applied patches​:


@​INC for perl v5.8.8​:
  /usr/local/lib/perl5/5.8.8/darwin-thread-multi-2level
  /usr/local/lib/perl5/5.8.8
  /usr/local/lib/perl5/site_perl/5.8.8/darwin-thread-multi-2level
  /usr/local/lib/perl5/site_perl/5.8.8
  /usr/local/lib/perl5/site_perl
  /System/Library/Perl/5.8.6/darwin-thread-multi-2level
  /System/Library/Perl/5.8.6/darwin-thread-multi-2level
  /System/Library/Perl/5.8.6
  /Library/Perl/5.8.6/darwin-thread-multi-2level
  /Library/Perl/5.8.6/darwin-thread-multi-2level
  /Library/Perl/5.8.6
  /Library/Perl
  /Network/Library/Perl/5.8.6/darwin-thread-multi-2level
  /Network/Library/Perl/5.8.6
  /Network/Library/Perl
  /System/Library/Perl/Extras/5.8.6/darwin-thread-multi-2level
  /System/Library/Perl/Extras/5.8.6/darwin-thread-multi-2level
  /System/Library/Perl/Extras/5.8.6
  /Library/Perl/5.8.1
  .


Environment for perl v5.8.8​:
  DYLD_LIBRARY_PATH (unset)
  HOME=/Users/neo
  LANG (unset)
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/bin​:/sbin​:/usr/bin​:/usr/sbin​:/usr/TeX/bin/powerpc-
darwin6.8​:/usr/local/bin
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2007

From @cpansprout

I've just noticed that the debugging line I added (warn longmess...)
actually stops the recursion (though in a larger module in which I
first encountered the bug, it doesn't). If I delete it, I get the
following warning​:

Deep recursion on anonymous subroutine at overtest line 10.

Line 10 is the line with the substitution.

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2007

From @rgarcia

On 26/02/07, via RT Father Chrysostomos <perlbug-followup@​perl.org> wrote​:

If the following hold true--

- die is called outside an eval
- its argument is an object with overloaded stringification
- while the stringification subroutine is on the call stack a
substitution is performed
- the substitution's regexp contains [\x{d800}-\x{dbff}]

that is, an Unicode surrogate,

--then the substitution operator will automagically call the
stringification routine again with the same arguments, thereby
causing infinite recursion.

I don't reproduce this with bleadperl; I think that was fixed by
change #30213, but I haven't checked.

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2007

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2008

From p5p@spam.wizbit.be

On Sun Feb 25 18​:08​:34 2007, sprout@​cpan.org wrote​:

If the following hold true--

- die is called outside an eval
- its argument is an object with overloaded stringification
- while the stringification subroutine is on the call stack a
substitution is performed
- the substitution's regexp contains [\x{d800}-\x{dbff}]

--then the substitution operator will automagically call the
stringification routine again with the same arguments, thereby
causing infinite recursion.

Here is a test script​:

#!/usr/bin/perl -lw

no warnings 'once';

use Carp 'longmess';
use overload '""' => sub {
warn longmess if ++$count == 10;

my $x = 'thing'; \# any string will trigger the bug
$x =~ s/\(\[\\x\{d800\}\-\\x\{dbff\}\]\)\(\[\\x\{dc00\}\-\\x\{dfff\}\]\)/
    chr 0x10000 \+ \(ord\($1\) \- 0xD800\) \* 0x400 \+
        \(ord\($2\) \- 0xDC00\)
/ge;
$x

};

$thing = bless [];
die $thing;
# die "$thing"; # this one works, because 'die' is not doing the
stringification

__END__

If I use s/[a-e]/b/g for the substitution, the bug is not triggered.
It's the [\x{d800}-\x{dbff}] that does it.

This bug exists in 5.9.4 as well as 5.8.8.

This is a really obscure bug--it took me a while to reproduce it. :-)

---

This is still a problem on blead...

#!/usr/bin/perl -lw

no warnings 'once';

use Carp 'longmess';
use overload '""' => sub {
  my @​z = @​_;
# warn longmess if ++$count == 10;

  my $x = "thing\n"; # any string will trigger the bug
  $x =~
  s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
  chr 0x10000 + (ord($1) - 0xD800) * 0x400 + (ord($2) - 0xDC00)
  /ge;
  $x;
};

$thing = bless [];
die $thing;
__END__

Doesn't segfault

#!/usr/bin/perl -lw

no warnings 'once';

use Carp 'longmess';
use overload '""' => sub {
  my @​z = @​_;
# warn longmess if ++$count == 10;

  my $x = "thing\n"; # any string will trigger the bug
  $x =~
  s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
  chr 0x10000 + (ord($1) - 0xD800) * 0x400 + (ord($2) - 0xDC00)
  /ge;
  $x;
};

my $x = "thing\n"; # any string will trigger the bug
$x =~ s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
  chr 0x10000 + (ord($1) - 0xD800) * 0x400 + (ord($2) - 0xDC00)
  /ge;
print $x;

$thing = bless [];
die $thing;
__END__

Does segfault

But​:

#!/usr/bin/perl -lw

my $x = "thing\n"; # any string will trigger the bug
$x =~ s/([\x{d800}-\x{dbff}])([\x{dc00}-\x{dfff}])/
  chr 0x10000 + (ord($1) - 0xD800) * 0x400 + (ord($2) - 0xDC00)
  /ge;
print $x;
__END__

Does not segfault.

Kind regards,

Bram

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

From @cpansprout

This was fixed by the die/eval cleanup in 5.14.0​:

There are only 'skip'ped commits left to test.
The first bad commit could be any of​:
7ce0928
99782e3
c5df309
62705b2
We cannot bisect more!
bisect run cannot continue any more
Died at ../perl.git/Porting/bisect.pl line 150.
That took 592 seconds

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

@cpansprout - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant