Perl / perl5

šŸŖ The Perl programming language
https://dev.perl.org/perl5/
Other
1.91k stars 542 forks source link

srand(()) weirdness (note the empty list) #13993

Closed p5pRT closed 9 years ago

p5pRT commented 10 years ago

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

Searchable as RT122351$

p5pRT commented 10 years ago

From @demerphq

Older perls misparse srand(())​:

blead​:/git_tree/perl$ perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. 0 but true

Blead does things differently\, but still not quite right\, why the uninitialized warning? and why the integer overflow warning?

blead​:/git_tree/perl$ ./perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. Integer overflow in srand at -e line 1. 18446744073709551615

Yves

Perls​:

$ perl -v

This is perl 5\, version 14\, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi (with 80 registered patches\, see perl -V for more detail)

$ ./perl -v

This is perl 5\, version 21\, subversion 2 (v5.21.2 (v5.21.1-192-gb6fbfd4*)) built for x86_64-linux (with 32 registered patches\, see perl -V for more detail)

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 10 years ago

From @druud62

On 2014-07-21 10​:27\, yves orton wrote​:

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

Older perls misparse srand(())​:

blead​:/git_tree/perl$ perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. 0 but true

Blead does things differently\, but still not quite right\, why the uninitialized warning? and why the integer overflow warning?

blead​:/git_tree/perl$ ./perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. Integer overflow in srand at -e line 1. 18446744073709551615

Yves

Perls​:

$ perl -v

This is perl 5\, version 14\, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi (with 80 registered patches\, see perl -V for more detail)

$ ./perl -v

This is perl 5\, version 21\, subversion 2 (v5.21.2 (v5.21.1-192-gb6fbfd4*)) built for x86_64-linux (with 32 registered patches\, see perl -V for more detail)

I hit that issue with code like​:

  my $seed = srand( DEBUG ? 42 : () );

which I then rewrote to​:

  my $seed = DEBUG ? srand(42) : srand;

perl5.14.2 -wE'   sub f (;$) { say scalar @​_ }   f();   f(()); ' 0 1

-- Greetings\, Ruud

p5pRT commented 10 years ago

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

p5pRT commented 10 years ago

From @iabyn

On Mon\, Jul 21\, 2014 at 01​:27​:36AM -0700\, yves orton wrote​:

Blead does things differently\, but still not quite right\, why the uninitialized warning? and why the integer overflow warning?

blead​:/git_tree/perl$ ./perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. Integer overflow in srand at -e line 1. 18446744073709551615

In blead\, srand(()) is treated the same as srand(undef)\, which explains the undef warning.

There is similar behaviour with sleep(()).

srand coerces its arg to a string before calling grok_number() on it. An undef value is coerced to ""\, which decides it's not IS_NUMBER_IN_UV so prints a warning about integer overflow and sets the seed to to UV_MAX.

I have no idea why srand() does grok_number(SvPV(sv)) rather than SvUV(sv) and whether this is correct or not.

-- This email is confidential\, and now that you have read it you are legally obliged to shoot yourself. Or shoot a lawyer\, if you prefer. If you have received this email in error\, place it in its original wrapping and return for a full refund. By opening this email\, you accept that Elvis lives.

p5pRT commented 10 years ago

From @demerphq

On 21 July 2014 17​:46\, Dave Mitchell \davem@&#8203;iabyn\.com wrote​:

On Mon\, Jul 21\, 2014 at 01​:27​:36AM -0700\, yves orton wrote​:

Blead does things differently\, but still not quite right\, why the uninitialized warning? and why the integer overflow warning?

blead​:/git_tree/perl$ ./perl -wle'print srand(())' Use of uninitialized value in srand at -e line 1. Integer overflow in srand at -e line 1. 18446744073709551615

In blead\, srand(()) is treated the same as srand(undef)\, which explains the undef warning.

There is similar behaviour with sleep(()).

srand coerces its arg to a string before calling grok_number() on it. An undef value is coerced to ""\, which decides it's not IS_NUMBER_IN_UV so prints a warning about integer overflow and sets the seed to to UV_MAX.

I have no idea why srand() does grok_number(SvPV(sv)) rather than SvUV(sv) and whether this is correct or not.

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 10 years ago

From @bulk88

On Mon Jul 21 08​:47​:21 2014\, davem wrote​:

srand coerces its arg to a string before calling grok_number() on it. An undef value is coerced to ""\, which decides it's not IS_NUMBER_IN_UV so prints a warning about integer overflow and sets the seed to to UV_MAX.

I have no idea why srand() does grok_number(SvPV(sv)) rather than SvUV(sv) and whether this is correct or not.

https://rt-archive.perl.org/perl5/Ticket/Display.html?id=40605 http​://perl5.git.perl.org/perl.git/commitdiff/f914a68295eedf2aa19e258317bc5955132805b4

I guess it is to prohibit negatives\, NAN\, and floats.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 10 years ago

From @ikegami

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240   REFCNT = 1   FLAGS = ()

p5pRT commented 10 years ago

From @demerphq

On 22 July 2014 21​:14\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240 REFCNT = 1 FLAGS = ()

Interesting. Thanks. That does make sense\, in a sad way.

Cheers\, Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 10 years ago

From @rjbs

* demerphq \demerphq@&#8203;gmail\.com [2014-07-22T15​:18​:38]

Interesting. Thanks. That does make sense\, in a sad way.

Saving that quote for use on many future explanations of weird behaviors.

-- rjbs

p5pRT commented 9 years ago

From @cpansprout

On Tue Jul 22 12​:18​:59 2014\, demerphq wrote​:

On 22 July 2014 21​:14\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240 REFCNT = 1 FLAGS = ()

Interesting. Thanks. That does make sense\, in a sad way.

I see no other way for this to work. Can we close this as not-a-bug?

--

Father Chrysostomos

p5pRT commented 9 years ago

From @tonycoz

On Tue Oct 21 21​:44​:12 2014\, sprout wrote​:

On Tue Jul 22 12​:18​:59 2014\, demerphq wrote​:

On 22 July 2014 21​:14\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240 REFCNT = 1 FLAGS = ()

Interesting. Thanks. That does make sense\, in a sad way.

I see no other way for this to work. Can we close this as not-a-bug?

I agree\, closing.

Tony

p5pRT commented 9 years ago

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

p5pRT commented 9 years ago

From @demerphq

On 22 October 2014 06​:44\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

On Tue Jul 22 12​:18​:59 2014\, demerphq wrote​:

On 22 July 2014 21​:14\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240 REFCNT = 1 FLAGS = ()

Interesting. Thanks. That does make sense\, in a sad way.

I see no other way for this to work. Can we close this as not-a-bug?

We could remove the unnecessary prototype.

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 9 years ago

From @demerphq

On 23 October 2014 05​:33\, Tony Cook via RT \perlbug\-followup@&#8203;perl\.org wrote​:

On Tue Oct 21 21​:44​:12 2014\, sprout wrote​:

On Tue Jul 22 12​:18​:59 2014\, demerphq wrote​:

On 22 July 2014 21​:14\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Mon\, Jul 21\, 2014 at 12​:08 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

The part I consider the most serious bug is that srand(()) or sleep(()) are treated the same as srand(undef) or sleep(undef). That is an empty list\, it should not be treated as a value.

perl -E"say prototype 'CORE​::sleep'" ;$

It's Perl's stupid prototypes. ($) means "one argument evaluated in scalar context"\, so (;$) means "no arguments or one evaluated in scalar context".

perl -E"sub x(;$) { say 0+@​_; } x(());" 1

A stub in scalar context is undef.

perl -MDevel​::Peek -e"$x = (); Dump($x);" SV = NULL(0x0) at 0x229240 REFCNT = 1 FLAGS = ()

Interesting. Thanks. That does make sense\, in a sad way.

I see no other way for this to work. Can we close this as not-a-bug?

I agree\, closing.

I dont agree. We can remove or fix the prototype.

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 9 years ago

From @cpansprout

On Thu Oct 23 00​:23​:43 2014\, demerphq wrote​:

I dont agree. We can remove or fix the prototype.

We have backward-compatibility to take into account. Removing the prototype from any built-in function that uses $ would change the context in which the argument is evaluated. (I am speaking loosely here. Built-in keywords donā€™t actually use the prototype for parsing\, but the basic concept is the same.)

Changing () in scalar-argument context also has ramifications for backward-compatibility. Currently you can do is(()\, undef)\, to see what () becomes in scalar context. Would you have the () elided completely? Or would it happen only if () is the sole argument?

Do you have any valid use cases for srand(())\, or is this just something that surprised you?

--

Father Chrysostomos

p5pRT commented 9 years ago

From @demerphq

On 23 October 2014 23​:54\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

On Thu Oct 23 00​:23​:43 2014\, demerphq wrote​:

I dont agree. We can remove or fix the prototype.

We have backward-compatibility to take into account. Removing the prototype from any built-in function that uses $ would change the context in which the argument is evaluated. (I am speaking loosely here. Built-in keywords donā€™t actually use the prototype for parsing\, but the basic concept is the same.)

Changing () in scalar-argument context also has ramifications for backward-compatibility. Currently you can do is(()\, undef)\, to see what () becomes in scalar context. Would you have the () elided completely? Or would it happen only if () is the sole argument?

Do you have any valid use cases for srand(())\, or is this just something that surprised you?

This type of code is buggy due to this behavior​:

my $x=0; $y=1234; print srand($x ? $y : ())

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 9 years ago

From @ikegami

On Thu\, Oct 23\, 2014 at 3​:23 AM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

I dont agree. We can remove or fix the prototype.

Of what? Most builtins have a prototype

$ perl -wE'say substr("abcdef"\, 2\, 3)' cde

$ perl -wE'say substr("abcdef"\, 2)' cdef

$ perl -wE'my $y=3; say substr("abcdef"\, 2\, $ARGV[0]?$y​:())' 0 Use of uninitialized value in substr at -e line 1.

$

p5pRT commented 9 years ago

From @demerphq

On 24 October 2014 14​:30\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Thu\, Oct 23\, 2014 at 3​:23 AM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

I dont agree. We can remove or fix the prototype.

Of what? Most builtins have a prototype

$ perl -wE'say substr("abcdef"\, 2\, 3)' cde

$ perl -wE'say substr("abcdef"\, 2)' cdef

$ perl -wE'my $y=3; say substr("abcdef"\, 2\, $ARGV[0]?$y​:())' 0 Use of uninitialized value in substr at -e line 1.

If we had a prototype that said "scalar or empty-list" then we could use it to fix srand().

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 9 years ago

From Eirik-Berg.Hanssen@allverden.no

On Fri\, Oct 24\, 2014 at 2​:34 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

If we had a prototype that said "scalar or empty-list" then we could use it to fix srand().

  Yet another contex? A "scalar-or-list-context"? What shold wantarray return within this context?

  Nah\, just do what we always do when a prototype gets in the way of what we're trying to do. Bypass it​:

my $x=0; $y=1234; print &CORE​::srand($x ? $y : ());

  There you go. List context. :)

Eirik

p5pRT commented 9 years ago

From @jhi

Yet another contex? A "scalar-or-list-context"? What shold wantarray return within this context?

1.5?

\

Eirik

-- There is this special biologist word we use for 'stable'. It is 'dead'. -- Jack Cohen

p5pRT commented 9 years ago

From Eirik-Berg.Hanssen@allverden.no

On Fri\, Oct 24\, 2014 at 3​:52 PM\, Jarkko Hietaniemi \jhi@&#8203;iki\.fi wrote​:

Yet another contex? A "scalar-or-list-context"? What shold wantarray return within this context?

1.5?

  IOW\, true?

\

  ;-)

Eirik

p5pRT commented 9 years ago

From @ikegami

On Fri\, Oct 24\, 2014 at 8​:34 AM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

On 24 October 2014 14​:30\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Thu\, Oct 23\, 2014 at 3​:23 AM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

I dont agree. We can remove or fix the prototype.

Of what? Most builtins have a prototype

$ perl -wE'say substr("abcdef"\, 2\, 3)' cde

$ perl -wE'say substr("abcdef"\, 2)' cdef

$ perl -wE'my $y=3; say substr("abcdef"\, 2\, $ARGV[0]?$y​:())' 0 Use of uninitialized value in substr at -e line 1.

If we had a prototype that said "scalar or empty-list" then we could use it to fix srand().

But not substr\, which has the exact same problem.

p5pRT commented 9 years ago

From @demerphq

On 24 October 2014 15​:23\, Eirik Berg Hanssen \< Eirik-Berg.Hanssen@​allverden.no> wrote​:

On Fri\, Oct 24\, 2014 at 2​:34 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

If we had a prototype that said "scalar or empty-list" then we could use it to fix srand().

Yet another contex? A "scalar-or-list-context"? What shold wantarray return within this context?

Nah\, just do what we always do when a prototype gets in the way of what we're trying to do. Bypass it​:

my $x=0; $y=1234; print &CORE​::srand($x ? $y : ());

There you go. List context. :)

While I get your point\, my problem here is that when this issue comes up\, it comes up in such a way that Perl does *exactly* the wrong thing\, and possibly the worst wrong thing it could do.

So\, if we aren't going to fix this we need to document this trap in perlfunc.

Yves

p5pRT commented 9 years ago

From @ikegami

On Fri\, Oct 24\, 2014 at 12​:01 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

While I get your point\, my problem here is that when this issue comes up\, it comes up in such a way that Perl does *exactly* the wrong thing\, and possibly the worst wrong thing it could do.

If that's the problem\, the more robust solution would be to make srand(undef) a fatal error rather than a warning.

p5pRT commented 9 years ago

From @jandubois

On Fri\, Oct 24\, 2014 at 6​:23 AM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@&#8203;allverden\.no wrote​:

On Fri\, Oct 24\, 2014 at 2​:34 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

If we had a prototype that said "scalar or empty-list" then we could use it to fix srand().

Yet another contex? A "scalar-or-list-context"? What shold wantarray return within this context?

You don't really need another prototype; they are not really being used for builtin functions anyways. So srand() could just be implemented so that an empty list argument would be treated the same as no argument\, to provide the DWIM behavior.

Just for the record\, I'm *not* in favor of having even more builtins whose functionality couldn't be implemented in a Perl level CORE​::GLOBAL​::* override implementation\, but there is some precedence for it. E.g. CORE​::unlink\, which has a prototype of '@​' but still handles unlink() and unlink(()) differently​:

unlink(); # same as unlink($_) unlink(()); # does nothing

This behavior does make sense (DWIM) as long as you don't think too much about how it might be implemented.

Cheers\, -Jan

p5pRT commented 9 years ago

From Eirik-Berg.Hanssen@allverden.no

On Fri\, Oct 24\, 2014 at 7​:24 PM\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Fri\, Oct 24\, 2014 at 12​:01 PM\, demerphq \demerphq@&#8203;gmail\.com wrote​:

While I get your point\, my problem here is that when this issue comes up\, it comes up in such a way that Perl does *exactly* the wrong thing\, and possibly the worst wrong thing it could do.

If that's the problem\, the more robust solution would be to make srand(undef) a fatal error rather than a warning.

  While you're at it\, consider making srand("") and srand("a4") (and other non-numerical values) behave equally sensibly.

$ perl -wE 'say srand($_) for undef\, ""\, "a4"\, "0x09"\, "0"' Use of uninitialized value $_ in srand at -e line 1. Integer overflow in srand at -e line 1. 18446744073709551615 Integer overflow in srand at -e line 1. 18446744073709551615 Integer overflow in srand at -e line 1. 18446744073709551615 Integer overflow in srand at -e line 1. 18446744073709551615 0 but true $

  I mean\, those are all (except for that last amusing case) equally useless\, right?

Eirik

p5pRT commented 9 years ago

From @ikegami

On Fri\, Oct 24\, 2014 at 1​:45 PM\, Jan Dubois \jand@&#8203;activestate\.com wrote​:

You don't really need another prototype; they are not really being used for builtin functions anyways.

It allows them to be overridden.

p5pRT commented 9 years ago

From @ikegami

On Fri\, Oct 24\, 2014 at 2​:05 PM\, Eirik Berg Hanssen \< Eirik-Berg.Hanssen@​allverden.no> wrote​:

I mean\, those are all (except for that last amusing case) equally useless\, right?

A warning is fine for useless. (Though they're not exactly useless.) That's not the point.

demerphq is worried about the danger of setting the seed to something known when intending to set the seed to something random.

p5pRT commented 9 years ago

From Eirik-Berg.Hanssen@allverden.no

On Fri\, Oct 24\, 2014 at 9​:01 PM\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Fri\, Oct 24\, 2014 at 2​:05 PM\, Eirik Berg Hanssen \Eirik\-Berg\.Hanssen@&#8203;allverden\.no wrote​:

I mean\, those are all (except for that last amusing case) equally useless\, right?

A warning is fine for useless. (Though they're not exactly useless.) That's not the point.

demerphq is worried about the danger of setting the seed to something known when intending to set the seed to something random.

  Well\, sure\, but aren't you're assuming intentions here? If they pass undef\, you assume they intended to set the seed to something random\, but if they pass (say) the empty string\, you assume they didn't?

  Or\, more interestingly\, perhaps; here you assume they intended to set the seed to something random​:

my $x=0; $y=1234; print srand($x ? $y : ())

  Whereas here\, you assume they intended to set the seed to something known​:

my $x=0; $y=1234; print srand( ($y) x $x );

  (Yes\, that argument evaluates to the empty string.)

Eirik