supercollider / supercollider

An audio server, programming language, and IDE for sound synthesis and algorithmic composition.
http://supercollider.github.io
GNU General Public License v3.0
5.52k stars 750 forks source link

Integer overflow on different OSes (4294967296) #3489

Closed prko closed 6 years ago

prko commented 6 years ago

Bug description: 4294967296 returns different result under macOS and Windows. Steps to reproduce:

  1. type 4294967296 in SC 3.9 under Windows
  2. evaluate it
  3. type 4294967296 in SC 3.9 under macOS
  4. evaluate it

Actual result: Under macOS, the result is 0. However, the result is 2147483647 under Windows.

Expected result: According to the help document of the integer class,

A 32 bit signed integer can represent values in the range -2147483648 to 2147483647. Adding up further returns in a wrapped result, so that and 2147483647+1= -2147483648.

Under macOS, the result seems to be correct, but the result seems not to be correct under Windows.

I know the integer can correctly represent values in the range -2147483648 to 2147483647, but it is strange to me that the results are different between two systems.

mossheim commented 6 years ago

Undefined behavior doesn't have to produce consistent results. My understanding of the quote you posted is that integers wrap and overflow when added together. It says nothing about the behavior of out of range literals.

prko commented 6 years ago

Undefined behavior doesn't have to produce consistent results.

Ah! Thank you. Then it cannot be a bug.

prko commented 6 years ago

Hm, but the results under macOS seem to be consistent while the results under Windows seem to be inconsistent:

2147483647
-> 2147483647 // macOS
-> 2147483647 // Windows

2147483648
-> -2147483648 // macOS
-> 2147483647 // Windows

2147483649
-> -2147483647 // macOS
-> 2147483647 // Windows

-2147483648
-> -2147483648 // macOS
-> -2147483647 // Windows

-2147483649
-> 2147483647 // macOS
-> -2147483647 // Windows

-2147483650
-> 2147483646 // macOS
-> -2147483647 // Windows
mossheim commented 6 years ago

How is this any different from the original report?

I think the main problem is that the parser is being too permissive. Out of bounds literals is an easy gotcha and serves no real purpose. I would prefer tightening up the interpreter's behavior here to making clearly undefined behavior behave the same across binaries.

prko commented 6 years ago

How is this any different from the original report?

just more examples. My two reports are theoretically not different.

I understand "2147483647+1" is different from "2147483648". What I have been being confused is that sclang under macOS treats "2147483648" just like "2147483647+1" while sclang under windows does not...

I now understand that the undefined behaviour must not have to produce consistent results. However, it might be confusing for some users who are not computer scientists.

Out of bounds literals is an easy gotcha and serves no real purpose.

I also think that I will never use such a big number greater than 2147483648, but I have been curious about the reason of the inconsistent results under different OSes while understanding the range of the integer in sclang.

Now, this makes me not confused, so I am happy now. Thank you!

mossheim commented 6 years ago

However, it might be confusing for some users who are not computer scientists.

Yes, definitely, which is why I think out of range literals should be disallowed.

I just did a quick survey:

C compilers typically give a warning in this case ("narrowing conversion"). Swift, Haskell, C#, Java, ML, and D fail. Swift gives a warning, Rust doesn't say anything. Python and Ruby don't have this problem because it's got built-in long ints. JS doesn't have integers, everything is float (shudder).

patrickdupuis commented 6 years ago

Rust doesn't say anything

Really? The Rust compiler is all about telling you where you've made mistakes. I find this really surprising.

Patrick


From: Brian Heim notifications@github.com Sent: February 4, 2018 6:26 PM To: supercollider/supercollider Cc: Subscribed Subject: Re: [supercollider/supercollider] Integer overflow on different OSes (4294967296) (#3489)

However, it might be confusing for some users who are not computer scientists.

Yes, definitely, which is why I think out of range literals should be disallowed.

I just did a quick survey:

C compilers typically give a warning in this case ("narrowing conversion"). Swift, Haskell, C#, Java, ML, and D fail. Swift gives a warning, Rust doesn't say anything. Python and Ruby don't have this problem because it's got built-in long ints. JS doesn't have integers, everything is float (shudder).

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/supercollider/supercollider/issues/3489#issuecomment-362949480, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ALNCHqtLFpdQgI4lBLsz2yCBA2zy5lGPks5tRjySgaJpZM4R4lZX.

mossheim commented 6 years ago

OK, just tried locally and I do get a warning (#[warn(overflowing_literals)]). It doesn't appear on godbolt for some reason, huh

patrickdupuis commented 6 years ago

That's what I would expect. Don't you just ❤ Rust? (that being said, I need to actually write something in Rust)


From: Brian Heim notifications@github.com Sent: February 4, 2018 6:58 PM To: supercollider/supercollider Cc: Patrick Dupuis; Comment Subject: Re: [supercollider/supercollider] Integer overflow on different OSes (4294967296) (#3489)

OK, just tried locally and I do get a warning (#[warn(overflowing_literals)]). It doesn't appear on godbolt for some reason, huh

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/supercollider/supercollider/issues/3489#issuecomment-362951348, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ALNCHkvxbjqSjcHIXA4h-rN9j3bRVucRks5tRkQSgaJpZM4R4lZX.

mossheim commented 6 years ago

That's what I would expect. Don't you just ❤ Rust? (that being said, I need to actually write something in Rust)

lol. But does rust have email chains with 1000s of messages about which build tool to use?

patrickdupuis commented 6 years ago

That sounds horrible 😞

vivid-synth commented 6 years ago

While we're sticking up for our favorite languages, Haskell has built-in support for long ints, too. You should see no problem with 4294967296 :: Integer

Thanks for thoroughly checking so many languages though, @brianlheim !

vivid-synth commented 6 years ago

Also @patrickdupuis here's some background on why Rust doesn't check for overflow by default: https://mail.mozilla.org/pipermail/rust-dev/2014-June/010363.html

mossheim commented 6 years ago

here's some background on why Rust doesn't check for overflow by default:

IIUC that message talks about why Rust won't check for overflow at runtime; the warning Patrick and I were talking about (which is enabled by default) warns on overflows at compile time.

prko commented 6 years ago

Is it possible automatically to convert the type of the data (thus the class as well) from integer to float if sclang detects an overflow of an integer?

sclang has already a similar conversion: for example, the following code 2**1 converts its data type (in this case, its class as well) into a float.

( I am not sure if the operator ** converts the data type or the class. To me, it seems to be changed both of them. )

Thus, I think sclang can have the feature to automatically decide the class (or the data type) of out of range literals.

mossheim commented 6 years ago

Is it possible automatically to convert the type of the data (thus the class as well) from integer to float if sclang detects an overflow of an integer?

Automatic conversion is a great way to give people unwelcome surprises, that's probably one of the reasons none of the dozen languages I mentioned above do it. In addition:

  1. with what you're proposing overflowing literals would convert, while overflowing integer operations wouldn't
  2. if they did, then you'd likely break a tonne of code
  3. it introduces new opportunities for type errors
  4. you can just add .0 to the end of the literal

To me, it seems to be changed both of them.

2 and 1 are both integer literals at compile time. ** is a method on numbers that produces a float.

prko commented 6 years ago

Ah.. Thank you!

mossheim commented 6 years ago

I am closing this and opening a new issue for a compiler warning.