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

Overloaded integer constants are prematurely deallocated #15646

Closed
p5pRT opened this issue Oct 7, 2016 · 11 comments
Closed

Overloaded integer constants are prematurely deallocated #15646

p5pRT opened this issue Oct 7, 2016 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 7, 2016

Migrated from rt.perl.org#129825 (status was 'rejected')

Searchable as RT129825$

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From trizenx@gmail.com

This is a bug report for perl from trizenx@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.


It seems like there is a premature deallocation of integer overloaded
constants which are stored inside an object. When the object is destroyed,
the constants are destroyed as well, which leads to undefined behavior.

Bellow is the code illustrating the issue​:

#######################################

package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ; segfault
(perl>=5.24.0)
#use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ; incorrect
(perl>=5.24.0)

sub new {
  my $class = shift;
  my $self = {};
  my %param = @​_;
  $self->{name} = $param{name};
  bless $self, $class;
}

sub set {
  my $self = shift;
  my %kv = @​_;

  while (my ($k, $v) = each %kv) {
  $self->{hash}->{$k} = $v;
  }
  1;
}

sub show {
  my $self = shift;
  my $kv = $self->{hash};

  printf "--- %s ---\n", $self->{name};

  my %kloop = %$kv;
  while (my ($k, $v) = each %kloop) {
  $v = 'UNDEF' if !defined $v;
  print "$k => $v\n";
  }
  1;
}

sub DESTROY {
  my $self = shift;
  show($self);
  1;
}

#my $foo; # NOTE​: uncommenting this line, fixes
the bug
$foo = Foo->new(name => 'explicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();
undef $foo;

$foo = Foo->new(name => 'implicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();

######################### END-OF-CODE #########################

The output under perl=5.24.0 with `Math​::GMP qw(​:constant)` is​:

--- explicit ---
1 => 2
3 => 4
5 => 6
--- explicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
1 => 2
3 => 4
5 => 6
--- implicit ---
5 => UNDEF
1 => 2
3 => 4



Flags​:
  category=core
  severity=medium


Site configuration information for perl 5.24.0​:

Configured by builduser at Thu Sep 8 13​:45​:49 CEST 2016.

Summary of my perl5 (revision 5 version 24 subversion 0) configuration​:

  Platform​:
  osname=linux, osvers=4.7.3-1-arch, archname=x86_64-linux-thread-multi
  uname='linux flo-64 4.7.3-1-arch #1 smp preempt wed sep 7 17​:57​:38 cest
2016 x86_64 gnulinux '
  config_args='-des -Dusethreads -Duseshrplib -Doptimize=-march=x86-64
-mtune=generic -O2 -pipe -fstack-protector-strong -Dprefix=/usr
-Dvendorprefix=/usr -Dprivlib=/usr/share/perl5/core_perl
-Darchlib=/usr/lib/perl5/core_perl -Dsitelib=/usr/share/perl5/site_perl
-Dsitearch=/usr/lib/perl5/site_perl
-Dvendorlib=/usr/share/perl5/vendor_perl
-Dvendorarch=/usr/lib/perl5/vendor_perl -Dscriptdir=/usr/bin/core_perl
-Dsitescript=/usr/bin/site_perl -Dvendorscript=/usr/bin/vendor_perl
-Dinc_version_list=none -Dman1ext=1perl -Dman3ext=3perl
-Dcccdlflags='-fPIC' -Dlddlflags=-shared
-Wl,-O1,--sort-common,--as-needed,-z,relro
-Dldflags=-Wl,-O1,--sort-common,--as-needed,-z,relro'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv
-fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-march=x86-64 -mtune=generic -O2 -pipe
-fstack-protector-strong',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe
-fstack-protector-strong -I/usr/local/include'
  ccversion='', gccversion='6.1.1 20160802', 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='cc', ldflags ='-Wl,-O1,--sort-common,--as-needed,-z,relro
-fstack-protector-strong -L/usr/local/lib'
  libpth=/usr/local/lib
/usr/lib/gcc/x86_64-pc-linux-gnu/6.1.1/include-fixed /usr/lib /lib/../lib
/usr/lib/../lib /lib /lib64 /usr/lib64
  libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc
-lgdbm_compat
  perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.24.so, so=so, useshrplib=true, libperl=libperl.so
  gnulibc_version='2.24'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E
-Wl,-rpath,/usr/lib/perl5/core_perl/CORE'
  cccdlflags='-fPIC', lddlflags='-shared
-Wl,-O1,--sort-common,--as-needed,-z,relro -L/usr/local/lib
-fstack-protector-strong'


@​INC for perl 5.24.0​:
  /usr/lib/perl5/site_perl
  /usr/share/perl5/site_perl
  /usr/lib/perl5/vendor_perl
  /usr/share/perl5/vendor_perl
  /usr/lib/perl5/core_perl
  /usr/share/perl5/core_perl
  .


Environment for perl 5.24.0​:
  HOME=/home/swampyx
  LANG=en_US.UTF-8
  LANGUAGE (unset)
  LC_CTYPE=en_US.UTF-8
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)

PATH=/usr/lib/ccache/bin​:/usr/local/sbin​:/usr/local/bin​:/usr/bin​:/usr/lib/jvm/default/bin​:/usr/bin/site_perl​:/usr/bin/vendor_perl​:/usr/bin/core_perl​:/usr/share/perl6/vendor/bin
  PERL_BADLANG (unset)
  SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From @jkeenan

On Fri Oct 07 05​:11​:42 2016, trizenx@​gmail.com wrote​:

This is a bug report for perl from trizenx@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------

It seems like there is a premature deallocation of integer overloaded
constants which are stored inside an object. When the object is
destroyed,
the constants are destroyed as well, which leads to undefined
behavior.

Bellow is the code illustrating the issue​:

#######################################

package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ;
segfault
(perl>=5.24.0)
#use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ;
incorrect
(perl>=5.24.0)

sub new {
my $class = shift;
my $self = {};
my %param = @​_;
$self->{name} = $param{name};
bless $self, $class;
}

sub set {
my $self = shift;
my %kv = @​_;

while (my ($k, $v) = each %kv) {
$self->{hash}->{$k} = $v;
}
1;
}

sub show {
my $self = shift;
my $kv = $self->{hash};

printf "--- %s ---\n", $self->{name};

my %kloop = %$kv;
while (my ($k, $v) = each %kloop) {
$v = 'UNDEF' if !defined $v;
print "$k => $v\n";
}
1;
}

sub DESTROY {
my $self = shift;
show($self);
1;
}

#my $foo; # NOTE​: uncommenting this line,
fixes
the bug
$foo = Foo->new(name => 'explicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();
undef $foo;

$foo = Foo->new(name => 'implicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();

######################### END-OF-CODE #########################

The output under perl=5.24.0 with `Math​::GMP qw(​:constant)` is​:

--- explicit ---
1 => 2
3 => 4
5 => 6
--- explicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
1 => 2
3 => 4
5 => 6
--- implicit ---
5 => UNDEF
1 => 2
3 => 4

Thanks for the bug report. I suspect this is going to require input from others to untangle.

If I read your post correctly, you are testing 3 scenarios differentiated by which of the 'use' statements is uncommented -- correct?

Here are my results​:

1.
#####
$ head -5 129825-constant-use-math-gmp.pl
package Foo;

use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ; segfault (perl>=5.24.0)
#use bignum only => 'GMP'; # ; error (perl>=5.18.4)
#use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ; incorrect (perl>=5.24.0)
#####
Math​::BigNum has a dependency on Math​::MPFR, which in turn has a dependency on C libraries which I do not have installed. So I can't say anything useful about this case.

2.
#####
$ perl -v | head -2 | tail -1
This is perl 5, version 24, subversion 0 (v5.24.0) built for x86_64-linux

$ head -5 129825-constant-bignum.pl
package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ; segfault (perl>=5.24.0)
use bignum only => 'GMP'; # ; error (perl>=5.18.4)
#use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ; incorrect (perl>=5.24.0)

$ perl 129825-constant-bignum.pl
Couldn't load specified math lib(s) and fallback disallowed at /home/jkeenan/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/bignum.pm line 171.
BEGIN failed--compilation aborted at 129825-constant-bignum.pl line 4.
#####
I don't understand why 'bignum' is failing to locate Math​::GMP, even though it is installed.

3.
#####
$ head -5 129825-constant-bignum.pl
package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ; segfault (perl>=5.24.0)
#use bignum only => 'GMP'; # ; error (perl>=5.18.4)
use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ; incorrect (perl>=5.24.0)

$ perl 129825-constant-bignum.pl
--- explicit ---
5 => 6
1 => 2
3 => 4
--- explicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
5 => 6
1 => 2
3 => 4
#####

So, in the one case where I can run your program (#3), I cannot reproduce your error.

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From trizenx@gmail.com

On Fri Oct 07 07​:29​:57 2016, jkeenan wrote​:

On Fri Oct 07 05​:11​:42 2016, trizenx@​gmail.com wrote​:

This is a bug report for perl from trizenx@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------

It seems like there is a premature deallocation of integer overloaded
constants which are stored inside an object. When the object is
destroyed,
the constants are destroyed as well, which leads to undefined
behavior.

Bellow is the code illustrating the issue​:

#######################################

package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ;
segfault
(perl>=5.24.0)
#use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ;
incorrect
(perl>=5.24.0)

sub new {
my $class = shift;
my $self = {};
my %param = @​_;
$self->{name} = $param{name};
bless $self, $class;
}

sub set {
my $self = shift;
my %kv = @​_;

while (my ($k, $v) = each %kv) {
$self->{hash}->{$k} = $v;
}
1;
}

sub show {
my $self = shift;
my $kv = $self->{hash};

printf "--- %s ---\n", $self->{name};

my %kloop = %$kv;
while (my ($k, $v) = each %kloop) {
$v = 'UNDEF' if !defined $v;
print "$k => $v\n";
}
1;
}

sub DESTROY {
my $self = shift;
show($self);
1;
}

#my $foo; # NOTE​: uncommenting this line,
fixes
the bug
$foo = Foo->new(name => 'explicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();
undef $foo;

$foo = Foo->new(name => 'implicit');
$foo->set(1 => 2, 3 => 4, 5 => 6);
$foo->show();

######################### END-OF-CODE #########################

The output under perl=5.24.0 with `Math​::GMP qw(​:constant)` is​:

--- explicit ---
1 => 2
3 => 4
5 => 6
--- explicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
1 => 2
3 => 4
5 => 6
--- implicit ---
5 => UNDEF
1 => 2
3 => 4

Thanks for the bug report. I suspect this is going to require input
from others to untangle.

If I read your post correctly, you are testing 3 scenarios
differentiated by which of the 'use' statements is uncommented --
correct?

Here are my results​:

1.
#####
$ head -5 129825-constant-use-math-gmp.pl
package Foo;

use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ;
segfault (perl>=5.24.0)
#use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
#use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ;
incorrect (perl>=5.24.0)
#####
Math​::BigNum has a dependency on Math​::MPFR, which in turn has a
dependency on C libraries which I do not have installed. So I can't
say anything useful about this case.

2.
#####
$ perl -v | head -2 | tail -1
This is perl 5, version 24, subversion 0 (v5.24.0) built for x86_64-
linux

$ head -5 129825-constant-bignum.pl
package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ;
segfault (perl>=5.24.0)
use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
#use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ;
incorrect (perl>=5.24.0)

$ perl 129825-constant-bignum.pl
Couldn't load specified math lib(s) and fallback disallowed at
/home/jkeenan/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/bignum.pm
line 171.
BEGIN failed--compilation aborted at 129825-constant-bignum.pl line 4.
#####
I don't understand why 'bignum' is failing to locate Math​::GMP, even
though it is installed.

3.
#####
$ head -5 129825-constant-bignum.pl
package Foo;

#use Math​::BigNum qw(​:constant); # correct (perl=5.18.4) ;
segfault (perl>=5.24.0)
#use bignum only => 'GMP'; # ; error
(perl>=5.18.4)
use Math​::GMP qw(​:constant); # correct (perl=5.18.4) ;
incorrect (perl>=5.24.0)

$ perl 129825-constant-bignum.pl
--- explicit ---
5 => 6
1 => 2
3 => 4
--- explicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
5 => 6
1 => 2
3 => 4
--- implicit ---
5 => 6
1 => 2
3 => 4
#####

So, in the one case where I can run your program (#3), I cannot
reproduce your error.

Thank you very much.

Adding a "1;" after the method DESTROY, the bug is reproducible in the third case as well.

##############
# ...

sub DESTROY {
  my $self = shift;
  show($self);
  1;
}

1; # this triggers the bug with Math​::GMP

#...
##############

For the second case of "bignum", the "Math​::BigInt​::GMP" module is required.

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From @iabyn

On Fri, Oct 07, 2016 at 07​:29​:57AM -0700, James E Keenan via RT wrote​:

So, in the one case where I can run your program (#3), I cannot reproduce your error.

I can reproduce the SEGV with use Math​::BigNum qw(​:constant).
I'm currently looking into it.

--
Music lesson​: a symbiotic relationship whereby a pupil's embellishments
concerning the amount of practice performed since the last lesson are
rewarded with embellishments from the teacher concerning the pupil's
progress over the corresponding period.

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From zefram@fysh.org

Daniel Suteu wrote​:

It seems like there is a premature deallocation of integer overloaded
constants which are stored inside an object. When the object is destroyed,
the constants are destroyed as well, which leads to undefined behavior.

This doesn't happen on just any destruction, it's specifically during
global destruction, at which point the order in which objects are
destroyed is not guaranteed. It is impossible to do all destruction in
the right order, because reference loops mean that there is no right order
for some structures. Non-loop cases such as yours could potentially be
changed, though.

Where your destructor depends on the object being well-formed, you
can aviod this kind of problem by checking ${^GLOBAL_PHASE} to see
whether you're in global destruction, and skipping sensitive parts of
the destructor in that case. Most cleanup isn't required when you know
the process is about to terminate.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From @iabyn

On Fri, Oct 07, 2016 at 04​:17​:16PM +0100, Dave Mitchell wrote​:

On Fri, Oct 07, 2016 at 07​:29​:57AM -0700, James E Keenan via RT wrote​:

So, in the one case where I can run your program (#3), I cannot reproduce your error.

I can reproduce the SEGV with use Math​::BigNum qw(​:constant).
I'm currently looking into it.

The SEGV is due to a bug in the typemap for Math-GMPq-0.41.

In particular these​:

  MPQ
  $var = INT2PTR($type, SvIVX(SvRV($arg)))
  MPZ
  $var = INT2PTR($type, SvIVX(SvRV($arg)))
  MPF
  $var = INT2PTR($type, SvIVX(SvRV($arg)))
  MPFR
  $var = INT2PTR($type, SvIVX(SvRV($arg)))
  GMP_RANDSTATE
  $var = INT2PTR($type, SvIVX(SvRV($arg)))

If the passed arg isn't a ref, then it will unconditionally attempt to deref
a non-ref, and SEGVs ensue.

During global destruction, it's quite possible for a RV to be converted
into an undef value, which is what's happening here. I haven't examined it
in enough detail to determine exactly when an how the RV becomes undef
(but its during string overloading while calling show() called from
DESTROY() called during global destruction).

Changing $foo to be lexical causes it to be cleared during exit from the
main scope, which happens before global destruction, and causes a more
orderly destroying sequence.

I should imagine that the other case, where it displays 'UNDEF' is due to
a similar global destruction ordering issue, but I haven't verified it
(and don't plan to unless someone makes a case why I should).

--
I don't want to achieve immortality through my work...
I want to achieve it through not dying.
  -- Woody Allen

@p5pRT
Copy link
Author

p5pRT commented Oct 7, 2016

From @sisyphus

----- Original Message -----
From​: "Dave Mitchell" <davem@​iabyn.com>
To​: "James E Keenan via RT" <perlbug-followup@​perl.org>
Cc​: <perl5-porters@​perl.org>
Sent​: Friday, October 07, 2016 5​:06 PM
Subject​: Re​: [perl #129825] Overloaded integer constants are prematurely
deallocated

[snip]

The SEGV is due to a bug in the typemap for Math-GMPq-0.41.

In particular these​:

MPQ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPZ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPF
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPFR
$var = INT2PTR($type, SvIVX(SvRV($arg)))
GMP_RANDSTATE
$var = INT2PTR($type, SvIVX(SvRV($arg)))

If the passed arg isn't a ref, then it will unconditionally attempt to
deref
a non-ref, and SEGVs ensue.

It's unclear to me exactly what the typemap should be specifying in order to
avoid this bug..
Could you/someone elaborate ?

(I'm the author of Math​::GMPq - and of a number of other modules that use
the same typemap.)

Cheers,
Rob

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2016

From @iabyn

On Fri, Oct 07, 2016 at 10​:11​:02PM +0100, Sisyphus wrote​:

----- Original Message ----- From​: "Dave Mitchell" <davem@​iabyn.com>
To​: "James E Keenan via RT" <perlbug-followup@​perl.org>
Cc​: <perl5-porters@​perl.org>
Sent​: Friday, October 07, 2016 5​:06 PM
Subject​: Re​: [perl #129825] Overloaded integer constants are prematurely
deallocated

[snip]

The SEGV is due to a bug in the typemap for Math-GMPq-0.41.

In particular these​:

MPQ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPZ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPF
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPFR
$var = INT2PTR($type, SvIVX(SvRV($arg)))
GMP_RANDSTATE
$var = INT2PTR($type, SvIVX(SvRV($arg)))

If the passed arg isn't a ref, then it will unconditionally attempt to
deref
a non-ref, and SEGVs ensue.

It's unclear to me exactly what the typemap should be specifying in order to
avoid this bug..
Could you/someone elaborate ?

(I'm the author of Math​::GMPq - and of a number of other modules that use
the same typemap.)

Well the problem is if an XS sub with that typemap is passed an arg which
(for whatever reason) isn't a ref, then the code is going to SEGV.
How to fix it depends I guess on how you want XS subs to behave in this
case. One possibility would be​:

  $var = SvROK($arg) ? INT2PTR($type, SvIVX(SvRV($arg))) : NULL

which will set $var to NULL pointer in that case. It's then up to the
body of the XS sub to decide what to do if the pointer is NULL.

Or you could have the code in the typemap expression croak.

--
Art is anything that has a label (especially if the label is "untitled 1")

@p5pRT
Copy link
Author

p5pRT commented Oct 9, 2016

From @sisyphus

----- Original Message -----
From​: "Dave Mitchell" <davem@​iabyn.com>
To​: "Sisyphus" <sisyphus1@​optusnet.com.au>
Cc​: <perl5-porters@​perl.org>
Sent​: Saturday, October 08, 2016 10​:53 AM
Subject​: Re​: [perl #129825] Overloaded integer constants are prematurely
deallocated

On Fri, Oct 07, 2016 at 10​:11​:02PM +0100, Sisyphus wrote​:

----- Original Message ----- From​: "Dave Mitchell" <davem@​iabyn.com>
To​: "James E Keenan via RT" <perlbug-followup@​perl.org>
Cc​: <perl5-porters@​perl.org>
Sent​: Friday, October 07, 2016 5​:06 PM
Subject​: Re​: [perl #129825] Overloaded integer constants are prematurely
deallocated

[snip]

The SEGV is due to a bug in the typemap for Math-GMPq-0.41.

In particular these​:

MPQ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPZ
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPF
$var = INT2PTR($type, SvIVX(SvRV($arg)))
MPFR
$var = INT2PTR($type, SvIVX(SvRV($arg)))
GMP_RANDSTATE
$var = INT2PTR($type, SvIVX(SvRV($arg)))

If the passed arg isn't a ref, then it will unconditionally attempt to
deref
a non-ref, and SEGVs ensue.

It's unclear to me exactly what the typemap should be specifying in order
to
avoid this bug..
Could you/someone elaborate ?

(I'm the author of Math​::GMPq - and of a number of other modules that use
the same typemap.)

Well the problem is if an XS sub with that typemap is passed an arg which
(for whatever reason) isn't a ref, then the code is going to SEGV.
How to fix it depends I guess on how you want XS subs to behave in this
case. One possibility would be​:

$var = SvROK($arg) ? INT2PTR($type, SvIVX(SvRV($arg))) : NULL

which will set $var to NULL pointer in that case. It's then up to the
body of the XS sub to decide what to do if the pointer is NULL.

Or you could have the code in the typemap expression croak.

Thanks Dave.

I'll have another think about if/how I want to handle this.

What I don't like is that something like
for(1..1000) {Rmpq_add(a, a, b)}
would call SvROK() 3000 times, though 2 such calls (one for "a" and one for
"b") should be sufficient.

I guess the SvROK() call is fairly cheap, but for general purposes it
doesn't go far enough as there are some ref objects (that could conceivably
be passed) which will still lead to a segfault.

Anyway ... something to think about when I get home in a couple of weeks.

Cheers,
Rob

@p5pRT p5pRT closed this as completed Mar 27, 2017
@p5pRT
Copy link
Author

p5pRT commented Mar 27, 2017

@iabyn - Status changed from 'open' to 'rejected'

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

1 participant