# HG changeset patch # User Mike Miller # Date 1458347918 25200 # Node ID db67dc54fa2ca7049260bc98d63c1561e0285659 # Parent ab0a19882615f52d9e8cc123e8c0c0525a02fc88 textscan: Avoid buffer out-of-bounds errors in delimited_stream * textscan.cc (delimited_stream::get, delimited_stream::peek, delimited_stream::putback): Check for eof before advancing, rewinding, or dereferencing the pointer into the stream buffer. diff -r ab0a19882615 -r db67dc54fa2c libinterp/corefcn/textscan.cc --- a/libinterp/corefcn/textscan.cc Fri Mar 18 16:53:40 2016 -0700 +++ b/libinterp/corefcn/textscan.cc Fri Mar 18 17:38:38 2016 -0700 @@ -74,13 +74,19 @@ // Get a character, relying on caller to call field_done if // a delimiter has been reached. - int get (void) { return delimited ? *idx++ : get_undelim (); } + int get (void) + { + if (delimited) + return eof () ? std::istream::traits_type::eof () : *idx++; + else + return get_undelim (); + } // Get a character, checking for underrun of the buffer. int get_undelim (void); // Read character that will be got by the next get. - int peek (void) { return *idx; } + int peek (void) { return eof () ? std::istream::traits_type::eof () : *idx; } // Read character that will be got by the next get. int peek_undelim (void); @@ -89,7 +95,7 @@ // to avoid overflow by calling putbacks only for a character got by // get() or get_undelim(), with no intervening // get, get_delim, field_done, refresh_buf, getline, read or seekg. - void putback (char /*ch*/ = 0) { --idx; } + void putback (char /*ch*/ = 0) { if (! eof ()) --idx; } int getline (std::string& dest, char delim);