More robust object -> double conversion.

Certain checks were useless, at the same time certain malformed inputs
were accepted without problems (emtpy strings parsed as zero).
Cases where strtod() returns ERANGE but we still want to parse the input
where ok in getDoubleFromObject() but not in the long variant.

As a side effect of these fixes, this commit fixes #4391.
This commit is contained in:
antirez 2017-10-30 13:20:13 +01:00
parent 37b501ca84
commit a259494736

View File

@ -558,11 +558,11 @@ int getDoubleFromObject(const robj *o, double *target) {
if (sdsEncodedObject(o)) { if (sdsEncodedObject(o)) {
errno = 0; errno = 0;
value = strtod(o->ptr, &eptr); value = strtod(o->ptr, &eptr);
if (isspace(((const char*)o->ptr)[0]) || if (sdslen(o->ptr) == 0 ||
isspace(((const char*)o->ptr)[0]) ||
eptr[0] != '\0' || eptr[0] != '\0' ||
(errno == ERANGE && (errno == ERANGE &&
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) || (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
errno == EINVAL ||
isnan(value)) isnan(value))
return C_ERR; return C_ERR;
} else if (o->encoding == OBJ_ENCODING_INT) { } else if (o->encoding == OBJ_ENCODING_INT) {
@ -600,8 +600,12 @@ int getLongDoubleFromObject(robj *o, long double *target) {
if (sdsEncodedObject(o)) { if (sdsEncodedObject(o)) {
errno = 0; errno = 0;
value = strtold(o->ptr, &eptr); value = strtold(o->ptr, &eptr);
if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || if (sdslen(o->ptr) == 0 ||
errno == ERANGE || isnan(value)) isspace(((const char*)o->ptr)[0]) ||
eptr[0] != '\0' ||
(errno == ERANGE &&
(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
isnan(value))
return C_ERR; return C_ERR;
} else if (o->encoding == OBJ_ENCODING_INT) { } else if (o->encoding == OBJ_ENCODING_INT) {
value = (long)o->ptr; value = (long)o->ptr;