[PATCH] Ensure std::getline always 0-terminates string.

Volodymyr Sapsai via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 8 12:36:00 PST 2017


Thanks for the patch, Reimar. Can you please add tests to ensure this functionality doesn’t regress? As null character is required by the standard (27.7.2.3p21), a good starting point seems to be
test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size.pass.cpp
test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size_chart.pass.cpp

And what about free function std::getline that takes a stream and a string? The standard (21.4.8.9p7) specifies 
> […]After constructing a sentry object, if the sentry converts to true, calls str.erase()[…]
It doesn’t mention explicitly effects to str if the sentry converts to false but it mentions that std::getline behaves as an unformatted input function (27.7.2.3). And 27.7.2.3p1 mentions
> […]If the sentry object returns true, when converted to a value of type bool, the function endeavors to obtain the requested input. Otherwise, if the sentry constructor exits by throwing an exception or if the sentry object returns false, when converted to a value of type bool, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to 0; unformatted input functions taking a character array of non-zero size as an argument shall also store a null character (using charT()) in the first location of the array.[…]


Technically, string is not a character array of non-zero size. But according to the spirit of the standard, I would expect string to be empty after reading into it from a stream that reached EOF. What do you think?

Regards,
Volodymyr

> On Oct 4, 2017, at 12:07, Reimar Döffinger via cfe-commits <cfe-commits at lists.llvm.org> wrote:
> 
> If the sentinel failed (e.g. due to having reached
> EOF before) or an exception was caught it failed to
> do that.
> The C++14 standard says:
> "In any case, if n is greater than zero, it then stores
> a null character (using charT()) into the next
> successive location of the array."
> Other implementations like libstdc++ do 0-terminate and
> not doing so may lead security issues in applications.
> ---
> include/istream | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/include/istream b/include/istream
> index 0b8e05d95..5c73df38f 100644
> --- a/include/istream
> +++ b/include/istream
> @@ -1069,16 +1069,18 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ
>                 this->rdbuf()->sbumpc();
>                 ++__gc_;
>             }
> -            if (__n > 0)
> -                *__s = char_type();
>             if (__gc_ == 0)
>                __err |= ios_base::failbit;
>             this->setstate(__err);
>         }
> +        if (__n > 0)
> +            *__s = char_type();
> #ifndef _LIBCPP_NO_EXCEPTIONS
>     }
>     catch (...)
>     {
> +        if (__n > 0)
> +            *__s = char_type();
>         this->__set_badbit_and_consider_rethrow();
>     }
> #endif  // _LIBCPP_NO_EXCEPTIONS
> -- 
> 2.14.2
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list