[#1094] Re: [ruby-cvs] ruby, ruby/lib: * eval.c (ev_const_defined, ev_const_get), variable.c — Dave Thomas <dave@...>

> * eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;

12 messages 2003/05/29
[#1095] Re: [ruby-cvs] ruby, ruby/lib: * eval.c (ev_const_defined, ev_const_get), variable.c — nobu.nokada@... 2003/05/29

Hi,

Re: Isn't NUM2UINT broken for 64-bit?

From: nobu.nokada@...
Date: 2003-05-29 20:26:07 UTC
List: ruby-core #1100
Hi,

At Fri, 30 May 2003 02:32:25 +0900,
lyle@knology.net <lyle@knology.net> wrote:
> The problem with this is that if you pass in a Ruby Integer that is greater
> than the maximum value for a *signed* integer, the conversion fails, since
> both rb_fix2int() and rb_num2int() compare their inputs to INT_MAX. I am
> specifically seeing this problem for the value (2**32 - 1), which is in
> range for unsigned integers, but I suppose it will happen for any Integer
> greater than INT_MAX.
> 
> Is this a bug, or am I missing something?

I guess it's a bug.


Index: ruby.h
===================================================================
RCS file: /cvs/ruby/src/ruby/ruby.h,v
retrieving revision 1.80
diff -u -2 -p -r1.80 ruby.h
--- ruby.h	20 May 2003 06:29:21 -0000	1.80
+++ ruby.h	29 May 2003 20:25:00 -0000
@@ -242,6 +242,8 @@ int rb_num2int _((VALUE));
 int rb_fix2int _((VALUE));
 #define FIX2INT(x) rb_fix2int((VALUE)x)
-#define NUM2UINT(x) ((unsigned int)NUM2INT(x))
-#define FIX2UINT(x) ((unsigned int)FIX2INT(x))
+unsigned int rb_num2uint _((VALUE));
+#define NUM2UINT(x) rb_num2uint(x)
+unsigned int rb_fix2uint _((VALUE));
+#define FIX2UINT(x) rb_fix2uint(x)
 #else
 #define NUM2INT(x) ((int)NUM2LONG(x))
Index: numeric.c
===================================================================
RCS file: /cvs/ruby/src/ruby/numeric.c,v
retrieving revision 1.87
diff -u -2 -p -r1.87 numeric.c
--- numeric.c	19 May 2003 05:41:07 -0000	1.87
+++ numeric.c	29 May 2003 20:21:51 -0000
@@ -1001,4 +1001,31 @@ rb_num2ulong(val)
 
 #if SIZEOF_INT < SIZEOF_LONG
+static void
+check_int(num)
+    long num;
+{
+    const char *s;
+
+    if (num < INT_MIN) {
+	s = "small";
+    }
+    else if (num > INT_MAX) {
+	s = "big";
+    }
+    else {
+	return;
+    }
+    rb_raise(rb_eRangeError, "integer %ld too %s to convert to `int'", num, s);
+}
+
+static void
+check_uint(num)
+    unsigned long num;
+{
+    if (num > INT_MAX) {
+	rb_raise(rb_eRangeError, "integer %lu too big to convert to `int'", num);
+    }
+}
+
 int
 rb_num2int(val)
@@ -1007,7 +1034,5 @@ rb_num2int(val)
     long num = rb_num2long(val);
 
-    if (num < INT_MIN || INT_MAX < num) {
-	rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
-    }
+    check_int(num);
     return (int)num;
 }
@@ -1019,7 +1044,25 @@ rb_fix2int(val)
     long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
 
-    if (num < INT_MIN || INT_MAX < num) {
-	rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
-    }
+    check_int(num);
+    return (int)num;
+}
+
+unsigned int
+rb_num2uint(val)
+    VALUE val;
+{
+    unsigned long num = rb_num2ulong(val);
+
+    check_uint(num);
+    return (int)num;
+}
+
+unsigned int
+rb_fix2int(val)
+    VALUE val;
+{
+    unsigned long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2ulong(val);
+
+    check_uint(num);
     return (int)num;
 }


-- 
Nobu Nakada

In This Thread