libCom: Fix unsigned overflow limits in epicsParse*

The strtoul() routine accepts negative numbers.  This fix
ensures we handle them properly, and adds suitable tests.

Also fix the test for 1e300, in case the compiler gives a
slightly different literal constant than strtod() returns.
This commit is contained in:
Andrew Johnson
2012-06-30 15:34:29 -05:00
parent fb61234431
commit da9982f875
2 changed files with 24 additions and 6 deletions

View File

@@ -142,7 +142,7 @@ epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units)
if (status)
return status;
if (value > 0xff)
if (value > 0xff && value <= ~0xffUL)
return S_stdlib_overflow;
*to = value;
@@ -174,7 +174,7 @@ epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units)
if (status)
return status;
if (value > 0xffff)
if (value > 0xffff && value <= ~0xffffUL)
return S_stdlib_overflow;
*to = value;
@@ -209,7 +209,7 @@ epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
return status;
#if (ULONG_MAX > 0xffffffff)
if (value > 0xffffffffUL)
if (value > 0xffffffffUL && value <= ~0xffffffffUL)
return S_stdlib_overflow;
#endif

View File

@@ -14,6 +14,7 @@
#include <errno.h>
#include <limits.h>
#include "epicsTypes.h"
#include "epicsStdlib.h"
#include "epicsMath.h"
#include "epicsUnitTest.h"
@@ -67,7 +68,7 @@ MAIN(epicsStdlibTest)
epicsInt32 i32;
epicsUInt32 u32;
testPlan(143);
testPlan(153);
testOk(epicsParseLong("", &l, 0, NULL) == S_stdlib_noConversion,
"Long '' => noConversion");
@@ -106,6 +107,11 @@ MAIN(epicsStdlibTest)
testOk(epicsScanFloat("\t 1\n", &f) && f == 1, "Float '\\t 1\\n'");
testOk(epicsScanDouble("\t 1\n", &d) && d == 1, "Double '\\t 1\\n'");
testOk(epicsScanLong("-1", &l, 0) && l == -1, "Long '-1'");
testOk(epicsScanULong("-1", &u, 0) && u + 1 == 0, "ULong '-1'");
testOk(epicsScanFloat("-1", &f) && f == -1, "Float '-1'");
testOk(epicsScanDouble("-1", &d) && d == -1, "Double '-1'");
testOk(epicsParseLong("2!", &l, 0, NULL) == S_stdlib_extraneous,
"Long '2!' => extraneous");
testOk(epicsParseULong("2!", &u, 0, NULL) == S_stdlib_extraneous,
@@ -209,16 +215,20 @@ MAIN(epicsStdlibTest)
testOk(!epicsParseInt8("0x7f", &i8, 0, NULL) && i8 == 0x7f,
"Int8 '0x7f'");
testOk(!epicsParseInt8("-0x80", &i8, 0, NULL) && i8 == -0x80,
testOk(!epicsParseInt8("-0x80", &i8, 0, NULL) && ((i8 + 0x80) & 0xff) == 0,
"Int8 '-0x80'");
testOk(!epicsParseUInt8("0xff", &u8, 0, NULL) && u8 == 0xff,
"UInt8 '0xff'");
testOk(!epicsParseUInt8("-1", &u8, 0, NULL) && u8 == 0xff,
"UInt8 '-1'");
testOk(epicsParseInt8("0x80", &i8, 0, NULL) == S_stdlib_overflow,
"Int8 '0x80' => overflow");
testOk(epicsParseInt8("-0x81", &i8, 0, NULL) == S_stdlib_overflow,
"Int8 '-0x81' => overflow");
testOk(epicsParseUInt8("0x100", &u8, 0, NULL) == S_stdlib_overflow,
"UInt8 '0x100' => overflow");
testOk(epicsParseUInt8("-0x100", &u8, 0, NULL) == S_stdlib_overflow,
"UInt8 '-0x100' => overflow");
testOk(!epicsParseInt16("0x7fff", &i16, 0, NULL) && i16 == 0x7fff,
"Int16 '0x7fff'");
@@ -226,12 +236,16 @@ MAIN(epicsStdlibTest)
"Int16 '-0x8000'");
testOk(!epicsParseUInt16("0xffff", &u16, 0, NULL) && u16 == 0xffff,
"UInt16 '0xffff'");
testOk(!epicsParseUInt16("-1", &u16, 0, NULL) && u16 == 0xffff,
"UInt16 '-1'");
testOk(epicsParseInt16("0x8000", &i16, 0, NULL) == S_stdlib_overflow,
"Int16 '0x8000' => overflow");
testOk(epicsParseInt16("-0x8001", &i16, 0, NULL) == S_stdlib_overflow,
"Int16 '-0x8001' => overflow");
testOk(epicsParseUInt16("0x10000", &u16, 0, NULL) == S_stdlib_overflow,
"UInt16 '0x10000' => overflow");
testOk(epicsParseUInt16("-0x10000", &u16, 0, NULL) == S_stdlib_overflow,
"UInt16 '-0x10000' => overflow");
testOk(!epicsParseInt32("0x7fffffff", &i32, 0, NULL) && i32 == 0x7fffffff,
"Int32 '0x7fffffff'");
@@ -239,12 +253,16 @@ MAIN(epicsStdlibTest)
"Int32 '-0x80000000'");
testOk(!epicsParseUInt32("0xffffffff", &u32, 0, NULL) && u32 == 0xffffffff,
"UInt32 '0xffffffff'");
testOk(!epicsParseUInt32("-1", &u32, 0, NULL) && u32 == 0xffffffffU,
"UInt32 '-1'");
testOk(epicsParseInt32("0x80000000", &i32, 0, NULL) == S_stdlib_overflow,
"Int32 '0x80000000' => overflow");
testOk(epicsParseInt32("-0x80000001", &i32, 0, NULL) == S_stdlib_overflow,
"Int32 '-0x80000001' => overflow");
testOk(epicsParseUInt32("0x100000000", &u32, 0, NULL) == S_stdlib_overflow,
"UInt32 '0x100000000' => overflow");
testOk(epicsParseUInt32("-0x100000000", &u32, 0, NULL) == S_stdlib_overflow,
"UInt32 '-0x100000000' => overflow");
testOk(epicsScanFloat(".1", &f) && fabs(f - 0.1) < 1e-7,
"Float '.1'");
@@ -288,7 +306,7 @@ MAIN(epicsStdlibTest)
testOk(epicsScanFloat("1e30", &f) && fabs(f - 1e30) < 1e24,
"Float '1e30'");
testOk(epicsScanDouble("1e300", &d) && d == 1e300,
testOk(epicsScanDouble("1e300", &d) && fabs(d - 1e300) < 1e285,
"Double '1e300'");
testOk(epicsParseFloat("1e40", &f, NULL) == S_stdlib_overflow,