[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ruby-core
Subject:    [ruby-core:51205] [ruby-trunk - Bug #7371] Fix undefined overflow checking in bigdecimal
From:       "xi (Xi Wang)" <redmine () ruby-lang ! org>
Date:       2012-12-31 5:01:43
Message-ID: redmine.journal-35165.20121231140142 () ruby-lang ! org
[Download RAW message or body]


Issue #7371 has been updated by xi (Xi Wang).


To see how it works, try to compile the following (simplified) code with gcc 4.8.  \
The entire function will be optimized away with "gcc -O2" (just grep "bar" in the \
resulting assembly code); gcc 4.7 or earlier doesn't do that.

#define SIGNED_VALUE    long
#define BASE_FIG        9

void bar(void);

static void AddExponent(SIGNED_VALUE e, SIGNED_VALUE n)
{
    SIGNED_VALUE m = e+n;
    SIGNED_VALUE eb, mb;
    if(e>0) {
        if(n>0) {
            mb = m*(SIGNED_VALUE)BASE_FIG;
            eb = e*(SIGNED_VALUE)BASE_FIG;
            if(mb<eb) goto overflow;
        }
    }
    return;
overflow:
    bar();
}

void foo(SIGNED_VALUE e)
{
    AddExponent(e, 1);
}
----------------------------------------
Bug #7371: Fix undefined overflow checking in bigdecimal
https://bugs.ruby-lang.org/issues/7371#change-35165

Author: xi (Xi Wang)
Status: Assigned
Priority: Normal
Assignee: mrkn (Kenta Murata)
Category: ext
Target version: 
ruby -v: 1.9.x


In AddExponent() at ext/bigdecimal/bigdecimal.c:3677, the overflow checks rely on \
signed integer overflow, which is undefined behavior in C.

    SIGNED_VALUE m = e+n;
    SIGNED_VALUE eb, mb;
    if(e>0) {
        if(n>0) {
            mb = m*(SIGNED_VALUE)BASE_FIG;
            eb = e*(SIGNED_VALUE)BASE_FIG;
            if(mb<eb) goto overflow;
        }

Some compilers (e.g., gcc 4.8) will optimize away such overflow checks due to \
undefined behavior.  Ruby currently uses "-fno-strict-overflow" to disable such \
offending optimizations in gcc, but this workaround option is not supported by other \
compilers, thus not portable.

The attached patch uses unsigned multiplication for overflow checking, which is well \
defined in C.


-- 
http://bugs.ruby-lang.org/


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic