From a01e62831818ed1c8c00e79991b8f34c02327127 Mon Sep 17 00:00:00 2001 From: naruse Date: Wed, 13 Oct 2010 03:56:31 +0000 Subject: * 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 --- numeric.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'numeric.c') diff --git a/numeric.c b/numeric.c index 5125507f04..4b3cf595cb 100644 --- a/numeric.c +++ b/numeric.c @@ -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: -- cgit v1.2.3