Mercurial > octave
changeset 31501:2d38bc5a35db
Fix scanf edge case with '-' character in last position and '%d' conversion (bug #63383)
* oct-stream.cc (octave_scan_1): Use "is >> std::ws" at start of function
to strip whitespace from start of field. Record pointer position in new
variable pos. Remove hand-coded whitespace stripping code from '%i' case
in switch statement. After reading value, if an error is found then
re-position stream pointer with seekg() and pass error on.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 21 Nov 2022 19:56:25 -0800 |
parents | 6bd338605fd3 |
children | b39bf92a2364 |
files | libinterp/corefcn/oct-stream.cc |
diffstat | 1 files changed, 31 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc Mon Nov 21 13:11:26 2022 -0800 +++ b/libinterp/corefcn/oct-stream.cc Mon Nov 21 19:56:25 2022 -0800 @@ -4282,6 +4282,9 @@ { T value = T (); + is >> std::ws; // skip through whitespace and advance stream pointer + std::streampos pos = is.tellg (); + switch (fmt.type) { case 'o': @@ -4295,11 +4298,7 @@ case 'i': { - int c1 = std::istream::traits_type::eof (); - - while (is && (c1 = is.get ()) != std::istream::traits_type::eof () - && isspace (c1)) - ; // skip whitespace + int c1 = is.get (); if (c1 != std::istream::traits_type::eof ()) { @@ -4348,18 +4347,33 @@ break; } - // If conversion produces an integer that overflows, failbit is set but - // value is non-zero. We want to treat this case as success, so clear - // failbit from the stream state to keep going. - // FIXME: Maybe set error state on octave stream as above? Matlab does - // *not* indicate an error message on overflow. - if ((is.rdstate () & std::ios::failbit) && value != T ()) - is.clear (is.rdstate () & ~std::ios::failbit); - - // Only copy the converted value if the stream is in a state where we - // want to continue reading. - if (! (is.rdstate () & std::ios::failbit)) - *valptr = value; + std::ios::iostate status = is.rdstate (); + if (! (status & std::ios::failbit)) + { + // Copy the converted value if the stream is in a good state + *valptr = value; + } + else + { + if (value != T ()) + { + // If conversion produces an integer that overflows, failbit is set + // but value is non-zero. We want to treat this case as success, + // so clear failbit from the stream state to keep going. + // FIXME: Maybe set error state on octave stream? Matlab does + // *not* indicate an error message on overflow. + is.clear (status & ~std::ios::failbit); + *valptr = value; + } + else + { + // True error. + // Reset stream to original position, clear eof bit, pass status on. + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } + } return is; }