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

PerlEmbed 5.14: sv_setsv(ERRSV, &PL_sv_undef); crashes on Linux #13230

Open
p5pRT opened this issue Sep 5, 2013 · 13 comments
Open

PerlEmbed 5.14: sv_setsv(ERRSV, &PL_sv_undef); crashes on Linux #13230

p5pRT opened this issue Sep 5, 2013 · 13 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 5, 2013

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

Searchable as RT119617$

@p5pRT
Copy link
Author

p5pRT commented Sep 5, 2013

From john.unsworth@cp.net

This is a bug report for perl from john.unsworth@​cp.net,

generated with the help of perlbug 1.39 running under perl 5.10.1.

The C++ application calling Perl worked correctly up to Perl 5.10. However
when I upgraded to 5.14 it cores on Linux; it continues to work OK on
Windows.

This is reported just before the core​:

Bizarre copy of UNKNOWN.

Segmentation fault (core dumped)

By adding trace lines I found that the call to sv_setsv(ERRSV,
&PL_sv_undef); was causing the crash

I looked into the header files and found a macro CLEAR_ERROR. At 5.10 this
is defined as​:

#define ERRSV GvSV(PL_errgv)

#define CLEAR_ERRSV() STMT_START { sv_setpvn(ERRSV,"",0); if
(SvMAGICAL(ERRSV)) { mg_free(ERRSV); } SvPOK_only(ERRSV); } STMT_END

However at 5.14 it is​:

#define ERRSV GvSVn(PL_errgv)

#define CLEAR_ERRSV() STMT_START { \

  if (!GvSV(PL_errgv)) { \

  sv_setpvs(GvSV(gv_add_by_type(PL_errgv, SVt_PV)), ""); \

  } else if (SvREADONLY(GvSV(PL_errgv))) { \

  SvREFCNT_dec(GvSV(PL_errgv)); \

  GvSV(PL_errgv) = newSVpvs(""); \

  } else { \

  SV *const errsv = GvSV(PL_errgv); \

  sv_setpvs(errsv, ""); \

  if (SvMAGICAL(errsv)) { \

  mg_free(errsv); \

  } \

  SvPOK_only(errsv); \

  } \

  } STMT_END

So it seems that the implementation of ERRSV has changed in that at 5.14 it
is not initially defined, hence I assume that sv_setsv(ERRSV, &PL_sv_undef);
was trying to set an undefined variable and thus causing the error. The
correct fix seems to be to change this to CLEAR_ERRSV(). Shouldn't this be
mentioned in the embed documentation? There is no mention at all of how to
reset the error variable.


Flags​:

  category=core

  severity=low


Site configuration information for perl 5.10.1​:

Configured by SYSTEM at Mon Aug 24 13​:48​:02 2009.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

 

  Platform​:

  osname=MSWin32, osvers=5.00, archname=MSWin32-x86-multi-thread

  uname=''

  config_args='undef'

  hint=recommended, useposix=true, d_sigaction=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='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -DWIN32
-D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE
-DPRIVLIB_LAST_IN_INC -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS
-DUSE_PERLIO -DPERL_MSVCRT_READFIX',

  optimize='-MD -Zi -DNDEBUG -O1',

  cppflags='-DWIN32'

  ccversion='12.00.8804', gccversion='', gccosandvers=''

  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234

  d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8

  ivtype='long', ivsize=4, 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
-libpath​:"C​:\Perl\lib\CORE" -machine​:x86'

  libpth=\lib

  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
msvcrt.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
msvcrt.lib

  libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl510.lib

  gnulibc_version=''

  Dynamic Linking​:

  dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '

  cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug
-opt​:ref,icf -libpath​:"C​:\Perl\lib\CORE" -machine​:x86'

Locally applied patches​:

  ACTIVEPERL_LOCAL_PATCHES_ENTRY

  32728 64-bit fix for Time​::Local


@​INC for perl 5.10.1​:

  C​:/Perl/site/lib

  C​:/Perl/lib

  .


Environment for perl 5.10.1​:

  HOME (unset)

  LANG (unset)

  LANGUAGE (unset)

  LD_LIBRARY_PATH (unset)

  LOGDIR (unset)

  PATH=C​:\Program Files (x86)\Support
Tools\;C​:\Perl\site\bin;C​:\Perl\bin;C​:\Program Files
(x86)\CriticalPath\CPDS\bin;C​:\windows\system32;C​:\windows;C​:\windows\System
32\Wbem;C​:\windows\System32\WindowsPowerShell\v1.0\;C​:\Program Files
(x86)\Java\jre7\binn;c​:\Program Files (x86)\Microsoft SQL
Server\90\Tools\binn\;C​:\Program Files (x86)\Common Files\ISOCOR

  PERL_BADLANG (unset)

  SHELL (unset)

@p5pRT
Copy link
Author

p5pRT commented Sep 5, 2013

From @jkeenan

On Thu Sep 05 04​:18​:28 2013, john.unsworth@​cp.net wrote​:

This is a bug report for perl from john.unsworth@​cp.net,

generated with the help of perlbug 1.39 running under perl 5.10.1.

The C++ application calling Perl worked correctly up to Perl 5.10. However
when I upgraded to 5.14 it cores on Linux; it continues to work OK on
Windows.

This is reported just before the core​:

Bizarre copy of UNKNOWN.

Segmentation fault (core dumped)

By adding trace lines I found that the call to sv_setsv(ERRSV,
&PL_sv_undef); was causing the crash

I looked into the header files and found a macro CLEAR_ERROR. At 5.10 this
is defined as​:

#define ERRSV GvSV(PL_errgv)

#define CLEAR_ERRSV() STMT_START { sv_setpvn(ERRSV,"",0); if
(SvMAGICAL(ERRSV)) { mg_free(ERRSV); } SvPOK_only(ERRSV); } STMT_END

However at 5.14 it is​:

#define ERRSV GvSVn(PL_errgv)

#define CLEAR_ERRSV() STMT_START { \

if \(\!GvSV\(PL\_errgv\)\) \{                                  \\

  sv\_setpvs\(GvSV\(gv\_add\_by\_type\(PL\_errgv\, SVt\_PV\)\)\, ""\);            \\

\} else if \(SvREADONLY\(GvSV\(PL\_errgv\)\)\) \{                      \\

  SvREFCNT\_dec\(GvSV\(PL\_errgv\)\);                         \\

  GvSV\(PL\_errgv\) = newSVpvs\(""\);                              \\

\} else \{                                                \\

  SV \*const errsv = GvSV\(PL\_errgv\);                     \\

  sv\_setpvs\(errsv\, ""\);                                 \\

  if \(SvMAGICAL\(errsv\)\) \{                               \\

      mg\_free\(errsv\);                                   \\

  \}                                               \\

  SvPOK\_only\(errsv\);                                    \\

\}                                                 \\

\} STMT\_END

So it seems that the implementation of ERRSV has changed in that at
5.14 it
is not initially defined, hence I assume that sv_setsv(ERRSV,
&PL_sv_undef);
was trying to set an undefined variable and thus causing the error. The
correct fix seems to be to change this to CLEAR_ERRSV(). Shouldn't this be
mentioned in the embed documentation? There is no mention at all of how to
reset the error variable.

Would it be possible for you to attach a file which reproduces this
problem either (a) in a file in a pure Perl format; or (b) in a minimal
C++ program calling a small Perl program?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Sep 5, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Sep 10, 2013

From @tonycoz

On Thu Sep 05 04​:18​:28 2013, john.unsworth@​cp.net wrote​:

The C++ application calling Perl worked correctly up to Perl 5.10. However
when I upgraded to 5.14 it cores on Linux; it continues to work OK on
Windows.

This is reported just before the core​:

Bizarre copy of UNKNOWN.

Segmentation fault (core dumped)

By adding trace lines I found that the call to sv_setsv(ERRSV,
&PL_sv_undef); was causing the crash

I looked into the header files and found a macro CLEAR_ERROR. At 5.10 this
is defined as​:

#define ERRSV GvSV(PL_errgv)

#define CLEAR_ERRSV() STMT_START { sv_setpvn(ERRSV,"",0); if
(SvMAGICAL(ERRSV)) { mg_free(ERRSV); } SvPOK_only(ERRSV); } STMT_END

However at 5.14 it is​:

#define ERRSV GvSVn(PL_errgv)

#define CLEAR_ERRSV() STMT_START { \

if \(\!GvSV\(PL\_errgv\)\) \{                                  \\

  sv\_setpvs\(GvSV\(gv\_add\_by\_type\(PL\_errgv\, SVt\_PV\)\)\, ""\);            \\

\} else if \(SvREADONLY\(GvSV\(PL\_errgv\)\)\) \{                      \\

  SvREFCNT\_dec\(GvSV\(PL\_errgv\)\);                         \\

  GvSV\(PL\_errgv\) = newSVpvs\(""\);                              \\

\} else \{                                                \\

  SV \*const errsv = GvSV\(PL\_errgv\);                     \\

  sv\_setpvs\(errsv\, ""\);                                 \\

  if \(SvMAGICAL\(errsv\)\) \{                               \\

      mg\_free\(errsv\);                                   \\

  \}                                               \\

  SvPOK\_only\(errsv\);                                    \\

\}                                                 \\

\} STMT\_END

So it seems that the implementation of ERRSV has changed in that at
5.14 it
is not initially defined, hence I assume that sv_setsv(ERRSV,
&PL_sv_undef);
was trying to set an undefined variable and thus causing the error. The
correct fix seems to be to change this to CLEAR_ERRSV(). Shouldn't this be
mentioned in the embed documentation? There is no mention at all of how to
reset the error variable.

Why do you need to clear ERRSV?

It should be cleared by eval_sv() or call_sv() on success (unless you
use G_KEEPERR).

While I think documenting CLEAR_ERRSV() is useful, I'm not sure where
you'd need to use it outside the core.

The example code Jim asked for would be useful.

Tony

@p5pRT
Copy link
Author

p5pRT commented Sep 10, 2013

From john.unsworth@cp.net

Hi Tony,

We do use G_KEEPERR because we want to report error details. I did send a response to Jim - but the example I tried to create on Windows crashes on the call to CLEAR_ERRSV() and I don't know why.

Regards,
John.

-----Original Message-----
From​: Tony Cook via RT [mailto​:perlbug-followup@​perl.org]
Sent​: 10 September 2013 02​:46
To​: john.unsworth@​cp.net
Subject​: [perl #119617] PerlEmbed 5.14​: sv_setsv(ERRSV, &PL_sv_undef); crashes on Linux

On Thu Sep 05 04​:18​:28 2013, john.unsworth@​cp.net wrote​:
<snip>

So it seems that the implementation of ERRSV has changed in that at
5.14 it
is not initially defined, hence I assume that sv_setsv(ERRSV,
&PL_sv_undef);
was trying to set an undefined variable and thus causing the error.
The correct fix seems to be to change this to CLEAR_ERRSV(). Shouldn't
this be mentioned in the embed documentation? There is no mention at
all of how to reset the error variable.

Why do you need to clear ERRSV?

It should be cleared by eval_sv() or call_sv() on success (unless you use G_KEEPERR).

While I think documenting CLEAR_ERRSV() is useful, I'm not sure where you'd need to use it outside the core.

The example code Jim asked for would be useful.

Tony

@p5pRT
Copy link
Author

p5pRT commented Sep 10, 2013

From @tonycoz

On Tue Sep 10 08​:40​:34 2013, john.unsworth@​cp.net wrote​:

Hi Tony,

We do use G_KEEPERR because we want to report error details. I did
send a response to Jim - but the example I tried to create on Windows
crashes on the call to CLEAR_ERRSV() and I don't know why.

Sorry, the response didn't make it into request tracker for some reason,
but I found it in my mailbox.

Tony

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2013

From @cpansprout

On Tue Sep 10 15​:59​:32 2013, tonyc wrote​:

On Tue Sep 10 08​:40​:34 2013, john.unsworth@​cp.net wrote​:

Hi Tony,

We do use G_KEEPERR because we want to report error details. I did
send a response to Jim - but the example I tried to create on Windows
crashes on the call to CLEAR_ERRSV() and I don't know why.

Sorry, the response didn't make it into request tracker for some reason,
but I found it in my mailbox.

Tony

The message is at
<http​://www.nntp.perl.org/group/perl.perl5.porters/;msgid=000001ceab1a$29aebd20$7d0c3760$@​cp.net>​:

I'm afraid I'm failing miserably with this. I have extracted the
calls that our code makes into a windows console application but it
crashes on the call to CLEAR_ERRSV(). Everything else seems to work
OK if I remove the call. I can see that vTHX->Ierrgv returns zero. I
have attached the code and test script. It is built against 5.14 from
ActiveState. Let me know what you suggest.

The ERRSV changes between 5.10 and 5.14 actually make it safer. In 5.10
CLEAR_ERRSV would crash if GvSV(PL_errgv) (aka
PL_errgv->sv_u.svu_gp->gp_sv) were null. In 5.14 GvSVn is used (with
the final n), which vivifies a new SV for that slot if it is null.

If vTHX->Ierrgv is giving you zero, then the ERRSV changes are a red
herring. Is it possible for you to trace the value of vTHX->Ierrgv to
see when it changes? Would you be able to do a git bisect?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @cpansprout

On Tue Sep 10 18​:17​:00 2013, sprout wrote​:

On Tue Sep 10 15​:59​:32 2013, tonyc wrote​:

On Tue Sep 10 08​:40​:34 2013, john.unsworth@​cp.net wrote​:

Hi Tony,

We do use G_KEEPERR because we want to report error details. I did
send a response to Jim - but the example I tried to create on
Windows
crashes on the call to CLEAR_ERRSV() and I don't know why.

Sorry, the response didn't make it into request tracker for some
reason,
but I found it in my mailbox.

Tony

The message is at
<http​://www.nntp.perl.org/group/perl.perl5.porters/;msgid=000001ceab1a$29aebd20$7d0c3760$@​cp.net>​:

I'm afraid I'm failing miserably with this. I have extracted the
calls that our code makes into a windows console application but it
crashes on the call to CLEAR_ERRSV().

Could you try the same program on Linux?

Everything else seems to work
OK if I remove the call. I can see that vTHX->Ierrgv returns zero. I
have attached the code and test script. It is built against 5.14 from
ActiveState. Let me know what you suggest.

The ERRSV changes between 5.10 and 5.14 actually make it safer. In
5.10
CLEAR_ERRSV would crash if GvSV(PL_errgv) (aka
PL_errgv->sv_u.svu_gp->gp_sv) were null. In 5.14 GvSVn is used (with
the final n), which vivifies a new SV for that slot if it is null.

If vTHX->Ierrgv is giving you zero, then the ERRSV changes are a red
herring. Is it possible for you to trace the value of vTHX->Ierrgv to
see when it changes? Would you be able to do a git bisect?

Re-reading your messages, I see that vTHX->Ierrgv is only zero on Windows.

On Mac OS X, that program just works. I tested the attached modified script with 5.19.5 and 5.14.4, and I get this​:

loaded OK
Hello
Undefined subroutine &test​::fred called at test.pl line 7.

Could you try reducing the app on the same architecture it crashes on?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @cpansprout

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

int main(int argc, char* argv[])
{
  char **perl_argv = (char **) calloc(3, sizeof(char *));
  int perl_argc = 1;

  perl_argv[0] = ("PerlCrash.exe");
  perl_argv[1] = ("test.pl");

  PERL_SYS_INIT(&perl_argc, &perl_argv);

  PerlInterpreter *my_perl = perl_alloc();

  perl_construct(my_perl);

  int iRet = perl_parse(my_perl, NULL, perl_argc, perl_argv, NULL);

  iRet = perl_run(my_perl);
  SV **sp = PL_stack_sp;

  PERL_SET_CONTEXT(my_perl);
  SPAGAIN;
  ENTER;
  SAVETMPS;
  PUSHMARK(sp);

  PUTBACK;

  int ret = perl_call_pv("test​::test", G_SCALAR|G_EVAL);

  GV* err = (vTHX->Ierrgv);
  warn("%"SVf, SVfARG(ERRSV));
  CLEAR_ERRSV();

  return 0;
}

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @bulk88

On Sat Oct 26 01​:05​:04 2013, sprout wrote​:

On Tue Sep 10 18​:17​:00 2013, sprout wrote​:

On Tue Sep 10 15​:59​:32 2013, tonyc wrote​:

On Tue Sep 10 08​:40​:34 2013, john.unsworth@​cp.net wrote​:

Sorry, the response didn't make it into request tracker for some
reason,
but I found it in my mailbox.

Tony

The message is at
<http​://www.nntp.perl.org/group/perl.perl5.porters/;msgid=000001ceab1a$29aebd20$7d0c3760$@​cp.net>​:

Attaching the 2 files from that John Unswort email post that didn't get to RT, to RT. Note, the C file is different from FC's C file in https://rt-archive.perl.org/perl5/Ticket/Display.html?id=119617#txn-1265206 .

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @bulk88

PerlCrash.cpp

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @bulk88

test.pl

@p5pRT
Copy link
Author

p5pRT commented Oct 26, 2013

From @bulk88

On Sat Oct 26 14​:25​:23 2013, bulk88 wrote​:

Attaching the 2 files from that John Unswort email post that didn't
get to RT, to RT. Note, the C file is different from FC's C file in
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=119617#txn-1265206 .

Ran on 5.19.6/blead, VC 2003 win32 32 bits threaded, got


loaded OK
Hello


no segvs.

The c++ code does look flakey. Also the code doesn't do "#define PERL_NO_GET_CONTEXT". Removing the 2 redundant lines below and doing "#define PERL_NO_GET_CONTEXT" still doesn't crash.


  SV **sp = PL_stack_sp;

  PERL_SET_CONTEXT(my_perl); //already set somewhere where bulk88 can't quickly ID, PL_stack_sp would be uninit memory otherwise
  SPAGAIN; //redundant of line 1, use dSP;


--
bulk88 ~ bulk88 at hotmail.com

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

2 participants