[前][次][番号順一覧][スレッド一覧]

ruby-changes:53552

From: shyouhei <ko1@a...>
Date: Fri, 16 Nov 2018 18:04:39 +0900 (JST)
Subject: [ruby-changes:53552] shyouhei:r65768 (trunk): pack.c: cast from double to float can be undefined

shyouhei	2018-11-16 18:04:34 +0900 (Fri, 16 Nov 2018)

  New Revision: 65768

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65768

  Log:
    pack.c: cast from double to float can be undefined
    
    Generally speaking, a value of double is not always representable
    when demoted to a float. ISO C defines what to do when such
    conversion loses precision, but leaves it undefined when the
    value is completely out of range. (cf: ISO/IEC 9899:1990 section
    6.2.1.4).
    
    Because ruby do not have half-precision floating-point types this
    is not a frequent headache but for pack / unpack, there are
    specifiers that has something to do with C float types.  We have
    to explicitly care these situations.

  Modified files:
    trunk/pack.c
Index: pack.c
===================================================================
--- pack.c	(revision 65767)
+++ pack.c	(revision 65768)
@@ -14,6 +14,7 @@ https://github.com/ruby/ruby/blob/trunk/pack.c#L14
 #include <sys/types.h>
 #include <ctype.h>
 #include <errno.h>
+#include <float.h>
 
 /*
  * It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG
@@ -148,6 +149,26 @@ unknown_directive(const char *mode, char https://github.com/ruby/ruby/blob/trunk/pack.c#L149
                mode, unknown, fmt);
 }
 
+static float
+VALUE_to_float(VALUE obj)
+{
+    VALUE v = rb_to_float(obj);
+    double d = RFLOAT_VALUE(v);
+
+    if (isnan(d)) {
+        return NAN;
+    }
+    else if (d < -FLT_MAX) {
+        return -INFINITY;
+    }
+    else if (d <= FLT_MAX) {
+        return d;
+    }
+    else {
+        return INFINITY;
+    }
+}
+
 /*
  *  call-seq:
  *     arr.pack( aTemplateString ) -> aBinaryString
@@ -663,7 +684,7 @@ pack_pack(int argc, VALUE *argv, VALUE a https://github.com/ruby/ruby/blob/trunk/pack.c#L684
 		float f;
 
 		from = NEXTFROM;
-		f = (float)RFLOAT_VALUE(rb_to_float(from));
+                f = VALUE_to_float(from);
 		rb_str_buf_cat(res, (char*)&f, sizeof(float));
 	    }
 	    break;
@@ -673,7 +694,7 @@ pack_pack(int argc, VALUE *argv, VALUE a https://github.com/ruby/ruby/blob/trunk/pack.c#L694
 		FLOAT_CONVWITH(tmp);
 
 		from = NEXTFROM;
-		tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
+                tmp.f = VALUE_to_float(from);
 		HTOVF(tmp);
 		rb_str_buf_cat(res, tmp.buf, sizeof(float));
 	    }
@@ -704,7 +725,7 @@ pack_pack(int argc, VALUE *argv, VALUE a https://github.com/ruby/ruby/blob/trunk/pack.c#L725
 	    while (len-- > 0) {
 		FLOAT_CONVWITH(tmp);
 		from = NEXTFROM;
-		tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
+                tmp.f = VALUE_to_float(from);
 		HTONF(tmp);
 		rb_str_buf_cat(res, tmp.buf, sizeof(float));
 	    }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]