From f98004c0f2f0b9234981af49d6b6566c37cc8c2d Mon Sep 17 00:00:00 2001 From: shyouhei Date: Thu, 15 Nov 2018 06:17:53 +0000 Subject: [PATCH] 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 --- hash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hash.c b/hash.c index 83ed66d530..fc30ae9cbc 100644 --- a/hash.c +++ b/hash.c @@ -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