PR# 14681 Call to {PLAIN_TEXT_FILE}.read_double returns garbage if next value not real
Problem Report Summary
Submitter: prestoat2000
Category: Runtime
Priority: Medium
Date: 2008/07/30
Class: Bug
Severity: Serious
Number: 14681
Release: 6.3.74123
Confidential: No
Status: Analyzed
Responsible:
Environment: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.8.1.13) Gecko/20080328 Firefox/2.0.0.13
Solaris 10 on SPARC
Synopsis: Call to {PLAIN_TEXT_FILE}.read_double returns garbage if next value not real
Description
A call to {PLAIN_TEXT_FILE}.read_double (or read_real) should fail if the next characters in the file do not represent a real number. Instead, it returns a garbage value (8.9959041872935432e-309 for read_double and 3.93962e-38 for read_real). Test program attached. The problem appears to be that routines `file_gi', `file_gr' and `file_gd' (in file.c) all check that the returned value of fscanf < 0. But if the conversion fails but there is no EOF, fscanf will return 0 (number of items successfully converted). So instead of failing, the routine returns the value of the uninitialized local. Problem discovered when lint reported possible use of locals before they were set.
To Reproduce
Compile attached program. Create input file "abc" with a single line whose contents are "weasel". Run program. Prints garbage values instead of raising an exception.
Problem Report Interactions
In PLAIN_TEXT_FILE, we have `is_sequence_an_expected_numeric' which is currently not exported. If we were to export it, we could use it for letting the user know about the failure to read. However for the real/double variant, it is harder and requires that we put a rescue clause in `read_double' and `read_real' to catch failures, so I'll need to modify those externals so that we get a better idea of what the failure is.
You should either raise an exception or add a way for the caller to check that the read_double, read_real or read_integer operation failed to successfully read a real or integer. Otherwise, a file with unexpected contents can cause an infinite loop. This applies also to read_integer, which should not return 0 if it can't read a valid integer from the file (unless there is another boolean to indicate whether the read was successful). Note also that the obsolete routines (and their callers in EiffelBase) should probably be removed, or at least marked obsolete. The Eiffel routines are: {CONSOLE}.console_readint {CONSOLE}.console_pi {PLAIN_TEXT_FILE}.file_pi {PLAIN_TEXT_FILE}.file_gi The C routines are: file_gi (in file.c) console_readint (in console.c)
For `file_gi' which is not used anymore, the Eiffel equivalent returns 0. Should we return 0.0 for DOUBLE/REAL, or raise an exception?