diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-10-13 03:56:31 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-10-13 03:56:31 +0000 |
commit | a01e62831818ed1c8c00e79991b8f34c02327127 (patch) | |
tree | 2ad7fb3cbeec9fa7cfc592bba2c3d0830a50aaeb /numeric.c | |
parent | acd98555b59522b8f81b8feff70964e92adb902f (diff) |
* numeric.c (rb_num_to_uint): added to check the range of arguments.
Mainly for negative value with NUM2UINT on 32bit environment.
* string.c (rb_str_concat): use rb_num_to_uint.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29480 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r-- | numeric.c | 30 |
1 files changed, 30 insertions, 0 deletions
@@ -113,6 +113,36 @@ rb_num_zerodiv(void) rb_raise(rb_eZeroDivError, "divided by 0"); } +/* experimental API */ +int +rb_num_to_uint(VALUE val, unsigned int *ret) +{ +#define NUMERR_TYPE 1 +#define NUMERR_NEGATIVE 2 +#define NUMERR_TOOLARGE 3 + if (FIXNUM_P(val)) { + long v = FIX2LONG(val); + if (v > UINT_MAX) return NUMERR_TOOLARGE; + if (v < 0) return NUMERR_NEGATIVE; + *ret = (unsigned int)v; + return 0; + } + + switch (TYPE(val)) { + case T_BIGNUM: + if (RBIGNUM_NEGATIVE_P(val)) return NUMERR_NEGATIVE; +#if SIZEOF_INT < SIZEOF_LONG + /* long is 64bit */ + return NUMERR_TOOLARGE; +#else + /* long is 32bit */ + if (RBIGNUM_LEN(x) > DIGSPERLONG) return NUMERR_TOOLARGE; + *ret = (unsigned int)rb_big2ulong((VALUE)val); + return 0; +#endif + } + return NUMERR_TYPE; +} /* * call-seq: |