From 7df46a4493ea5b261aab64d482a840fbd57ffcca Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 22 Jan 2004 18:06:38 +0000 Subject: * pack.c (num2i32): pack should not raise RangeError. [ruby-dev:22654] * pack.c (pack_pack): do not auto convert nil to zero. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5542 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++- bignum.c | 30 ++++++++++---- object.c | 15 ++++--- pack.c | 108 +++++++++---------------------------------------- test/ruby/test_pack.rb | 4 ++ 5 files changed, 64 insertions(+), 103 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ef429d1df..72be744510 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,15 @@ +Fri Jan 23 02:26:30 2004 Yukihiro Matsumoto + + * pack.c (num2i32): pack should not raise RangeError. + [ruby-dev:22654] + + * pack.c (pack_pack): do not auto convert nil to zero. + Thu Jan 22 22:54:53 2004 Shugo Maeda * lib/net/imap.rb (BEG_REGEXP): allow 8-bit characters in quoted - strings for Novell GroupWise Internet Agent. + strings for Novell GroupWise Internet Agent. + * lib/net/imap.rb (DATA_REGEXP): ditto. Thu Jan 22 18:35:49 2004 WATANABE Hirofumi diff --git a/bignum.c b/bignum.c index 237ba96e86..027384076d 100644 --- a/bignum.c +++ b/bignum.c @@ -203,8 +203,9 @@ rb_quad_pack(buf, val) long len = RBIGNUM(val)->len; BDIGIT *ds; - if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) - rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'"); + if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) { + len = SIZEOF_LONG/SIZEOF_BDIGITS; + } ds = BDIGITS(val); q = 0; while (len--) { @@ -725,16 +726,20 @@ rb_big_to_s(argc, argv, x) } static unsigned long -big2ulong(x, type) +big2ulong(x, type, check) VALUE x; char *type; + int check; { long len = RBIGNUM(x)->len; BDIGIT_DBL num; BDIGIT *ds; - if (len > SIZEOF_LONG/SIZEOF_BDIGITS) - rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); + if (len > SIZEOF_LONG/SIZEOF_BDIGITS) { + if (check) + rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); + len = SIZEOF_LONG/SIZEOF_BDIGITS; + } ds = BDIGITS(x); num = 0; while (len--) { @@ -744,11 +749,22 @@ big2ulong(x, type) return num; } +unsigned long +rb_big2ulong_pack(x) + VALUE x; +{ + unsigned long num = big2ulong(x, "unsigned long", Qfalse); + if (!RBIGNUM(x)->sign) { + return -num; + } + return num; +} + unsigned long rb_big2ulong(x) VALUE x; { - unsigned long num = big2ulong(x, "unsigned long"); + unsigned long num = big2ulong(x, "unsigned long", Qtrue); if (!RBIGNUM(x)->sign) { if ((long)num < 0) { @@ -763,7 +779,7 @@ long rb_big2long(x) VALUE x; { - unsigned long num = big2ulong(x, "long"); + unsigned long num = big2ulong(x, "long", Qtrue); if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) { rb_raise(rb_eRangeError, "bignum too big to convert into `long'"); diff --git a/object.c b/object.c index cccb56fec1..5e77630820 100644 --- a/object.c +++ b/object.c @@ -2004,8 +2004,9 @@ rb_convert_type(val, type, tname, method) if (TYPE(val) == type) return val; v = convert_type(val, tname, method, Qtrue); if (TYPE(v) != type) { - rb_raise(rb_eTypeError, "%s#%s should return %s", - rb_obj_classname(val), method, tname); + char *cname = rb_obj_classname(val); + rb_raise(rb_eTypeError, "cannot convert %s to %s (%s#%s gives %s)", + cname, tname, cname, method, rb_obj_classname(v)); } return v; } @@ -2023,8 +2024,9 @@ rb_check_convert_type(val, type, tname, method) v = convert_type(val, tname, method, Qfalse); if (NIL_P(v)) return Qnil; if (TYPE(v) != type) { - rb_raise(rb_eTypeError, "%s#%s should return %s", - rb_obj_classname(val), method, tname); + char *cname = rb_obj_classname(val); + rb_raise(rb_eTypeError, "cannot convert %s to %s (%s#%s gives %s)", + cname, tname, cname, method, rb_obj_classname(v)); } return v; } @@ -2037,8 +2039,9 @@ rb_to_integer(val, method) { VALUE v = convert_type(val, "Integer", method, Qtrue); if (!rb_obj_is_kind_of(v, rb_cInteger)) { - rb_raise(rb_eTypeError, "%s#%s should return Integer", - rb_obj_classname(val), method); + char *cname = rb_obj_classname(val); + rb_raise(rb_eTypeError, "cannot convert %s to Integer (%s#%s gives %s)", + cname, cname, method, rb_obj_classname(v)); } return v; } diff --git a/pack.c b/pack.c index 4edffd3801..9680b0fd7f 100644 --- a/pack.c +++ b/pack.c @@ -24,8 +24,6 @@ #ifdef NATINT_PACK # define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16))) # define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32))) -# define NATINT_I32(x) (natint?NUM2LONG(x):(NUM2I32(x))) -# define NATINT_U32(x) (natint?NUM2ULONG(x):(NUM2U32(x))) # define NATINT_LEN(type,len) (natint?sizeof(type):(len)) # ifdef WORDS_BIGENDIAN # define OFF16(p) OFF16B(p) @@ -36,8 +34,6 @@ # define NATINT_HTONS(x) (natint?htons(x):hton16(x)) # define NATINT_HTONL(x) (natint?htonl(x):hton32(x)) #else -# define NATINT_I32(x) NUM2I32(x) -# define NATINT_U32(x) NUM2U32(x) # define NATINT_LEN(type,len) sizeof(type) # define NATINT_HTOVS(x) htovs(x) # define NATINT_HTOVL(x) htovl(x) @@ -335,53 +331,22 @@ endian() #define VTOHD(x,y) vtohd(x) #endif -#if SIZEOF_LONG == SIZE32 -typedef long I32; -typedef unsigned long U32; -#define NUM2I32(x) NUM2LONG(x) -#define NUM2U32(x) NUM2ULONG(x) -#else -typedef int I32; -typedef unsigned int U32; -# if SIZEOF_INT == SIZE32 -# define NUM2I32(x) NUM2INT(x) -# define NUM2U32(x) NUM2UINT(x) -# else - -#define I32_MAX 2147483647 -#define I32_MIN (-I32_MAX-1) +unsigned long rb_big2ulong_pack _((VALUE x)); -static I32 +static unsigned long num2i32(x) VALUE x; { - long num = NUM2LONG(x); - - if (num < I32_MIN || I32_MAX < num) { - rb_raise(rb_eRangeError, "integer %ld too big to convert to `I32'", num); - } - return (I32)num; -} - -#define U32_MAX 4294967295 - -static U32 -num2u32(x) - VALUE x; -{ - unsigned long num = NUM2ULONG(x); + x = rb_to_int(x); /* is nil OK? (should not) */ - if (U32_MAX < num) { - rb_raise(rb_eRangeError, "integer %ld too big to convert to `U32'", num); + if (FIXNUM_P(x)) return FIX2LONG(x); + if (TYPE(x) == T_BIGNUM) { + return rb_big2ulong_pack(x); } - return (U32)num; + rb_raise(rb_eTypeError, "cannot conver %s to `integer'", rb_obj_classname(x)); + return 0; /* not reached */ } -# define NUM2I32(x) num2i32(x) -# define NUM2U32(x) num2u32(x) -# endif -#endif - #if SIZEOF_LONG == SIZE32 || SIZEOF_INT == SIZE32 # define EXTEND32(x) #else @@ -512,7 +477,7 @@ pack_pack(ary, fmt) continue; } if (*p == '_' || *p == '!') { - char *natstr = "sSiIlL"; + const char *natstr = "sSiIlL"; if (strchr(natstr, type)) { #ifdef NATINT_PACK @@ -702,10 +667,7 @@ pack_pack(ary, fmt) char c; from = NEXTFROM; - if (NIL_P(from)) c = 0; - else { - c = NUM2INT(from); - } + c = num2i32(from); rb_str_buf_cat(res, &c, sizeof(char)); } break; @@ -716,10 +678,7 @@ pack_pack(ary, fmt) short s; from = NEXTFROM; - if (NIL_P(from)) s = 0; - else { - s = NUM2INT(from); - } + s = num2i32(from); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } break; @@ -730,13 +689,7 @@ pack_pack(ary, fmt) long i; from = NEXTFROM; - if (NIL_P(from)) i = 0; - else if (type == 'i') { - i = NATINT_I32(from); - } - else { - i = NATINT_U32(from); - } + i = num2i32(from); rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4)); } break; @@ -747,13 +700,7 @@ pack_pack(ary, fmt) long l; from = NEXTFROM; - if (NIL_P(from)) l = 0; - else if (type == 'l') { - l = NATINT_I32(from); - } - else { - l = NATINT_U32(from); - } + l = num2i32(from); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } break; @@ -764,7 +711,6 @@ pack_pack(ary, fmt) char tmp[QUAD_SIZE]; from = NEXTFROM; - if (NIL_P(from)) from = INT2FIX(0); rb_quad_pack(tmp, from); rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE); } @@ -775,10 +721,7 @@ pack_pack(ary, fmt) unsigned short s; from = NEXTFROM; - if (NIL_P(from)) s = 0; - else { - s = NUM2INT(from); - } + s = num2i32(from); s = NATINT_HTONS(s); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } @@ -789,10 +732,7 @@ pack_pack(ary, fmt) unsigned long l; from = NEXTFROM; - if (NIL_P(from)) l = 0; - else { - l = NATINT_U32(from); - } + l = num2i32(from); l = NATINT_HTONL(l); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } @@ -803,10 +743,7 @@ pack_pack(ary, fmt) unsigned short s; from = NEXTFROM; - if (NIL_P(from)) s = 0; - else { - s = NUM2INT(from); - } + s = num2i32(from); s = NATINT_HTOVS(s); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } @@ -817,10 +754,7 @@ pack_pack(ary, fmt) unsigned long l; from = NEXTFROM; - if (NIL_P(from)) l = 0; - else { - l = NATINT_U32(from); - } + l = num2i32(from); l = NATINT_HTOVL(l); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } @@ -932,10 +866,7 @@ pack_pack(ary, fmt) int le; from = NEXTFROM; - if (NIL_P(from)) l = 0; - else { - l = NUM2UINT(from); - } + l = num2i32(from); le = uv_to_utf8(buf, l); rb_str_buf_cat(res, (char*)buf, le); } @@ -1018,8 +949,7 @@ pack_pack(ary, fmt) } } - if (NIL_P(from)) ul = 0; - else { + { long l = NUM2LONG(from); if (l < 0) { rb_raise(rb_eArgError, "cannot compress negative numbers"); diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb index a1ae01839a..9939f9f07b 100644 --- a/test/ruby/test_pack.rb +++ b/test/ruby/test_pack.rb @@ -27,6 +27,10 @@ class TestPack < Test::Unit::TestCase assert_equal "\377\377\377\376", [4294967294].pack('N') assert_equal "\377\377\377\377", [4294967295].pack('N') + assert_equal "\200\000\000\000", [2**31].pack('N') + assert_equal "\177\377\377\377", [-2**31-1].pack('N') + assert_equal "\377\377\377\377", [-1].pack('N') + assert_equal "\000\000\000\001\000\000\000\001", [1,1].pack('N*') assert_equal "\000\000\000\001\000\000\000\001\000\000\000\001", [1,1,1].pack('N*') end -- cgit v1.2.3