Skip to content

VS2022 Test ext/XS-APItest/t/clone-with-stack.t randomly causes "perl.exe has stopped working" in perl 5.39.7 #21969

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

Closed
twata1 opened this issue Feb 10, 2024 · 10 comments

Comments

@twata1
Copy link
Contributor

twata1 commented Feb 10, 2024

Description

I'm building Perl 5.39.7 on Windows 8.1 64 bit using Visual Studio 2022 Community Edition (Microsoft(R) C/C++ Optimizing Compiler Version 19.33.31630 for x64).

The compilation itself is successful, although several types of warnings are outputed (e.g. C4244, C4267, etc.).
The tests themselves are successful when running nmake test. However, It seems to me that ext/XS-APItest/t/clone-with-stack.t randomly causes "perl.exe has stopped working" (See the following image.).

XS-APItest-t-clone-with-stack-t

Steps to Reproduce

Download perl-5.39.7.tar.gz from metacpan (https://metacpan.org/release/CORION/perl-5.39.7).
Extract from perl-5.39.7.tar.gz to C:\VCPerl64.
Open C:\VCPerl64\perl-5.39.7\win32\Makefile in your editor and edit as follows.

INST_TOP	= $(INST_DRV)\perl64
INST_VER	= \5.39.7
# Visual C++ 2022 (aka Visual C++ 14.3) (full version or Community Edition)
CCTYPE		= MSVC143

Launch "x64 Native Tools Command Prompt for VS 2022" from the Start menu.
On that Command Prompt, run the following.

cd C:\VCPerl64\perl-5.39.7\win32
nmake

After nmake is finished , cd ..\ext\XS-APItest and run the following about 3 or 4 times.

..\..\perl -I..\..\lib t\clone-with-stack.t

Expected behavior

do not cause "perl.exe has stopped working"

Perl configuration

C:\VCPerl64\perl-5.39.7>perl -V
Summary of my perl5 (revision 5 version 39 subversion 7) configuration:
   
  Platform:
    osname=MSWin32
    osvers=6.3.9600
    archname=MSWin32-x64-multi-thread
    uname=''
    config_args='undef'
    hint=recommended
    useposix=true
    d_sigaction=undef
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
  Compiler:
    cc='cl'
    ccflags ='-nologo -GF -W3 -MD -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -D_CRT_SECURE_NO_DEPRECATE  -D_CRT_NONSTDC_NO_DEPRECATE -D_WINSOCK_DEPRECATED_NO_WARNINGS  -DPERL_TEXTMODE_SCRIPTS -DMULTIPLICITY -DPERL_IMPLICIT_SYS'
    optimize='-O1 -Zi -GL -fp:precise'
    cppflags='-DWIN32'
    ccversion='19.33.31630'
    gccversion=''
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=undef
    longlongsize=8
    d_longdbl=define
    longdblsize=8
    longdblkind=0
    ivtype='__int64'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='__int64'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='link'
    ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -ltcg  -libpath:"c:\perl64\5.39.7\lib\CORE"  -machine:AMD64 -subsystem:console,"5.02"'
    libpth="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\\lib\x64"
    libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib vcruntime.lib ucrt.lib
    perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib vcruntime.lib ucrt.lib
    libc=ucrt.lib
    so=dll
    useshrplib=true
    libperl=perl539.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs
    dlext=dll
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -ltcg  -libpath:"c:\perl64\5.39.7\lib\CORE"  -machine:AMD64 -subsystem:console,"5.02"'


Characteristics of this binary (from libperl): 
  Compile-time options:
    HAS_LONG_DOUBLE
    HAS_TIMES
    HAVE_INTERP_INTERN
    MULTIPLICITY
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_HASH_FUNC_SIPHASH13
    PERL_HASH_USE_SBOX32
    PERL_IMPLICIT_SYS
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_SAFE_PUTENV
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
    USE_THREAD_SAFE_LOCALE
  Built under MSWin32
  Compiled at Feb 11 2024 04:49:26
  @INC:
    C:/VCPerl64/perl-5.39.7/lib

@jkeenan
Copy link
Contributor

jkeenan commented Feb 10, 2024

We have not received any other recent reports of test failures in https://perl5.test-smoke.org/matrix (per https://perl5.test-smoke.org/matrix).

Did you experience these failures with earlier perl releases, e.g., perl-5.39.6 or perl-5.38.1?

I see from this statement from Microsoft that Windows 8.1 was EOLed on January 10, 2023. My feeling is that we should not be concerned about random test failures on obsolete Windows systems unless we can reproduce them on versions that MS is supporting.

@twata1
Copy link
Contributor Author

twata1 commented Feb 10, 2024

Did you experience these failures with earlier perl releases, e.g., perl-5.39.6 or perl-5.38.1?

No. So I just tried the same thing with Perl 5.39.6 and it reproduces.
I only had experience of building up to perl 5.38.0 RC1, but I can reproduce it in perl 5.38.0 RC1.
I was not aware of it.

@sisyphus
Copy link
Contributor

I can't reproduce the issue on Windows 11 (Microsoft Windows [Version 10.0.22621.3007], using the same version of VS2022 (Microsoft (R) C/C++ Optimizing Compiler Version 19.33.31630 for x64).

Does running ....\perl -I....\lib t\clone-with-stack.t give an indication of the point at which the crash occurs ?
For me, test 3 of clone-with-stack.t is a failing #TODO test:

not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 1280

And I'm wondering if the crash is associated with that failing test ?

@twata1
Copy link
Contributor Author

twata1 commented Feb 11, 2024

Does running ....\perl -I....\lib t\clone-with-stack.t give an indication of the point at which the crash occurs ?

To me, it appears to occur at the test 3 of clone-with-stack.t.
Please have a look at the images below when the test was run twice (First success, second crash.).
try-2times-in-perl-5 39 7

The results of the above are as follows.

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 65280
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>

Edit:
Sorry, I built and tried again after setting the PATH environment variable to only the PATH that would be relevant to Visual Studio and Windows system.
path.txt

The STATUS value changed as follows, but crashes randomly.

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 1280
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>

Thank you,

@sisyphus
Copy link
Contributor

Could @iabyn take a look at this.
This test was also a failing #TODO for me back in perl-5.38.0, too - but there have been some changes made to the clone_with_stack() XSub since then.
Maybe those changes are enough to trigger the crash ?

Finding a fix for these sorts of things is a bit beyond me.
All I can suggest is that the test be skipped if $Config{cc} is cl.

@twata, I suppose that one thing you could do is to remove that failing test, and see if that prevents the crash:

--- t/clone-with-stack.t_orig	2024-01-15 01:39:54.000000000 +1100
+++ t/clone-with-stack.t	2024-02-11 17:34:43.511632400 +1100
@@ -17,7 +17,7 @@
     skip_all("clone_with_stack requires threads");
 }
 
-plan(8);
+plan(7);
 
 fresh_perl_is( <<'----', <<'====', undef, "minimal clone_with_stack" );
 use XS::APItest;
@@ -38,19 +38,19 @@
 ok
 ====
 
-{
-    local our $TODO = "clone_with_stack inside a begin block";
-    fresh_perl_is( <<'----', <<'====', undef, "inside a BEGIN block" );
-use XS::APItest;
-BEGIN {
-    clone_with_stack();
-}
-print "ok\n";
-----
-ok
-====
-
-}
+#{
+#    local our $TODO = "clone_with_stack inside a begin block";
+#    fresh_perl_is( <<'----', <<'====', undef, "inside a BEGIN block" );
+#use XS::APItest;
+#BEGIN {
+#    clone_with_stack();
+#}
+#print "ok\n";
+#----
+#ok
+#====
+#
+#}
 
 {
     fresh_perl_is( <<'----', <<'====', undef, "clone stack" );

@twata1
Copy link
Contributor Author

twata1 commented Feb 11, 2024

@sisyphus
Thank you for providing the patch.
It has been tried 12 times as follows and it does not crash.

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..7
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
ok 3 - clone stack
ok 4 - with a lexical sub
ok 5 - with localised stuff
ok 6 - inside a loop inside a fn
ok 7 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>

Thank you,

@xenu
Copy link
Member

xenu commented Feb 11, 2024

That test launches a separate interpreter which crashes. Since the test is marked as TODO, it doesn't cause a failure.

It's a TODO test because pseudofork inside BEGIN blocks is documented as broken. That being said, it probably shouldn't crash.

Here's what ASAN says about the crash:

=================================================================
==2876==ERROR: AddressSanitizer: heap-use-after-free on address 0x1198ef1a8954 at pc 0x7ff8338de3b1 bp 0x000165b387b0 sp 0x000165b387b0
READ of size 4 at 0x1198ef1a8954 thread T0
    #0 0x7ff8338de3b0 in Perl_call_list C:\Users\xenu\Documents\git\perl5\win32\perl.c:5266
    #1 0x7ff8338eab7d in perl_destruct C:\Users\xenu\Documents\git\perl5\win32\perl.c:662
    #2 0x7ff8382e8ec7 in XS_XS__APItest_clone_with_stack C:\Users\xenu\Documents\git\perl5\ext\XS-APItest\APItest.xs:4259
    #3 0x7ff8339d3678 in Perl_rpp_invoke_xs C:\Users\xenu\Documents\git\perl5\inline.h:1193
    #4 0x7ff8339e401f in Perl_pp_entersub C:\Users\xenu\Documents\git\perl5\pp_hot.c:6497
    #5 0x7ff833c45915 in Perl_runops_standard C:\Users\xenu\Documents\git\perl5\run.c:41
    #6 0x7ff8338e05da in Perl_call_sv C:\Users\xenu\Documents\git\perl5\win32\perl.c:3216
    #7 0x7ff8338de8e0 in Perl_call_list C:\Users\xenu\Documents\git\perl5\win32\perl.c:5295
    #8 0x7ff83388ef6f in S_process_special_blocks C:\Users\xenu\Documents\git\perl5\win32\op.c:11279
    #9 0x7ff83383c7a1 in Perl_newATTRSUB_x C:\Users\xenu\Documents\git\perl5\win32\op.c:11115
    #10 0x7ff83390720a in Perl_yyparse C:\Users\xenu\Documents\git\perl5\win32\perly.y:370
    #11 0x7ff8338fe058 in S_parse_body C:\Users\xenu\Documents\git\perl5\win32\perl.c:2672
    #12 0x7ff8338f0f9e in perl_parse C:\Users\xenu\Documents\git\perl5\win32\perl.c:1912
    #13 0x7ff833df6a74 in RunPerl C:\Users\xenu\Documents\git\perl5\win32\perllib.c:196
    #14 0x7ff7e18b1048 in main C:\Users\xenu\Documents\git\perl5\win32\perlmain.c:39
    #15 0x7ff7e18b36df in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #16 0x7ff7e18b36df in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #17 0x7ff8613a7343  (C:\Windows\System32\KERNEL32.DLL+0x180017343)
    #18 0x7ff8616e26b0  (C:\Windows\SYSTEM32\ntdll.dll+0x1800526b0)

0x1198ef1a8954 is located 468 bytes inside of 576-byte region [0x1198ef1a8780,0x1198ef1a89c0)
freed by thread T0 here:
    #0 0x7ff8327a2408 in free D:\a\_work\1\s\src\vctools\asan\llvm\compiler-rt\lib\asan\asan_malloc_win.cpp:230
    #1 0x7ff833df828d in VMem::Free(void *) C:\Users\xenu\Documents\git\perl5\win32\vmem.h:229
    #2 0x7ff833e07e05 in CPerlHost::FreeShared(void *) C:\Users\xenu\Documents\git\perl5\win32\perlhost.h:98
    #3 0x7ff833e01114 in PerlMemSharedFree(struct IPerlMem *, void *) C:\Users\xenu\Documents\git\perl5\win32\perlhost.h:357
    #4 0x7ff83386636e in Perl_opslab_free C:\Users\xenu\Documents\git\perl5\win32\op.c:558
    #5 0x7ff8338660f5 in Perl_opslab_force_free C:\Users\xenu\Documents\git\perl5\win32\op.c:606
    #6 0x7ff8338adb1c in Perl_cv_undef_flags C:\Users\xenu\Documents\git\perl5\pad.c:352
    #7 0x7ff8338ad0cf in Perl_cv_undef C:\Users\xenu\Documents\git\perl5\pad.c:300
    #8 0x7ff833c76faa in Perl_sv_clear C:\Users\xenu\Documents\git\perl5\sv.c:6784
    #9 0x7ff833c7e3f0 in Perl_sv_free2 C:\Users\xenu\Documents\git\perl5\sv.c:7299
    #10 0x7ff8339004d5 in Perl_SvREFCNT_dec C:\Users\xenu\Documents\git\perl5\sv_inline.h:694
    #11 0x7ff8338eb3cc in perl_destruct C:\Users\xenu\Documents\git\perl5\win32\perl.c:911
    #12 0x7ff8382e8c86 in XS_XS__APItest_clone_with_stack C:\Users\xenu\Documents\git\perl5\ext\XS-APItest\APItest.xs:4225
    #13 0x7ff8339d3678 in Perl_rpp_invoke_xs C:\Users\xenu\Documents\git\perl5\inline.h:1193
    #14 0x7ff8339e401f in Perl_pp_entersub C:\Users\xenu\Documents\git\perl5\pp_hot.c:6497
    #15 0x7ff833c45915 in Perl_runops_standard C:\Users\xenu\Documents\git\perl5\run.c:41
    #16 0x7ff8338e05da in Perl_call_sv C:\Users\xenu\Documents\git\perl5\win32\perl.c:3216
    #17 0x7ff8338de8e0 in Perl_call_list C:\Users\xenu\Documents\git\perl5\win32\perl.c:5295
    #18 0x7ff83388ef6f in S_process_special_blocks C:\Users\xenu\Documents\git\perl5\win32\op.c:11279
    #19 0x7ff83383c7a1 in Perl_newATTRSUB_x C:\Users\xenu\Documents\git\perl5\win32\op.c:11115
    #20 0x7ff83390720a in Perl_yyparse C:\Users\xenu\Documents\git\perl5\win32\perly.y:370
    #21 0x7ff8338fe058 in S_parse_body C:\Users\xenu\Documents\git\perl5\win32\perl.c:2672
    #22 0x7ff8338f0f9e in perl_parse C:\Users\xenu\Documents\git\perl5\win32\perl.c:1912
    #23 0x7ff833df6a74 in RunPerl C:\Users\xenu\Documents\git\perl5\win32\perllib.c:196
    #24 0x7ff7e18b1048 in main C:\Users\xenu\Documents\git\perl5\win32\perlmain.c:39
    #25 0x7ff7e18b36df in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #26 0x7ff7e18b36df in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #27 0x7ff8613a7343  (C:\Windows\System32\KERNEL32.DLL+0x180017343)
    #28 0x7ff8616e26b0  (C:\Windows\SYSTEM32\ntdll.dll+0x1800526b0)

previously allocated by thread T0 here:
    #0 0x7ff8327a2548 in malloc D:\a\_work\1\s\src\vctools\asan\llvm\compiler-rt\lib\asan\asan_malloc_win.cpp:252
    #1 0x7ff833df7f09 in VMem::Malloc(unsigned __int64) C:\Users\xenu\Documents\git\perl5\win32\vmem.h:167
    #2 0x7ff833e0ad25 in CPerlHost::MallocShared(unsigned __int64) C:\Users\xenu\Documents\git\perl5\win32\perlhost.h:83
    #3 0x7ff833e010a4 in PerlMemSharedMalloc(struct IPerlMem *, unsigned __int64) C:\Users\xenu\Documents\git\perl5\win32\perlhost.h:347
    #4 0x7ff83389e6f3 in S_new_slab C:\Users\xenu\Documents\git\perl5\win32\op.c:254
    #5 0x7ff833821c33 in Perl_Slab_Alloc C:\Users\xenu\Documents\git\perl5\win32\op.c:345
    #6 0x7ff83384dcd7 in Perl_newSVOP C:\Users\xenu\Documents\git\perl5\win32\op.c:7737
    #7 0x7ff833d0f003 in S_force_word C:\Users\xenu\Documents\git\perl5\toke.c:2285
    #8 0x7ff833d3dc2c in S_tokenize_use C:\Users\xenu\Documents\git\perl5\toke.c:5155
    #9 0x7ff833da032a in yyl_word_or_keyword C:\Users\xenu\Documents\git\perl5\toke.c:8843
    #10 0x7ff833da4d5d in yyl_keylookup C:\Users\xenu\Documents\git\perl5\toke.c:9132
    #11 0x7ff833d7d6b8 in yyl_try C:\Users\xenu\Documents\git\perl5\toke.c:9646
    #12 0x7ff833d07699 in Perl_yylex C:\Users\xenu\Documents\git\perl5\toke.c:9948
    #13 0x7ff833904f83 in Perl_yyparse C:\Users\xenu\Documents\git\perl5\perly.c:357
    #14 0x7ff8338fe058 in S_parse_body C:\Users\xenu\Documents\git\perl5\win32\perl.c:2672
    #15 0x7ff8338f0f9e in perl_parse C:\Users\xenu\Documents\git\perl5\win32\perl.c:1912
    #16 0x7ff833df6a74 in RunPerl C:\Users\xenu\Documents\git\perl5\win32\perllib.c:196
    #17 0x7ff7e18b1048 in main C:\Users\xenu\Documents\git\perl5\win32\perlmain.c:39
    #18 0x7ff7e18b36df in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #19 0x7ff7e18b36df in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #20 0x7ff8613a7343  (C:\Windows\System32\KERNEL32.DLL+0x180017343)
    #21 0x7ff8616e26b0  (C:\Windows\SYSTEM32\ntdll.dll+0x1800526b0)

SUMMARY: AddressSanitizer: heap-use-after-free C:\Users\xenu\Documents\git\perl5\win32\perl.c:5266 in Perl_call_list
Shadow bytes around the buggy address:
  0x03a00cfb50d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x03a00cfb50e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x03a00cfb50f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x03a00cfb5100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x03a00cfb5110: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x03a00cfb5120: fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd
  0x03a00cfb5130: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
  0x03a00cfb5140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x03a00cfb5150: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x03a00cfb5160: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x03a00cfb5170: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2876==ABORTING

@iabyn
Copy link
Contributor

iabyn commented Feb 12, 2024 via email

iabyn added a commit that referenced this issue Feb 12, 2024
a fresh_perl() TODO test in this file does something like

    use XS::APItest;
    BEGIN {
        clone_with_stack();
    }
    print "ok\n";

As a standalone program, this code gives errors under valgrind,
and in ticket GH #21969 was causing "perl.exe has stopped working" on
Windows 8.

The clone_with_stack() XS function is fairly dodgy - it clones the whole
interpreter including stacks (i.e. what fork() emulation on windows
does), but then continues the RUNOPS loop to completion itself, using
the cloned interpreter, rather than relying on the caller to finish the
ops loop.

This doesn't work very well under BEGIN (hence why it's a TODO test),
but specifically, PL_curcop can be left pointing at an op which gets
freed , but then is later accessed anyway.

This commit resets PL_curcop to &PL_compiling to avoid crashes.
@iabyn
Copy link
Contributor

iabyn commented Feb 12, 2024 via email

@twata1
Copy link
Contributor Author

twata1 commented Feb 12, 2024

@iabyn
Thank you for your response.
I confiremd #21979.
It has been tried 12 times as follows and it does not crash.

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>
C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>..\..\perl -I..\..\lib t\clone-with-stack.t
1..8
ok 1 - minimal clone_with_stack
ok 2 - inside a subroutine
not ok 3 - inside a BEGIN block # TODO clone_with_stack inside a begin block
# Failed test 3 - inside a BEGIN block at t\clone-with-stack.t line 43
#      got ""
# expected "ok"
# PROG:
# use XS::APItest;
# BEGIN {
#     clone_with_stack();
# }
# print "ok\n";
# STATUS: 0
ok 4 - clone stack
ok 5 - with a lexical sub
ok 6 - with localised stuff
ok 7 - inside a loop inside a fn
ok 8 - inside fn inside a loop inside a fn

C:\VCPerl64\perl-5.39.7\ext\XS-APItest>

Thank you all!

iabyn added a commit that referenced this issue Feb 16, 2024
a fresh_perl() TODO test in this file does something like

    use XS::APItest;
    BEGIN {
        clone_with_stack();
    }
    print "ok\n";

As a standalone program, this code gives errors under valgrind,
and in ticket GH #21969 was causing "perl.exe has stopped working" on
Windows 8.

The clone_with_stack() XS function is fairly dodgy - it clones the whole
interpreter including stacks (i.e. what fork() emulation on windows
does), but then continues the RUNOPS loop to completion itself, using
the cloned interpreter, rather than relying on the caller to finish the
ops loop.

This doesn't work very well under BEGIN (hence why it's a TODO test),
but specifically, PL_curcop can be left pointing at an op which gets
freed , but then is later accessed anyway.

This commit resets PL_curcop to &PL_compiling to avoid crashes.
@twata1 twata1 closed this as completed Feb 18, 2024
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

5 participants