Mercurial > octave
changeset 27132:8ea53aa9ac39
Fix stream positioning when using scanf with widths (bug #56200).
* oct-stream.cc (octave_scan (std::istream&, const scanf_format_elt&, T*)):
Rename variable "tmp" to "strbuf" for clarity. Record position of input stream
"is" in variable "orig_pos" before any operations. After scanning operation on
stringstream object "ss" check whether eof() is set (full width of characters
were used). If not, restore "is" position back to value at start of function.
Find the number of characters read on stringstream object with tellg() and
then re-perform the extraction operation on input stream with the "correct"
width (number of characters). Copy the failbit from the "ss" object to the
"is" object to propagate any pattern matching errors.
author | Rik <rik@octave.org> |
---|---|
date | Sat, 01 Jun 2019 08:56:51 -0700 |
parents | acedcba362be |
children | fbe46901ae62 |
files | libinterp/corefcn/oct-stream.cc |
diffstat | 1 files changed, 30 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc Thu May 30 11:23:16 2019 +0000 +++ b/libinterp/corefcn/oct-stream.cc Sat Jun 01 08:56:51 2019 -0700 @@ -4269,14 +4269,40 @@ { // Limit input to fmt.width characters by reading into a // temporary stringstream buffer. - std::string tmp; + std::string strbuf; + + auto orig_pos = is.tellg (); is.width (fmt.width); - is >> tmp; - - std::istringstream ss (tmp); + is >> strbuf; + + std::istringstream ss (strbuf); octave_scan_1 (ss, fmt, valptr); + + if (! ss.eof ()) + { + // If fewer characters than width were used to read a number then + // the original istream object positioning is incorrect. + // Rather than attempt to update istream state and positioning, + // just redo the '>>' operation with the correct width so that + // all flags get set correctly. + + is.clear (); // Clear EOF, FAILBIT, BADBIT + is.seekg (orig_pos, is.beg); + + int chars_read = ss.tellg (); + if (chars_read > 0) + { + is.width (chars_read); + is >> strbuf; + } + } + + // If pattern failed to match then propagate fail bit to 'is' stream. + if (ss.fail ()) + is.setstate (std::ios::failbit); + } else octave_scan_1 (is, fmt, valptr);