fix: reject trailing non-number characters in Num.fromString parsing

Previously, `Num.fromString` accepted strings like `"1.2prefix"` and returned the
leading numeric portion (`1.2`). This change makes parsing stricter by requiring
that the entire string be consumed after `strtod`, skipping only trailing
whitespace. If any non-whitespace characters remain after the number, the
function now returns `null` instead of a partial result.

The fix also adds an explicit empty-string check and updates the test suite to
reflect the new behavior, replacing the old `"1.2prefix"` success test with a
`"1.2suffix"` null-return test.
This commit is contained in:
Bob Nystrom
2015-02-25 15:07:54 +00:00
parent f0a73b6ce2
commit 3aa82e7960
2 changed files with 14 additions and 5 deletions
+12 -4
View File
@@ -1,3 +1,4 @@
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -923,14 +924,21 @@ DEF_NATIVE(num_fromString)
{
if (!validateString(vm, args, 1, "Argument")) return PRIM_ERROR;
ObjString* candidate = AS_STRING(args[1]);
ObjString* string = AS_STRING(args[1]);
// Corner case: Can't parse an empty string.
if (string->length == 0) RETURN_NULL;
char* end;
double number = strtod(candidate->value, &end);
double number = strtod(string->value, &end);
// Invalid number literal.
// Skip past any trailing whitespace.
while (*end != '\0' && isspace(*end)) end++;
// We must have consumed the entire string. Otherwise, it contains non-number
// characters and we can't parse it.
// TODO: Check errno == ERANGE here.
if (end == candidate->value) RETURN_NULL;
if (end < string->value + string->length) RETURN_NULL;
RETURN_NUM(number);
}