From: noreply@... Date: 2006-02-09T05:43:36+09:00 Subject: [ ruby-Patches-3503 ] Correction to string-to-float conversion of string with trailing 'e' Patches item #3503, was opened at 2006-02-08 12:31 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1700&aid=3503&group_id=426 Category: Ruby1.9 Group: None Status: Open Resolution: None Priority: 3 Submitted By: Michael Hartl (mhartl) Assigned to: Nobody (None) Summary: Correction to string-to-float conversion of string with trailing 'e' Initial Comment: The documentation for ruby_strtod in util.c says that in the string "-I.FE-X", either 'E' or the exponent 'X' can be omitted, but not both. The most recent version of Ruby in the CVS repository (1.9.0) does not exhibit this behavior, but rather silently ignores a trailing 'E': irb> Float('5.0E') => 5.0 The following patch to ruby_strtod in util.c checks to make sure that 'e' or 'E' is not the last character in the string (and isn't followed by whitespace). If it is, the character pointer is rewound to the previous value (namely 'e' or 'E') and allowed to fall through to the rest of the function, which catches 'e' as an error just as it would any other letter, raising an ArgumentError exception. (In other words, by rewinding the pointer's value to 'e' we simply reduce the problem to one already solved for the other letters.) This is my first patch to an open-source project, so if I screwed something up, please let me know (and please go easy on me :-). --- ruby-orig/util.c 2006-02-08 12:01:22.000000000 -0800 +++ ruby/util.c 2006-02-08 12:34:58.000000000 -0800 @@ -722,7 +722,7 @@ { int sign, expSign = FALSE; double fraction, dblExp, *d; - register const char *p; + register const char *p, *temp; register int c; int exp = 0; /* Exponent read from "EX" field. */ int fracExp = 0; /* Exponent that derives from the fractional @@ -835,22 +835,31 @@ * Skim off the exponent. */ - p = pExp; + p = temp = pExp; if ((*p == 'E') || (*p == 'e')) { p += 1; - if (*p == '-') { - expSign = TRUE; - p += 1; - } + /* + * If p has a trailing 'e', this is an error, so rewind p to + * previous value to treat 'e' like any other letter. + */ + if (!*p || ISSPACE(*p)) { + p = temp; + } else { - if (*p == '+') { + if (*p == '-') { + expSign = TRUE; p += 1; - } - expSign = FALSE; - } - while (ISDIGIT(*p)) { - exp = exp * 10 + (*p - '0'); - p += 1; + } + else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (ISDIGIT(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } } } if (expSign) { ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1700&aid=3503&group_id=426