possible snprintf() regression in 3.3.2

Tony Cook tony@develop-help.com
Wed Nov 17 00:37:18 GMT 2021


This came up from regression testing perl.

Regression testing of perl @4a1b9dd524007193213d3919d6a331109608b90c
used (from uname):

 cygwin_nt-10.0 fv-az177-186 3.3.1(0.34153) 2021-10-28 20:52 x86_64 cygwin

this did not exhibit the problem.  See https://github.com/Perl/perl5/runs/4084168038?check_suite_focus=true

Testing of perl @a85e04e2281234a61c051f8f3ff63bed7381902c, the next
commit, which is purely a documentation change did exhibit the bug, used:

  cygwin_nt-10.0 fv-az177-290 3.3.2(0.34153) 2021-11-08 16:55 x86_64 cygwin

which did crash.  See https://github.com/Perl/perl5/runs/4159124596?check_suite_focus=true

snprintf() appears to be crashing internally to ldtoa_r(), without
cygwin-debuginfo the backtrace is:

Thread 1 "perl" received signal SIGSEGV, Segmentation fault.
0x00007ffd26b21548 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
(gdb) bt
#0  0x00007ffd26b21548 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#1  0x00007ffd26b21040 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#2  0x00007ffd26b20e7b in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#3  0x00007ffd26b413a8 in ntdll!RtlRaiseException ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#4  0x00007ffd26b90bfe in ntdll!KiUserExceptionDispatcher ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#5  0x00000001801fec7c in eiremain () from /usr/bin/cygwin1.dll
#6  0x0000000180200319 in _ldtoa_r () from /usr/bin/cygwin1.dll
#7  0x00000001801cfca9 in _svfprintf_r () from /usr/bin/cygwin1.dll
#8  0x00000001801bf327 in snprintf () from /usr/bin/cygwin1.dll
#9  0x000000018018eb0b in _sigfe () from /usr/bin/cygwin1.dll
#10 0x0000000052162647 in Perl_sv_vcatpvfn_flags (my_perl=0x80004a3e0,
    sv=0x800ca9e78, pat=0x523a3501 <regexp_core_intflags_names+4769> "%.9f",
    patlen=4, args=0xffffc550, svargs=0x0, sv_count=0, maybe_tainted=0x0,
    flags=0) at sv.c:13482
#11 0x000000005215e360 in Perl_sv_vsetpvfn (my_perl=0x80004a3e0,
    sv=0x800ca9e78, pat=0x523a3501 <regexp_core_intflags_names+4769> "%.9f",
    patlen=4, args=0xffffc550, svargs=0x0, sv_count=0, maybe_tainted=0x0)
    at sv.c:11271
#12 0x000000005215dde9 in Perl_sv_vsetpvf (my_perl=0x80004a3e0,
    sv=0x800ca9e78, pat=0x523a3501 <regexp_core_intflags_names+4769> "%.9f",
    args=0xffffc550) at sv.c:11101
#13 0x000000005215dd6a in Perl_sv_setpvf (my_perl=0x80004a3e0, sv=0x800ca9e78,
    pat=0x523a3501 <regexp_core_intflags_names+4769> "%.9f") at sv.c:11076
#14 0x000000005210aa74 in Perl_upg_version (my_perl=0x80004a3e0,
    ver=0x800cacb00, qv=false) at /home/tony/dev/perl/git/perl/vutil.c:700
#15 0x00000000520440a4 in XS_universal_version (my_perl=0x80004a3e0,
    cv=0x80004dfa0) at /home/tony/dev/perl/git/perl/vxs.inc:122
#16 0x0000000052142b10 in Perl_pp_entersub (my_perl=0x80004a3e0)
    at pp_hot.c:5361
#17 0x00000000521318e7 in Perl_runops_standard (my_perl=0x80004a3e0)
    at run.c:41
#18 0x00000000520376ff in S_run_body (my_perl=0x80004a3e0, oldscope=1)
    at perl.c:2715
#19 0x0000000052037214 in perl_run (my_perl=0x80004a3e0) at perl.c:2643
#20 0x000000010040117c in main (argc=4, argv=0xffffcc00, env=0x8000281a0)
    at perlmain.c:110

With cygwin-debuginfo installed the backtrace is:

Thread 1 "perl" received signal SIGSEGV, Segmentation fault.
0x00007ffd26b21548 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
(gdb) bt
#0  0x00007ffd26b21548 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#1  0x00007ffd26b21040 in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#2  0x00007ffd26b20e7b in ntdll!RtlVirtualUnwind ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#3  0x00007ffd26b413a8 in ntdll!RtlRaiseException ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#4  0x00007ffd26b90bfe in ntdll!KiUserExceptionDispatcher ()
   from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
#5  0x00000001801fec7c in eiremain (den=0x1, num=0x0, ldp=0x5)
    at /usr/src/debug/cygwin-3.3.2-1/newlib/libc/stdlib/ldtoa.c:3736
#6  0x00000001802bb0b0 in etens () from /usr/bin/cygwin1.dll
#7  0x00000000ffffbac2 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

The stack appears to be badly corrupted (etens isn't a function).

Unfortunately I haven't been able to make a simple pure C reproducer
for this.

To reproduce:

Fetch and build perl (needs make, gcc):

   $ git clone https://github.com/Perl/perl5.git
   $ cd perl5
   $ ./Configure -des -Dusedevel -Doptimize=-O0\ -g
   # adjust -j6 to the desired parallel jobs
   $ make -j6 test-prep

reproducing the original failure:

  $ cd t ; gdb --args ./perl -I.. -MTestInit ../cpan/version/t/01base.t

a simpler test case, with some debugging:

  $ echo '$Foo::VERSION = 9.e99; eval { Foo->VERSION(9e99) }' >mytest.pl
  $ gdb --args ./perl mytest.pl
  ...
  Reading symbols from ./perl...
  (gdb) b vutil.c:700
  No source file named vutil.c.
  Make breakpoint pending on future shared library load? (y or [n]) y
  Breakpoint 1 (vutil.c:700) pending.
  (gdb) r
  Starting program: /home/tony/dev/perl/git/perl/perl mytest.pl
  [New Thread 16120.0x3a54]
  [New Thread 16120.0x3368]
  [New Thread 16120.0x134]
  [New Thread 16120.0x133c]

  Thread 1 "perl" hit Breakpoint 1, Perl_upg_version (my_perl=0x80004a3b0,
      ver=0x800090c98, qv=false) at /home/tony/dev/perl/git/perl/vutil.c:700
  700                     Perl_sv_setpvf(aTHX_ sv, "%.9" NVff, SvNVX(ver));
  (gdb) b sv.c:13482
  Breakpoint 2 at 0x521624f6: file sv.c, line 13482.
  (gdb) c
  Continuing.

  Thread 1 "perl" hit Breakpoint 2, Perl_sv_vcatpvfn_flags (my_perl=0x80004a3b0,
      sv=0x800090c80, pat=0x523a3501 <regexp_core_intflags_names+4769> "%.9f",
      patlen=4, args=0xffffc580, svargs=0x0, sv_count=0, maybe_tainted=0x0,
      flags=0) at sv.c:13482
  13482                   WITH_LC_NUMERIC_SET_TO_NEEDED_IN(in_lc_numeric,
  (gdb) p my_perl->Iefloatbuf
  $1 = 0x80009b540 ""
  (gdb) p my_perl->Iefloatsize
  $2 = 177
  (gdb) p ptr
  $3 = 0xffffc44a "%.9f"
  (gdb) p fv
  $4 = 8.99999999999999994886e+99
  (gdb) c
  Continuing.
  [New Thread 16120.0x3a98]
  [New Thread 16120.0x1c3c]

  Thread 1 "perl" received signal SIGSEGV, Segmentation fault.
  0x00007ffd26b21548 in ntdll!RtlVirtualUnwind ()
     from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll

The code at sv.c:13482 is 13482 is:

                WITH_LC_NUMERIC_SET_TO_NEEDED_IN(in_lc_numeric,
                    elen = ((intsize == 'q')
                            ? my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, fv)
                            : my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, (double)fv))
                );

Given the macro definitions and value of intsize at this point, this
becomes a call to snprintf:

  snprintf(my_perl->Iefloatbuf, my_perl->Iefloatsize, ptr, (double)fv)

I suspect

  https://cygwin.com/git/?p=newlib-cygwin.git;a=commit;h=4d90e5335914551862831de3e02f6c102b78435b

but I'm not really setup to build and debug cygwin.

Tony


More information about the Cygwin mailing list