Skip Menu |

This queue is for tickets about the version CPAN distribution.

Report information
The Basics
Id: 81294
Status: resolved
Priority: 0/
Queue: version

People
Owner: Nobody in particular
Requestors: 'spro^^*%*^6ut# [...] &$%*c
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Memory leak with fatal warnings
The ‘Integer overflow in version’ warning from scan_version causes a memory leak if fatal warnings are enabled. Run this ‘one’-liner and watch the memory usage: $ ./perl -Ilib -Mwarnings=FATAL,all -e 'warn $$; while (1) { new version "v111111111111111111111111111111" }'
On Tue Nov 20 02:23:37 2012, SPROUT wrote: Show quoted text
> The ‘Integer overflow in version’ warning from scan_version causes a > memory leak if fatal > warnings are enabled. > > Run this ‘one’-liner and watch the memory usage: > > $ ./perl -Ilib -Mwarnings=FATAL,all -e 'warn $$; while (1) { new > version > "v111111111111111111111111111111" }'
Having a hard time with this one. Still looking at it... John
On Wed Mar 06 19:18:55 2013, JPEACOCK wrote: Show quoted text
> On Tue Nov 20 02:23:37 2012, SPROUT wrote:
> > The ‘Integer overflow in version’ warning from scan_version causes a > > memory leak if fatal > > warnings are enabled. > > > > Run this ‘one’-liner and watch the memory usage: > > > > $ ./perl -Ilib -Mwarnings=FATAL,all -e 'warn $$; while (1) { new > > version > > "v111111111111111111111111111111" }'
> > Having a hard time with this one. Still looking at it...
Something like ENTER; ... SAVEFREEPV(some string that needs to be freed); ... SAVEFREESV(some scalar that needs to be freed); ... LEAVE; should do the trick. I haven’t looked at the code too closely. If you need to countermand a SAVEFREESV, you can simply SvREFCNT_inc. If you need to countermand a SAVEFREEPV, it is a little trickier and requires an SV wrapper; SV *wrapper = newSV_type(SVt_PV); SvPV_set(wrapper, that_pv); SvLEN_set(wrapper, 1); /* any non-zero will do */ SAVEFREESV(wrapper); Countermand it with SvLEN_set(wrapper,0);
On Sun Sep 08 02:41:37 2013, SPROUT wrote: Show quoted text
> On Wed Mar 06 19:18:55 2013, JPEACOCK wrote:
> > On Tue Nov 20 02:23:37 2012, SPROUT wrote:
> > > The ‘Integer overflow in version’ warning from scan_version causes > > > a > > > memory leak if fatal > > > warnings are enabled. > > > > > > Run this ‘one’-liner and watch the memory usage: > > > > > > $ ./perl -Ilib -Mwarnings=FATAL,all -e 'warn $$; while (1) { new > > > version > > > "v111111111111111111111111111111" }'
> > > > Having a hard time with this one. Still looking at it...
> > Something like > > ENTER; > ... > SAVEFREEPV(some string that needs to be freed); > ... > SAVEFREESV(some scalar that needs to be freed); > ... > LEAVE; > > should do the trick. I haven’t looked at the code too closely. > > If you need to countermand a SAVEFREESV, you can simply SvREFCNT_inc. > > If you need to countermand a SAVEFREEPV, it is a little trickier and > requires an SV wrapper; > > SV *wrapper = newSV_type(SVt_PV); > SvPV_set(wrapper, that_pv); > SvLEN_set(wrapper, 1); /* any non-zero will do */ > SAVEFREESV(wrapper); > > Countermand it with SvLEN_set(wrapper,0);
This will actually be a little trickier than that. scan_version frees its buffer on error. toke.c’s S_force_strict_version passes a pointer that is not the start of a buffer. It can trigger the fatal warning: $ ./perl -Ilib -e 'use warnings FATAL=>all; package Foo v1111111111111111111111111111.1.1' Integer overflow in version at -e line 1.
On Mon Sep 09 02:37:10 2013, SPROUT wrote: Show quoted text
> > This will actually be a little trickier than that. scan_version frees > its buffer on error. toke.c’s S_force_strict_version passes a pointer > that is not the start of a buffer. It can trigger the fatal warning: > > $ ./perl -Ilib -e 'use warnings FATAL=>all; package Foo > v1111111111111111111111111111.1.1' > Integer overflow in version at -e line 1.
That is a problem. The docs for scan_version say /* =for apidoc scan_version Returns a pointer to the next character after the parsed version string, as well as upgrading the passed in SV to an RV. Function must be called with an already existing SV like sv = newSV(0); s = scan_version(s, SV *sv, bool qv); Performs some preprocessing to the string to ensure that it has the correct characteristics of a version. Flags the object if it contains an underscore (which denotes this is an alpha version). The boolean qv denotes that the version should be interpreted as if it had multiple decimals, even if it doesn't. =cut */ --------------------------- with an autogen proto of "const char* scan_version(const char *s, SV *rv, bool qv)". What if arg s is alloca mem or non-Newx memory? Calling Safefree on alloca mem/C auto car array or some other non-Perl memory allocator's block is bad. Newx != malloc on Win32.
In scan_version at https://bitbucket.org/jpeacock/version/src/9f49d95d787c38ad5b6fcdab71f1ce7c95a1b3d3/vutil/vutil.c?at=default#cl-399 AvFILLp should be used instead of av_len since av can't be magical at this point since it was just created. At https://bitbucket.org/jpeacock/version/src/9f49d95d787c38ad5b6fcdab71f1ce7c95a1b3d3/vutil/vutil.c?at=default#cl-435 "if ( *s == 'u' && strEQ(s,"undef") ) {" strEQ shouldn't test char "u" again, just test s+1 and "ndef".
Fixed in 0.9907