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

SEGV reading through null HEK* in hv_ename_add #14512

Closed
p5pRT opened this issue Feb 16, 2015 · 8 comments
Closed

SEGV reading through null HEK* in hv_ename_add #14512

p5pRT opened this issue Feb 16, 2015 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 16, 2015

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

Searchable as RT123847$

@p5pRT
Copy link
Author

p5pRT commented Feb 16, 2015

From @hvds

AFL (<http​://lcamtuf.coredump.cx/afl/>) finds this​:

% ./miniperl -e '%0=*​:=*​::​::=0'
Segmentation fault (core dumped)
%

The code looks similar to the glob overwriting cases in [perl #123710], but the failure mode is quite different​:

Program received signal SIGSEGV, Segmentation fault.
0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108, name=0xa62460 "​:",
  len=1, flags=0) at hv.c​:2342
2342 (HEK_UTF8(*hekp) || (flags & SVf_UTF8))
(gdb) where
#0 0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108, name=0xa62460 "​:",
  len=1, flags=0) at hv.c​:2342
#1 0x000000000055a651 in S_mro_gather_and_rename (stashes=0xa557c0,
  seen_stashes=0xa55790, stash=0xa56108, oldstash=0x0, namesv=0xa61400)
  at mro.c​:992
#2 0x000000000055953b in Perl_mro_package_moved (stash=0xa56108,
  oldstash=0x0, gv=0xa613e8, flags=0) at mro.c​:844
#3 0x00000000005a9e33 in S_glob_assign_glob (dstr=0xa613e8, sstr=0xa61418,
  dtype=9) at sv.c​:4005
#4 0x00000000005afa88 in Perl_sv_setsv_flags (dstr=0xa613e8, sstr=0xa61418,
  flags=1538) at sv.c​:4426
#5 0x0000000000574add in Perl_pp_sassign () at pp_hot.c​:231
#6 0x000000000052a13d in Perl_runops_debug () at dump.c​:2231
#7 0x00000000004098c7 in S_run_body (oldscope=1) at perl.c​:2423
#8 0x0000000000408f0b in perl_run (my_perl=0xa40010) at perl.c​:2346
#9 0x00000000004508d1 in main (argc=3, argv=0x7fffffffe638,
  env=0x7fffffffe658) at miniperlmain.c​:122
(gdb) p hekp
$1 = (HEK **) 0xa5f820
(gdb) p *hekp
$2 = (HEK *) 0x0
(gdb) p /x *hv
$3 = {sv_any = 0xa47ec0, sv_refcnt = 0x1, sv_flags = 0x3200000c, sv_u = {
  svu_pv = 0xa59150, svu_iv = 0xa59150, svu_uv = 0xa59150, svu_nv = 0x0,
  svu_rv = 0xa59150, svu_rx = 0xa59150, svu_array = 0xa59150,
  svu_hash = 0xa59150, svu_gp = 0xa59150, svu_fp = 0xa59150}}
(gdb) p *aux
$4 = {xhv_name_u = {xhvnameu_name = 0xa5f820, xhvnameu_names = 0xa5f820},
  xhv_backreferences = 0x0, xhv_eiter = 0x0, xhv_riter = -1,
  xhv_name_count = -2, xhv_mro_meta = 0xa5f4e0, xhv_rand = 1738015991,
  xhv_last_rand = 1738015991, xhv_fill_lazy = 0, xhv_aux_flags = 0}
(gdb) p aux->xhv_name_u.xhvnameu_names[0]@​2
$5 = {0x0, 0xa4d368}

Not sure what's supposed to be happening here - the else branch (when not aux->xhv_name_count) clearly knows when it stores existing_name to xhvnameu_names[0] that it might be NULL, that's why our name_count is -2, so how can it be right to loop as far as xhvnameu_names[0] in the if branch?

Hugo

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2015

From @cpansprout

On Mon Feb 16 04​:37​:51 2015, hv wrote​:

AFL (<http​://lcamtuf.coredump.cx/afl/>) finds this​:

% ./miniperl -e '%0=*​:=*​::​::=0'
Segmentation fault (core dumped)
%

The code looks similar to the glob overwriting cases in [perl
#123710], but the failure mode is quite different​:

Program received signal SIGSEGV, Segmentation fault.
0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108, name=0xa62460
"​:",
len=1, flags=0) at hv.c​:2342
2342 (HEK_UTF8(*hekp) || (flags & SVf_UTF8))
(gdb) where
#0 0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108,
name=0xa62460 "​:",
len=1, flags=0) at hv.c​:2342
#1 0x000000000055a651 in S_mro_gather_and_rename (stashes=0xa557c0,
seen_stashes=0xa55790, stash=0xa56108, oldstash=0x0,
namesv=0xa61400)
at mro.c​:992
#2 0x000000000055953b in Perl_mro_package_moved (stash=0xa56108,
oldstash=0x0, gv=0xa613e8, flags=0) at mro.c​:844
#3 0x00000000005a9e33 in S_glob_assign_glob (dstr=0xa613e8,
sstr=0xa61418,
dtype=9) at sv.c​:4005
#4 0x00000000005afa88 in Perl_sv_setsv_flags (dstr=0xa613e8,
sstr=0xa61418,
flags=1538) at sv.c​:4426
#5 0x0000000000574add in Perl_pp_sassign () at pp_hot.c​:231
#6 0x000000000052a13d in Perl_runops_debug () at dump.c​:2231
#7 0x00000000004098c7 in S_run_body (oldscope=1) at perl.c​:2423
#8 0x0000000000408f0b in perl_run (my_perl=0xa40010) at perl.c​:2346
#9 0x00000000004508d1 in main (argc=3, argv=0x7fffffffe638,
env=0x7fffffffe658) at miniperlmain.c​:122
(gdb) p hekp
$1 = (HEK **) 0xa5f820
(gdb) p *hekp
$2 = (HEK *) 0x0
(gdb) p /x *hv
$3 = {sv_any = 0xa47ec0, sv_refcnt = 0x1, sv_flags = 0x3200000c, sv_u
= {
svu_pv = 0xa59150, svu_iv = 0xa59150, svu_uv = 0xa59150, svu_nv =
0x0,
svu_rv = 0xa59150, svu_rx = 0xa59150, svu_array = 0xa59150,
svu_hash = 0xa59150, svu_gp = 0xa59150, svu_fp = 0xa59150}}
(gdb) p *aux
$4 = {xhv_name_u = {xhvnameu_name = 0xa5f820, xhvnameu_names =
0xa5f820},
xhv_backreferences = 0x0, xhv_eiter = 0x0, xhv_riter = -1,
xhv_name_count = -2, xhv_mro_meta = 0xa5f4e0, xhv_rand =
1738015991,
xhv_last_rand = 1738015991, xhv_fill_lazy = 0, xhv_aux_flags = 0}
(gdb) p aux->xhv_name_u.xhvnameu_names[0]@​2
$5 = {0x0, 0xa4d368}

Not sure what's supposed to be happening here - the else branch (when
not aux->xhv_name_count) clearly knows when it stores existing_name to
xhvnameu_names[0] that it might be NULL, that's why our name_count is
-2, so how can it be right to loop as far as xhvnameu_names[0] in the
if branch?

Bisect​:

1f656fc is the first bad commit
commit 1f656fc
Author​: Father Chrysostomos <sprout@​cpan.org>
Date​: Fri Apr 15 22​:33​:31 2011 -0700

  Followup to 088225f/[perl #88132]​: packages ending with :

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Mar 12, 2015

From @cpansprout

On Mon Mar 02 22​:09​:39 2015, sprout wrote​:

On Mon Feb 16 04​:37​:51 2015, hv wrote​:

AFL (<http​://lcamtuf.coredump.cx/afl/>) finds this​:

% ./miniperl -e '%0=*​:=*​::​::=0'
Segmentation fault (core dumped)
%

The code looks similar to the glob overwriting cases in [perl
#123710], but the failure mode is quite different​:

Program received signal SIGSEGV, Segmentation fault.
0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108, name=0xa62460
"​:",
len=1, flags=0) at hv.c​:2342
2342 (HEK_UTF8(*hekp) || (flags & SVf_UTF8))
(gdb) where
#0 0x000000000056afbc in Perl_hv_ename_add (hv=0xa56108,
name=0xa62460 "​:",
len=1, flags=0) at hv.c​:2342
#1 0x000000000055a651 in S_mro_gather_and_rename (stashes=0xa557c0,
seen_stashes=0xa55790, stash=0xa56108, oldstash=0x0,
namesv=0xa61400)
at mro.c​:992
#2 0x000000000055953b in Perl_mro_package_moved (stash=0xa56108,
oldstash=0x0, gv=0xa613e8, flags=0) at mro.c​:844
#3 0x00000000005a9e33 in S_glob_assign_glob (dstr=0xa613e8,
sstr=0xa61418,
dtype=9) at sv.c​:4005
#4 0x00000000005afa88 in Perl_sv_setsv_flags (dstr=0xa613e8,
sstr=0xa61418,
flags=1538) at sv.c​:4426
#5 0x0000000000574add in Perl_pp_sassign () at pp_hot.c​:231
#6 0x000000000052a13d in Perl_runops_debug () at dump.c​:2231
#7 0x00000000004098c7 in S_run_body (oldscope=1) at perl.c​:2423
#8 0x0000000000408f0b in perl_run (my_perl=0xa40010) at perl.c​:2346
#9 0x00000000004508d1 in main (argc=3, argv=0x7fffffffe638,
env=0x7fffffffe658) at miniperlmain.c​:122
(gdb) p hekp
$1 = (HEK **) 0xa5f820
(gdb) p *hekp
$2 = (HEK *) 0x0
(gdb) p /x *hv
$3 = {sv_any = 0xa47ec0, sv_refcnt = 0x1, sv_flags = 0x3200000c, sv_u
= {
svu_pv = 0xa59150, svu_iv = 0xa59150, svu_uv = 0xa59150, svu_nv =
0x0,
svu_rv = 0xa59150, svu_rx = 0xa59150, svu_array = 0xa59150,
svu_hash = 0xa59150, svu_gp = 0xa59150, svu_fp = 0xa59150}}
(gdb) p *aux
$4 = {xhv_name_u = {xhvnameu_name = 0xa5f820, xhvnameu_names =
0xa5f820},
xhv_backreferences = 0x0, xhv_eiter = 0x0, xhv_riter = -1,
xhv_name_count = -2, xhv_mro_meta = 0xa5f4e0, xhv_rand =
1738015991,
xhv_last_rand = 1738015991, xhv_fill_lazy = 0, xhv_aux_flags = 0}
(gdb) p aux->xhv_name_u.xhvnameu_names[0]@​2
$5 = {0x0, 0xa4d368}

Not sure what's supposed to be happening here - the else branch (when
not aux->xhv_name_count) clearly knows when it stores existing_name to
xhvnameu_names[0] that it might be NULL, that's why our name_count is
-2, so how can it be right to loop as far as xhvnameu_names[0] in the
if branch?

Bisect​:

1f656fc is the first bad commit
commit 1f656fc
Author​: Father Chrysostomos <sprout@​cpan.org>
Date​: Fri Apr 15 22​:33​:31 2011 -0700

Followup to 088225f/\[perl \#88132\]&#8203;: packages ending with :

Here is a clearer example, which goes back to 5.14​:

$ ./miniperl -e '%0; *bar​::=*foo​::=0'

The %0 hash needs to be vivified beforehand, and the two globs assigned to need to be stash globs (fq names ending in :​:).

The logic in hv_ename_add is wrong, and probably has been so since I wrote it.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Mar 12, 2015

From @cpansprout

Fixed in 3d50185.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Mar 12, 2015

@cpansprout - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented Jun 2, 2015

From @khwilliamson

Thank you for submitting this ticket.

The issue should now be resolved with the release today of Perl v5.22, which is available at http​://www.perl.org/get.html
--
Karl Williamson for the Perl 5 team

@p5pRT
Copy link
Author

p5pRT commented Jun 2, 2015

@khwilliamson - Status changed from 'pending release' 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