diff options
author | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-15 06:17:53 +0000 |
---|---|---|
committer | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-15 06:17:53 +0000 |
commit | f98004c0f2f0b9234981af49d6b6566c37cc8c2d (patch) | |
tree | 68a7875c027c6dd1c1379db423f2afcad74e9c31 | |
parent | ef5eacc0e004d2b7969fdfe5a2c67f16d13bcfb6 (diff) | |
download | ruby-f98004c0f2f0b9234981af49d6b6566c37cc8c2d.tar.gz |
hash.c: cast from double to unsigned is undefined
When a negative double is casted into an unsigned type, that operation
is undefined (cf: ISO/IEC 9899:1990 section 6.2.9.3). Recent versions
of C kindly footnotes that "The remaindering operation performed when
a value of integer type is converted to unsigned type need not be
performed when a value of real floating type is converted to unsigned
type" (cf: ISO/IEC 9899:1999 section 6.3.1.4 footnote 50).
So it is a wrong idea to just cast a double to st_data_t.
The intention of the code is commented as "mix the actual float value
in". It seems we should do a reinterpret_cast and rule out
static_cast.
Confirmed this changeset does not affect `make benchmark`.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65737 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | hash.c | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -293,7 +293,9 @@ rb_ident_hash(st_data_t n) * many integers get interpreted as 2.0 or -2.0 [Bug #10761] */ if (FLONUM_P(n)) { - n ^= (st_data_t)rb_float_value(n); + union { double d; st_data_t i; } u; + u.d = rb_float_value(n); + n ^= u.i; } #endif |