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

Segfault in Perl_vwarner (util.c:2051) #15824

Open
p5pRT opened this issue Jan 22, 2017 · 3 comments
Open

Segfault in Perl_vwarner (util.c:2051) #15824

p5pRT opened this issue Jan 22, 2017 · 3 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 22, 2017

Migrated from rt.perl.org#130621 (status was 'open')

Searchable as RT130621$

@p5pRT
Copy link
Author

p5pRT commented Jan 22, 2017

From @dur-randir

Created by @dur-randir

While fuzzing perl v5.25.8-216-gfbceb79751 built with afl and run
under libdislocator, I found the following program

eval q!$^D = 'C';0 =~ ~v1000 / 0!

to crash on debugging builds (as assigning to $^D is a no-op on
regular builds). This is a regression between v5.22.2 and v5.24.0,
bisect points to

4df352a is the first bad commit
commit 4df352a
Author​: David Mitchell <davem@​iabyn.com>
Date​: Mon Oct 12 14​:56​:35 2015 +0100

  reverse the order of POPBLOCK; POPFOO

  Currently most pp_leavefoo subs have something along the lines of

  POPBLOCK(cx);
  POPFOO(cx);

  where POPBLOCK does cxstack_ix-- and sets cx to point to the top CX stack
  entry. It then restores a bunch of PL_ vars saved in the CX struct.

  Then POPFOO does any type-specific restoration, e.g. POPSUB decrements the
  ref count of the cv that was just executed.

  However, this is logically the wrong order. When we *enter* a scope, we do

  PUSHBLOCK;
  PUSHFOO;

  so undoing the PUSHBLOCK should be the last thing we do. As it happens,
  it doesn't really make any difference to the running, which is why we've
  never fixed it before.

  Reordering it has two advantages.

  First, it allows the steps for scope exit to be the exact logical reverse
  of scope exit, which makes understanding what's going on and debugging
  easier.

  It allows us to make the code cleaner.

  This commit also removes the cxstack_ix-- and setting cx steps from
  POPBLOCK; now we already expect cx to be set (which it usually already is)
  and we do the cxstack_ix-- ourselves. This also means we can remove a
  whole bunch of cxstack_ix++'s that were added immediately after the
  POPBLOCK in order to prevent the context being inadvertently overwritten
  before we've finished using it.

  So in full,

  POPBLOCK(cx);
  POPFOO(cx);

  is now implemented as​:

  cx = &cxstack[cxstack_ix];
  ... other stuff done with cx ...
  POPFOO(cx);
  POPBLOCK(cx);
  cxstack_ix--;

  Finally, this commit also tweaks PL_curcop in pp_leaveeval, since
  otherwise PL_curcop could temporarily be NULL when debugging code is
  called in the presence of 'use re Debug'. It also stops the debugging code
  crashing if PL_curcop is still NULL.

GDB info about the crash location​:

#0 0x00007fbd1b8dc188 in Perl_vwarner (err=2, pat=0x7fbd1bb87876
"%s", args=0x7ffd2c784800) at util.c​:2050
2050 (PL_warnhook == PERL_WARNHOOK_FATAL || ckDEAD(err)) &&
(gdb) bt
#0 0x00007fbd1b8dc188 in Perl_vwarner (err=2, pat=0x7fbd1bb87876
"%s", args=0x7ffd2c784800) at util.c​:2050
#1 0x00007fbd1b8dc117 in Perl_warner (err=2, pat=0x7fbd1bb87876 "%s")
at util.c​:2040
#2 0x00007fbd1ba83105 in Perl_utf8n_to_uvchr_error (s=0x7fbd1d62528d
"", curlen=13, retlen=0x0, flags=0, errors=0x7ffd2c784918) at
utf8.c​:1700
#3 0x00007fbd1ba92f73 in Perl_pv_uni_display (dsv=0x7fbd1d61ba78,
spv=0x7fbd1d625280
"\377\200\217\277\277\277\277\277\277\277\277\260\227", len=13,
  pvlim=78, flags=3) at utf8.c​:5047
#4 0x00007fbd1ba933b8 in Perl_sv_uni_display (dsv=0x7fbd1d61ba78,
ssv=0x7fbd1d629ce0, pvlim=78, flags=3) at utf8.c​:5109
#5 0x00007fbd1b8cc3fa in Perl_do_sv_dump (level=0,
file=0x7fbd1d615620, sv=0x7fbd1d629ce0, nest=0, maxnest=0,
dumpops=false, pvlim=0) at dump.c​:1627
#6 0x00007fbd1b8d498f in Perl_sv_dump (sv=0x7fbd1d629ce0) at dump.c​:2219
#7 0x00007fbd1b9790c6 in Perl_sv_clear (orig_sv=0x7fbd1d629ce0) at sv.c​:6744
#8 0x00007fbd1b97b125 in Perl_sv_free2 (sv=0x7fbd1d629ce0, rc=1) at sv.c​:7061
#9 0x00007fbd1b859765 in S_SvREFCNT_dec (sv=0x7fbd1d629ce0) at inline.h​:189
#10 0x00007fbd1b8bc827 in Perl_pregfree2 (rx=0x7fbd1d61bfb8) at regcomp.c​:19330
#11 0x00007fbd1b977f72 in Perl_sv_clear (orig_sv=0x7fbd1d61bfb8) at sv.c​:6607
#12 0x00007fbd1b97b125 in Perl_sv_free2 (sv=0x7fbd1d61bfb8, rc=1) at sv.c​:7061
#13 0x00007fbd1b78ad4d in S_SvREFCNT_dec (sv=0x7fbd1d61bfb8) at inline.h​:189
#14 0x00007fbd1b78d848 in Perl_op_clear (o=0x7fbd1d625e20) at op.c​:1055
#15 0x00007fbd1b78d330 in Perl_op_free (o=0x7fbd1d625e20) at op.c​:855
#16 0x00007fbd1b9dd58d in Perl_leave_scope (base=0) at scope.c​:1109
#17 0x00007fbd1b9ec13b in S_pop_eval_context_maybe_croak
(cx=0x7fbd1d609fc0, errsv=0x7fbd1d629d10, action=2) at pp_ctl.c​:1613
#18 0x00007fbd1b9ecc66 in Perl_die_unwind (msv=0x7fbd1d629d10) at pp_ctl.c​:1741
#19 0x00007fbd1b8db690 in Perl_vcroak (pat=0x7fbd1bb5afa2 "Illegal
division by zero", args=0x7ffd2c786120) at util.c​:1805
#20 0x00007fbd1b8db3b5 in Perl_die (pat=0x7fbd1bb5afa2 "Illegal
division by zero") at util.c​:1736
#21 0x00007fbd1b9acd21 in Perl_pp_divide () at pp.c​:1554
#22 0x00007fbd1b8d4bde in Perl_runops_debug () at dump.c​:2260
#23 0x00007fbd1b7cf156 in S_run_body (oldscope=1) at perl.c​:2528
#24 0x00007fbd1b7ce6d4 in perl_run (my_perl=0x7fbd1d605010) at perl.c​:2451
#25 0x00007fbd1b789d3e in main (argc=2, argv=0x7ffd2c786608,
env=0x7ffd2c786620) at perlmain.c​:123
(gdb) p PL_curcop->cop_warnings
Cannot access memory at address 0x40

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.25.9:

Configured by root at Sat Jan 14 02:25:05 MSK 2017.

Summary of my perl5 (revision 5 version 25 subversion 9) configuration:
  Commit id: cbe2fc5001aa59cdc73e04cc35e097a2ecfbeec0
  Platform:
    osname=linux
    osvers=3.16.0-4-amd64
    archname=x86_64-linux
    uname='linux dorothy 3.16.0-4-amd64 #1 smp debian 3.16.36-1+deb8u2
(2016-10-19) x86_64 gnulinux '
    config_args='-des -Dusedevel -DDEBUGGING -Dcc=afl-clang-fast
-Doptimize=-O0 -g -ggdb3'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    bincompat5005=undef
  Compiler:
    cc='afl-clang-fast'
    ccflags ='-DDEBUGGING -fno-strict-aliasing -pipe
-fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-O0 -g -ggdb3'
    cppflags='-DDEBUGGING -fno-strict-aliasing -pipe
-fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.2.1 Compatible Clang 3.9.1 (tags/RELEASE_391/rc2)'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='afl-clang-fast'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/llvm-3.9/bin/../lib/clang/3.9.1/lib
/usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu
/lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.24.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.24'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags='-shared -O0 -g -ggdb3 -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.25.9:
    lib
    /usr/local/lib/perl5/site_perl/5.25.9/x86_64-linux
    /usr/local/lib/perl5/site_perl/5.25.9
    /usr/local/lib/perl5/5.25.9/x86_64-linux
    /usr/local/lib/perl5/5.25.9


Environment for perl 5.25.9:
    HOME=/home/afl
    LANG=en_US.UTF-8
    LANGUAGE=en_US:en
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/afl/perlbrew/bin:/home/afl/perlbrew/perls/perl-5.22.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERLBREW_BASHRC_VERSION=0.78
    PERLBREW_HOME=/home/afl/.perlbrew
    PERLBREW_MANPATH=/home/afl/perlbrew/perls/perl-5.22.1/man
    PERLBREW_PATH=/home/afl/perlbrew/bin:/home/afl/perlbrew/perls/perl-5.22.1/bin
    PERLBREW_PERL=perl-5.22.1
    PERLBREW_ROOT=/home/afl/perlbrew
    PERLBREW_VERSION=0.78
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Jan 23, 2017

From @iabyn

On Sun, Jan 22, 2017 at 01​:10​:42PM -0800, Sergey Aleynikov wrote​:

While fuzzing perl v5.25.8-216-gfbceb79751 built with afl and run
under libdislocator, I found the following program

eval q!$^D = 'C';0 =~ ~v1000 / 0!

to crash on debugging builds (as assigning to $^D is a no-op on
regular builds). This is a regression between v5.22.2 and v5.24.0,
bisect points to

I've fixed the proximate cause with the following two commits; the deeper
eval fix I'll leave till later.

commit b1a69a6
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Mon Jan 23 13​:27​:07 2017 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Mon Jan 23 13​:52​:36 2017 +0000

  ckDEAD​: PL_curcop->cop_warnings only if PL_curcop
 
  RT #130621
 
  In ckDEAD(), don't check the value of PL_curcop->cop_warnings unless
  PL_curcop is non-null.
 
  In the ticket above, the reason that PL_curcop is null is the less
  than optimal way that evals free their optree​: ideally the optree should
  be attached to the eval CV and freed when the CV is; instead a separate
  SAVEFREEOP() is done. But that fix is for another time; regardless,
  ckDEAD() should have a PL_curcop != NULL guard anyway like isLEXWARN_on()
  etc already do.

commit f4c6177
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Mon Jan 23 13​:37​:21 2017 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Mon Jan 23 13​:52​:36 2017 +0000

  mess_sv()​: access only if PL_curcop is non-null
 
  RT #130621
 
  In Perl_mess_sv(), don't try to add an "at foo line NN" to the error
  message if PL_curcop is null.
 
  In the ticket above, the reason that PL_curcop is null is the less
  than optimal way that evals free their optree​: ideally the optree should
  be attached to the eval CV and freed when the CV is; instead a separate
  SAVEFREEOP() is done. But that fix is for another time; regardless,
  mess_sv() should have a PL_curcop != NULL guard anyway.

--
This email is confidential, and now that you have read it you are legally
obliged to shoot yourself. Or shoot a lawyer, if you prefer. If you have
received this email in error, place it in its original wrapping and return
for a full refund. By opening this email, you accept that Elvis lives.

@p5pRT
Copy link
Author

p5pRT commented Jan 23, 2017

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

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

No branches or pull requests

2 participants