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

Extend SvREFCNT* to work on any perl variable type #12935

Closed
p5pRT opened this issue Apr 28, 2013 · 15 comments
Closed

Extend SvREFCNT* to work on any perl variable type #12935

p5pRT opened this issue Apr 28, 2013 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 28, 2013

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

Searchable as RT117793$

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2013

From @jmdh

Created by @jmdh

This is a bug report for perl from dom@​earth.li,
generated with the help of perlbug 1.39 running under perl 5.14.2.

-----------------------------------------------------------------
From <http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401132>​:

"I recently discovered that Devel​::Peek's SvREFCNT, SvREFCNT_inc
and SvREFCNT_dec functions are not as flexible as the XS functions that
they wrap. In XS where you wish to get the reference count of an hash
your HV * pointer will cast to an SV * when passed as an argument to
SvREFCNT(). In Perl using Devel​::Peek​:SvREFCNT(%m) does not return the
reference count of %m, but rather treats %m as a list of arguments to
the function causing a runtime error. I believe the intent of the code was
to return the reference count of the parameter passed and the difference
between Perl Prototypes and C casting was overlooked.
  A small patch (attached) will extend these three functions to
work on any perl variable type. This could break code in cases where
users expect an array of one member passed to these functions to operate
on that only member of the array, but for all other data types (and
arrays of any other length) these functions currently croak. Possibly a
new family of functions is warranted to maintain reverse compatibility
in the single element array case in the existing functions, but it is
not my place to make that judgement."

....

" "\%m" is a reference constructor, so SvREFCNT() ends up
reporting the reference count of that newly constructed SV. The
situation can be illustrated with this small script​:

#!/usr/bin/perl
use strict;
use warnings;
use Devel​::Peek;
my %m = (a => 'b');
my $mr = \%m;
Devel​::Peek​::Dump($mr);
print Devel​::Peek​::SvREFCNT(\%m), "\n";

  From the Dump you can see that %m (the PVHV) has a refcount of
2, but "Devel​::Peek​::SvREFCNT(\%m)" reports 1. The reason for this can
be illustrated by breaking that call up a little bit. One would
normally expect that​:

Devel​::Peek​::SvREFCNT(\%m)

should be equivalent to

my $tmp = \%m;
Devel​::Peek​::SvREFCNT($tmp)

which unsurprisingly reports a refcount of 1 for $tmp. Nothing changes
when $tmp is an immediate, unlabeled value on the argument stack to
SvREFCNT() and I think that's expected and correct behavior.

  The proposed patch solves this difficulty by always passing the
argument from Perl by reference and then unconditionally dereferencing
to access the target value."

Patch attached for review.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.14.2:

Configured by Debian Project at Fri Apr 12 09:56:36 UTC 2013.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=2.6.32-5-686-bigmem, archname=i486-linux-gnu-thread-multi-64int
    uname='linux murphy 2.6.32-5-686-bigmem #1 smp mon feb 25 01:53:47 utc 2013 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Dldflags= -Wl,-z,relro -Dlddlflags=-shared -Wl,-z,relro -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.14.2 -Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.14.2 -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.7.2', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/i386-linux-gnu /lib/../lib /usr/lib/i386-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=, so=so, useshrplib=true, libperl=libperl.so.5.14.2
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.14.2:
    /etc/perl
    /usr/local/lib/perl/5.14.2
    /usr/local/share/perl/5.14.2
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.14
    /usr/share/perl/5.14
    /usr/local/lib/site_perl
    .


Environment for perl 5.14.2:
    HOME=/home/dom
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

-- 
Dominic Hargreaves | http://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2013

From @jmdh

0001-Extend-SvREFCNT-to-work-on-any-perl-variable-type.patch
From 68ee83ef1867e121aeb890f3d4f326126b2495f7 Mon Sep 17 00:00:00 2001
From: Robert Stone <talby@trap.mtview.ca.us>
Date: Thu, 30 Nov 2006 18:31:54 -0800
Subject: [PATCH] Extend SvREFCNT* to work on any perl variable type

This could break code in cases where users expect an array of one member
passed to these functions to operate on that only member of the array, but
for all other data types (and arrays of any other length) these functions
currently croak.  Possibly a new family of functions is warranted to
maintain reverse compatibility in the single element array case in the
existing functions, but it is not my place to make that judgement.

Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401132
---
 ext/Devel-Peek/Peek.xs |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/ext/Devel-Peek/Peek.xs b/ext/Devel-Peek/Peek.xs
index e97c979..1cc0fd3 100644
--- a/ext/Devel-Peek/Peek.xs
+++ b/ext/Devel-Peek/Peek.xs
@@ -389,15 +389,22 @@ PPCODE:
 I32
 SvREFCNT(sv)
 SV *	sv
+PROTOTYPE: \[$@%&*]
+PPCODE:
+{
+    RETVAL = SvREFCNT(SvRV(sv)) - 1; // -1 because our ref doesn't count
+    PUSHi(RETVAL);
+}
 
 # PPCODE needed since otherwise sv_2mortal is inserted that will kill the value.
 
 SV *
 SvREFCNT_inc(sv)
 SV *	sv
+PROTOTYPE: \[$@%&*]
 PPCODE:
 {
-    RETVAL = SvREFCNT_inc(sv);
+    RETVAL = SvREFCNT_inc(SvRV(sv));
     PUSHs(RETVAL);
 }
 
@@ -406,9 +413,10 @@ PPCODE:
 void
 SvREFCNT_dec(sv)
 SV *	sv
+PROTOTYPE: \[$@%&*]
 PPCODE:
 {
-    SvREFCNT_dec(sv);
+    SvREFCNT_dec(SvRV(sv));
     PUSHs(sv);
 }
 
-- 
1.7.10.4

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2013

From @tonycoz

On Sun, Apr 28, 2013 at 02​:39​:25PM -0700, Dominic Hargreaves wrote​:

"I recently discovered that Devel​::Peek's SvREFCNT, SvREFCNT_inc
and SvREFCNT_dec functions are not as flexible as the XS functions that
they wrap. In XS where you wish to get the reference count of an hash
your HV * pointer will cast to an SV * when passed as an argument to
SvREFCNT(). In Perl using Devel​::Peek​:SvREFCNT(%m) does not return the
reference count of %m, but rather treats %m as a list of arguments to
the function causing a runtime error. I believe the intent of the code was
to return the reference count of the parameter passed and the difference
between Perl Prototypes and C casting was overlooked.
A small patch (attached) will extend these three functions to
work on any perl variable type. This could break code in cases where
users expect an array of one member passed to these functions to operate
on that only member of the array, but for all other data types (and
arrays of any other length) these functions currently croak. Possibly a
new family of functions is warranted to maintain reverse compatibility
in the single element array case in the existing functions, but it is
not my place to make that judgement."

Or we could just deprecate/remove them.

Tony

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2013

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

@p5pRT
Copy link
Author

p5pRT commented May 13, 2013

From @nwc10

On Mon, Apr 29, 2013 at 09​:02​:50AM +1000, Tony Cook wrote​:

On Sun, Apr 28, 2013 at 02​:39​:25PM -0700, Dominic Hargreaves wrote​:

"I recently discovered that Devel​::Peek's SvREFCNT, SvREFCNT_inc
and SvREFCNT_dec functions are not as flexible as the XS functions that
they wrap. In XS where you wish to get the reference count of an hash
your HV * pointer will cast to an SV * when passed as an argument to
SvREFCNT(). In Perl using Devel​::Peek​:SvREFCNT(%m) does not return the
reference count of %m, but rather treats %m as a list of arguments to
the function causing a runtime error. I believe the intent of the code was
to return the reference count of the parameter passed and the difference
between Perl Prototypes and C casting was overlooked.
A small patch (attached) will extend these three functions to
work on any perl variable type. This could break code in cases where
users expect an array of one member passed to these functions to operate
on that only member of the array, but for all other data types (and
arrays of any other length) these functions currently croak. Possibly a
new family of functions is warranted to maintain reverse compatibility
in the single element array case in the existing functions, but it is
not my place to make that judgement."

Or we could just deprecate/remove them.

Yes. It's always going to be possible for people to use (or write) code
to mess with the internals, such as reference counts.

But I'm really not convinced that we should be offering documented functions
in the default installation which offer such dangerous direct unguarded
access to the internals. If people want to live dangerously, they should
at least have to install an appropriate module from CPAN.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 13, 2013

From @khwilliamson

On 05/13/2013 09​:03 AM, Nicholas Clark wrote​:

On Mon, Apr 29, 2013 at 09​:02​:50AM +1000, Tony Cook wrote​:

On Sun, Apr 28, 2013 at 02​:39​:25PM -0700, Dominic Hargreaves wrote​:

"I recently discovered that Devel​::Peek's SvREFCNT, SvREFCNT_inc
and SvREFCNT_dec functions are not as flexible as the XS functions that
they wrap. In XS where you wish to get the reference count of an hash
your HV * pointer will cast to an SV * when passed as an argument to
SvREFCNT(). In Perl using Devel​::Peek​:SvREFCNT(%m) does not return the
reference count of %m, but rather treats %m as a list of arguments to
the function causing a runtime error. I believe the intent of the code was
to return the reference count of the parameter passed and the difference
between Perl Prototypes and C casting was overlooked.
A small patch (attached) will extend these three functions to
work on any perl variable type. This could break code in cases where
users expect an array of one member passed to these functions to operate
on that only member of the array, but for all other data types (and
arrays of any other length) these functions currently croak. Possibly a
new family of functions is warranted to maintain reverse compatibility
in the single element array case in the existing functions, but it is
not my place to make that judgement."

Or we could just deprecate/remove them.

Yes. It's always going to be possible for people to use (or write) code
to mess with the internals, such as reference counts.

But I'm really not convinced that we should be offering documented functions
in the default installation which offer such dangerous direct unguarded
access to the internals. If people want to live dangerously, they should
at least have to install an appropriate module from CPAN.

Nicholas Clark

+1

@p5pRT
Copy link
Author

p5pRT commented May 13, 2013

From @bulk88

Nicholas Clark wrote​:

Yes. It's always going to be possible for people to use (or write) code
to mess with the internals, such as reference counts.

But I'm really not convinced that we should be offering documented functions
in the default installation which offer such dangerous direct unguarded
access to the internals. If people want to live dangerously, they should
at least have to install an appropriate module from CPAN.

Nicholas Clark

The refcount checkers from Perl lang are useful to prove in a test that
a leak was fixed.

@p5pRT
Copy link
Author

p5pRT commented May 13, 2013

From @nwc10

On Mon, May 13, 2013 at 01​:36​:06PM -0400, bulk88 wrote​:

Nicholas Clark wrote​:

Yes. It's always going to be possible for people to use (or write) code
to mess with the internals, such as reference counts.

But I'm really not convinced that we should be offering documented functions
in the default installation which offer such dangerous direct unguarded
access to the internals. If people want to live dangerously, they should
at least have to install an appropriate module from CPAN.

Nicholas Clark

The refcount checkers from Perl lang are useful to prove in a test that
a leak was fixed.

Agree, in that I could see that the perl core is reading reference counts in
tests to check them. But not changing them. I went for a look with
grep.cpan.me, and as far as I can tell the pretty much only place doing this
in tests is the perl core. But the core doesn't need to install self-test
infrastructure, just to have it available during testing.

(That's not an argument that everything must change. Just a thought that
things are not as constrained as they might seem)

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 13, 2013

From @Hugmeir

On Sun, Apr 28, 2013 at 6​:39 PM, Dominic Hargreaves <
perlbug-followup@​perl.org> wrote​:

# New Ticket Created by Dominic Hargreaves
# Please include the string​: [perl #117793]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=117793 >

This is a bug report for perl from dom@​earth.li,
generated with the help of perlbug 1.39 running under perl 5.14.2.

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

From <http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401132>​:

"I recently discovered that Devel​::Peek's SvREFCNT, SvREFCNT_inc
and SvREFCNT_dec functions are not as flexible as the XS functions that
they wrap. In XS where you wish to get the reference count of an hash
your HV * pointer will cast to an SV * when passed as an argument to
SvREFCNT(). In Perl using Devel​::Peek​:SvREFCNT(%m) does not return the
reference count of %m, but rather treats %m as a list of arguments to
the function causing a runtime error. I believe the intent of the code was
to return the reference count of the parameter passed and the difference
between Perl Prototypes and C casting was overlooked.
A small patch (attached) will extend these three functions to
work on any perl variable type. This could break code in cases where
users expect an array of one member passed to these functions to operate
on that only member of the array, but for all other data types (and
arrays of any other length) these functions currently croak. Possibly a
new family of functions is warranted to maintain reverse compatibility
in the single element array case in the existing functions, but it is
not my place to make that judgement."

....

" "\%m" is a reference constructor, so SvREFCNT() ends up
reporting the reference count of that newly constructed SV. The
situation can be illustrated with this small script​:

#!/usr/bin/perl
use strict;
use warnings;
use Devel​::Peek;
my %m = (a => 'b');
my $mr = \%m;
Devel​::Peek​::Dump($mr);
print Devel​::Peek​::SvREFCNT(\%m), "\n";

From the Dump you can see that %m \(the PVHV\) has a refcount of

2, but "Devel​::Peek​::SvREFCNT(\%m)" reports 1. The reason for this can
be illustrated by breaking that call up a little bit. One would
normally expect that​:

Devel​::Peek​::SvREFCNT(\%m)

should be equivalent to

my $tmp = \%m;
Devel​::Peek​::SvREFCNT($tmp)

which unsurprisingly reports a refcount of 1 for $tmp. Nothing changes
when $tmp is an immediate, unlabeled value on the argument stack to
SvREFCNT() and I think that's expected and correct behavior.

The proposed patch solves this difficulty by always passing the

argument from Perl by reference and then unconditionally dereferencing
to access the target value."

Patch attached for review.

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=core
severity=low
---
Site configuration information for perl 5.14.2​:

Configured by Debian Project at Fri Apr 12 09​:56​:36 UTC 2013.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration​:

Platform​:
osname=linux, osvers=2.6.32-5-686-bigmem,
archname=i486-linux-gnu-thread-multi-64int
uname='linux murphy 2.6.32-5-686-bigmem #1 smp mon feb 25 01​:53​:47 utc
2013 i686 gnulinux '
config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4
-Wformat -Werror=format-security -Dldflags= -Wl,-z,relro
-Dlddlflags=-shared -Wl,-z,relro -Dcccdlflags=-fPIC
-Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.14
-Darchlib=/usr/lib/perl/5.14 -Dvendorprefix=/usr
-Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5
-Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.14.2
-Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1 -Dman3ext=3perl
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm
-Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib
-Dlibperl=libperl.so.5.14.2 -des'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=define, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN
-fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2 -g',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector
-fno-strict-aliasing -pipe -I/usr/local/include'
ccversion='', gccversion='4.7.2', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long long', ivsize=8, nvtype='double', nvsize=8,
Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries​:
ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
libpth=/usr/local/lib /lib/i386-linux-gnu /lib/../lib
/usr/lib/i386-linux-gnu /usr/lib/../lib /lib /usr/lib
libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
perllibs=-ldl -lm -lpthread -lc -lcrypt
libc=, so=so, useshrplib=true, libperl=libperl.so.5.14.2
gnulibc_version='2.13'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib
-fstack-protector'

Locally applied patches​:

---
@​INC for perl 5.14.2​:
/etc/perl
/usr/local/lib/perl/5.14.2
/usr/local/share/perl/5.14.2
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.14
/usr/share/perl/5.14
/usr/local/lib/site_perl
.

---
Environment for perl 5.14.2​:
HOME=/home/dom
LANG=en_GB.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=~/bin​:/usr/local/bin​:/usr/bin​:/bin​:/usr/local/games​:/usr/games
PERL_BADLANG (unset)
SHELL=/bin/bash

--
Dominic Hargreaves | http​://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)

If you really really need to mess with the refcounts, you might as well use
SvREFCNT directly (although you might want to write wrappers for _inc and
_dec, for sanity's sake)​:

&Internals​::SvREFCNT(\@​etc, 10);
&Internals​::SvREFCNT(\*ENV, 0); # boom

Enjoy your rope!

@p5pRT
Copy link
Author

p5pRT commented Jun 24, 2013

From @tonycoz

On Mon May 13 11​:06​:50 2013, nicholas wrote​:

On Mon, May 13, 2013 at 01​:36​:06PM -0400, bulk88 wrote​:

Nicholas Clark wrote​:

Yes. It's always going to be possible for people to use (or write)
code
to mess with the internals, such as reference counts.

But I'm really not convinced that we should be offering documented
functions
in the default installation which offer such dangerous direct
unguarded
access to the internals. If people want to live dangerously, they
should
at least have to install an appropriate module from CPAN.

Nicholas Clark

The refcount checkers from Perl lang are useful to prove in a test
that
a leak was fixed.

Agree, in that I could see that the perl core is reading reference
counts in
tests to check them. But not changing them. I went for a look with
grep.cpan.me, and as far as I can tell the pretty much only place
doing this
in tests is the perl core. But the core doesn't need to install self-
test
infrastructure, just to have it available during testing.

(That's not an argument that everything must change. Just a thought
that
things are not as constrained as they might seem)

So should we be removing (or deprecating) the SvREFCNT_*() modifiers
from Devel​::Peek, but keep SvREFCNT() itself?

Or nuke them all, since they're available (if deliberately undocumented)
in Internals?

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

On Sun Jun 23 18​:04​:00 2013, tonyc wrote​:

So should we be removing (or deprecating) the SvREFCNT_*() modifiers
from Devel​::Peek, but keep SvREFCNT() itself?

Or nuke them all, since they're available (if deliberately undocumented)
in Internals?

Here's an alternative patch that​:

- removes the modifier functions

- modifies the SvREFCNT() XS function to accept any type of object

- adds a very basic test

Note that the original patch leaked the SV SvREFCNT() returned.

For debate, I'll apply it in a few days unless there's some
overwhelmingly negative response.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

On Thu Jul 11 17​:28​:56 2013, tonyc wrote​:

Here's an alternative patch that​:

This time with the patch.

Thanks, khw.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

0001-perl-117793-remove-dangerous-functions-and-improve-S.patch
From 5eb402dc3f63c00e3839efd02f8bd4ebe64be4d2 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Fri, 12 Jul 2013 10:14:57 +1000
Subject: [PATCH] [perl #117793] remove dangerous functions and improve
 SvREFCNT()

This allows Devel::Peek::SvREFCNT() to work on any variable, not just
scalars, but has a chance of breaking backward compatibility.

Also changes the type of SvREFCNT() to UV to match the type returned by
the underlying macro
---
 ext/Devel-Peek/Peek.pm  |    5 ++---
 ext/Devel-Peek/Peek.xs  |   29 ++++++-----------------------
 ext/Devel-Peek/t/Peek.t |    7 +++++++
 3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/ext/Devel-Peek/Peek.pm b/ext/Devel-Peek/Peek.pm
index 2dacb54..f46864c 100644
--- a/ext/Devel-Peek/Peek.pm
+++ b/ext/Devel-Peek/Peek.pm
@@ -13,7 +13,7 @@ require XSLoader;
 @ISA = qw(Exporter);
 @EXPORT = qw(Dump mstat DeadCode DumpArray DumpWithOP DumpProg
 	     fill_mstats mstats_fillhash mstats2hash runops_debug debug_flags);
-@EXPORT_OK = qw(SvREFCNT SvREFCNT_inc SvREFCNT_dec CvGV);
+@EXPORT_OK = qw(SvREFCNT CvGV);
 %EXPORT_TAGS = ('ALL' => [@EXPORT, @EXPORT_OK]);
 
 XSLoader::load();
@@ -98,8 +98,7 @@ Devel::Peek supplies a C<Dump()> function which can dump a raw Perl
 datatype, and C<mstat("marker")> function to report on memory usage
 (if perl is compiled with corresponding option).  The function
 DeadCode() provides statistics on the data "frozen" into inactive
-C<CV>.  Devel::Peek also supplies C<SvREFCNT()>, C<SvREFCNT_inc()>, and
-C<SvREFCNT_dec()> which can query, increment, and decrement reference
+C<CV>.  Devel::Peek also supplies C<SvREFCNT()> which can query reference
 counts on SVs.  This document will take a passive, and safe, approach
 to data debugging and for that it will describe only the C<Dump()>
 function.
diff --git a/ext/Devel-Peek/Peek.xs b/ext/Devel-Peek/Peek.xs
index e97c979..a8d79f3 100644
--- a/ext/Devel-Peek/Peek.xs
+++ b/ext/Devel-Peek/Peek.xs
@@ -386,31 +386,14 @@ PPCODE:
 	op_dump(PL_main_root);
 }
 
-I32
+U32
 SvREFCNT(sv)
 SV *	sv
-
-# PPCODE needed since otherwise sv_2mortal is inserted that will kill the value.
-
-SV *
-SvREFCNT_inc(sv)
-SV *	sv
-PPCODE:
-{
-    RETVAL = SvREFCNT_inc(sv);
-    PUSHs(RETVAL);
-}
-
-# PPCODE needed since by default it is void
-
-void
-SvREFCNT_dec(sv)
-SV *	sv
-PPCODE:
-{
-    SvREFCNT_dec(sv);
-    PUSHs(sv);
-}
+PROTOTYPE: \[$@%&*]
+CODE:
+    RETVAL = SvREFCNT(SvRV(sv)) - 1; /* -1 because our ref doesn't count */
+OUTPUT:
+    RETVAL
 
 SV *
 DeadCode()
diff --git a/ext/Devel-Peek/t/Peek.t b/ext/Devel-Peek/t/Peek.t
index 5019fb1..79a3fd7 100644
--- a/ext/Devel-Peek/t/Peek.t
+++ b/ext/Devel-Peek/t/Peek.t
@@ -1080,4 +1080,11 @@ do_test('UTF-8 in a regular expression',
     SAVED_COPY = 0x0)?
 ');
 
+{ # perl #117793: Extend SvREFCNT* to work on any perl variable type
+  my %hash;
+  my $base_count = Devel::Peek::SvREFCNT(%hash);
+  my $ref = \%hash;
+  is(Devel::Peek::SvREFCNT(%hash), $base_count + 1, "SvREFCNT on non-scalar");
+}
+
 done_testing();
-- 
1.7.10.4

@p5pRT
Copy link
Author

p5pRT commented Aug 9, 2013

From @tonycoz

On Thu Jul 11 17​:28​:56 2013, tonyc wrote​:

On Sun Jun 23 18​:04​:00 2013, tonyc wrote​:

So should we be removing (or deprecating) the SvREFCNT_*() modifiers
from Devel​::Peek, but keep SvREFCNT() itself?

Or nuke them all, since they're available (if deliberately undocumented)
in Internals?

Here's an alternative patch that​:

- removes the modifier functions

- modifies the SvREFCNT() XS function to accept any type of object

- adds a very basic test

Note that the original patch leaked the SV SvREFCNT() returned.

For debate, I'll apply it in a few days unless there's some
overwhelmingly negative response.

There was no response at all, everyone loves it!

Applied as da1929e.

Tony

@p5pRT
Copy link
Author

p5pRT commented Aug 9, 2013

@tonycoz - Status changed from 'open' 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