f18c02e util: fix uint parsing on 64-bit platforms

Authored and Committed by ericb 9 years ago
    util: fix uint parsing on 64-bit platforms
    
    Commit f22b7899 called to light a long-standing latent bug: the
    behavior of virStrToLong_ui was different on 32-bit platforms
    than on 64-bit platforms.  Curse you, C type promotion and
    narrowing rules, and strtoul specification.  POSIX says that for
    a 32-bit long, strtol handles only 2^32 values [LONG_MIN to
    LONG_MAX] while strtoul handles 2^33 - 1 values [-ULONG_MAX to
    ULONG_MAX] with twos-complement wraparound for negatives.  Thus,
    parsing -1 as unsigned long produces ULONG_MAX, rather than a
    range error.  We WANT[1] this same shortcut for turning -1 into
    UINT_MAX when parsing to int; and get it for free with 32-bit
    long.  But with 64-bit long, ULONG_MAX is outside the range
    of int and we were rejecting it as invalid; meanwhile, we were
    silently treating -18446744073709551615 as 1 even though it
    textually exceeds INT_MIN.  Too bad there's not a strtoui() in
    libc that does guaranteed parsing to int, regardless of the size
    of long.
    
    The bug has been latent since 2007, introduced by Jim Meyering
    in commit 5d25419 in the attempt to eradicate unsafe use of
    strto[u]l when parsing ints and longs.  How embarrassing that we
    are only discovering it now - so I'm adding a testsuite to ensure
    that it covers all the corner cases we care about.
    
    [1] Ideally, we really want the caller to be able to choose whether
    to allow negative numbers to wrap around to their 2s-complement
    counterpart, as in strtoul, or to force a stricter input range
    of [0 to UINT_MAX] by rejecting negative signs; this will be added
    in a later patch for all three int types.
    
    This patch is tested on both 32- and 64-bit; the enhanced
    virstringtest passes on both platforms, while virstoragetest now
    reliably fails on both platforms instead of just 32-bit platforms.
    That test will be fixed later.
    
    * src/util/virstring.c (virStrToLong_ui): Ensure same behavior
    regardless of platform long size.
    * tests/virstringtest.c (testStringToLong): New function.
    (mymain): Comprehensively test string to long parsing.
    
    Signed-off-by: Eric Blake <eblake@redhat.com>
    
        
file modified
+15 -3
file modified
+176 -1