]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/src/c++98/istream.cc
libstdc++: Fix infinite loop in std::istream::ignore(n, delim) [PR93672]
[thirdparty/gcc.git] / libstdc++-v3 / src / c++98 / istream.cc
CommitLineData
adb31ad6
PC
1// Input streams -*- C++ -*-
2
a945c346 3// Copyright (C) 2004-2024 Free Software Foundation, Inc.
adb31ad6
PC
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
748086b7 8// Free Software Foundation; either version 3, or (at your option)
adb31ad6
PC
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
748086b7
JJ
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
adb31ad6
PC
24
25//
26// ISO C++ 14882: 27.6.1 Input streams
27//
28
29#include <istream>
30
12ffa228
BK
31namespace std _GLIBCXX_VISIBILITY(default)
32{
33_GLIBCXX_BEGIN_NAMESPACE_VERSION
3cbc7af0 34
adb31ad6
PC
35 template<>
36 basic_istream<char>&
37 basic_istream<char>::
38 getline(char_type* __s, streamsize __n, char_type __delim)
39 {
40 _M_gcount = 0;
6f0398bb 41 ios_base::iostate __err = ios_base::goodbit;
adb31ad6 42 sentry __cerb(*this, true);
880b527f 43 if (__cerb)
adb31ad6 44 {
bc2631e0 45 __try
adb31ad6
PC
46 {
47 const int_type __idelim = traits_type::to_int_type(__delim);
48 const int_type __eof = traits_type::eof();
49 __streambuf_type* __sb = this->rdbuf();
50 int_type __c = __sb->sgetc();
f92ab29f 51
adb31ad6
PC
52 while (_M_gcount + 1 < __n
53 && !traits_type::eq_int_type(__c, __eof)
54 && !traits_type::eq_int_type(__c, __idelim))
55 {
56 streamsize __size = std::min(streamsize(__sb->egptr()
57 - __sb->gptr()),
58 streamsize(__n - _M_gcount
59 - 1));
60 if (__size > 1)
61 {
62 const char_type* __p = traits_type::find(__sb->gptr(),
63 __size,
64 __delim);
65 if (__p)
66 __size = __p - __sb->gptr();
67 traits_type::copy(__s, __sb->gptr(), __size);
68 __s += __size;
1139a735 69 __sb->__safe_gbump(__size);
adb31ad6
PC
70 _M_gcount += __size;
71 __c = __sb->sgetc();
72 }
73 else
74 {
75 *__s++ = traits_type::to_char_type(__c);
76 ++_M_gcount;
77 __c = __sb->snextc();
78 }
79 }
80
81 if (traits_type::eq_int_type(__c, __eof))
82 __err |= ios_base::eofbit;
83 else if (traits_type::eq_int_type(__c, __idelim))
84 {
f92ab29f 85 ++_M_gcount;
adb31ad6
PC
86 __sb->sbumpc();
87 }
88 else
89 __err |= ios_base::failbit;
90 }
bc2631e0 91 __catch(__cxxabiv1::__forced_unwind&)
d05f74f1
JM
92 {
93 this->_M_setstate(ios_base::badbit);
94 __throw_exception_again;
95 }
bc2631e0 96 __catch(...)
adb31ad6
PC
97 { this->_M_setstate(ios_base::badbit); }
98 }
75a25e3f
PC
99 // _GLIBCXX_RESOLVE_LIB_DEFECTS
100 // 243. get and getline when sentry reports failure.
101 if (__n > 0)
102 *__s = char_type();
adb31ad6
PC
103 if (!_M_gcount)
104 __err |= ios_base::failbit;
105 if (__err)
106 this->setstate(__err);
107 return *this;
108 }
109
adb31ad6
PC
110 template<>
111 basic_istream<char>&
112 basic_istream<char>::
113 ignore(streamsize __n, int_type __delim)
114 {
2d694414
JW
115 {
116 // If conversion to int_type changes the value then __delim does not
117 // correspond to a value of type char_type, and so will never match
118 // a character extracted from the input sequence. Just use ignore(n).
119 const int_type chk_delim = traits_type::to_int_type(__delim);
120 const bool matchable = traits_type::eq_int_type(chk_delim, __delim);
121 if (__builtin_expect(!matchable, 0))
122 return ignore(__n);
123 // Now we know that __delim is a valid char_type value, so it's safe
124 // for the code below to use traits_type::find to search for it.
125 }
adb31ad6
PC
126
127 _M_gcount = 0;
128 sentry __cerb(*this, true);
880b527f 129 if (__n > 0 && __cerb)
adb31ad6 130 {
6f0398bb 131 ios_base::iostate __err = ios_base::goodbit;
bc2631e0 132 __try
adb31ad6 133 {
21da6d0f 134 const char_type __cdelim = traits_type::to_char_type(__delim);
adb31ad6
PC
135 const int_type __eof = traits_type::eof();
136 __streambuf_type* __sb = this->rdbuf();
137 int_type __c = __sb->sgetc();
138
78593d78 139 bool __large_ignore = false;
bea53dbf 140 while (true)
adb31ad6 141 {
bea53dbf
PC
142 while (_M_gcount < __n
143 && !traits_type::eq_int_type(__c, __eof)
144 && !traits_type::eq_int_type(__c, __delim))
adb31ad6 145 {
bea53dbf
PC
146 streamsize __size = std::min(streamsize(__sb->egptr()
147 - __sb->gptr()),
148 streamsize(__n - _M_gcount));
149 if (__size > 1)
150 {
151 const char_type* __p = traits_type::find(__sb->gptr(),
152 __size,
153 __cdelim);
154 if (__p)
155 __size = __p - __sb->gptr();
1139a735 156 __sb->__safe_gbump(__size);
bea53dbf
PC
157 _M_gcount += __size;
158 __c = __sb->sgetc();
159 }
160 else
161 {
162 ++_M_gcount;
163 __c = __sb->snextc();
164 }
adb31ad6 165 }
6725add5 166 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max
bea53dbf
PC
167 && !traits_type::eq_int_type(__c, __eof)
168 && !traits_type::eq_int_type(__c, __delim))
78593d78 169 {
6725add5
PC
170 _M_gcount =
171 __gnu_cxx::__numeric_traits<streamsize>::__min;
78593d78
PC
172 __large_ignore = true;
173 }
adb31ad6 174 else
bea53dbf 175 break;
adb31ad6 176 }
bea53dbf 177
ba8fe4b4
JW
178 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max)
179 {
180 if (__large_ignore)
181 _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max;
78593d78 182
ba8fe4b4
JW
183 if (traits_type::eq_int_type(__c, __eof))
184 __err |= ios_base::eofbit;
185 else
186 {
187 if (_M_gcount != __n)
188 ++_M_gcount;
189 __sb->sbumpc();
190 }
191 }
192 else if (_M_gcount < __n) // implies __c == __delim or EOF
adb31ad6 193 {
ba8fe4b4
JW
194 if (traits_type::eq_int_type(__c, __eof))
195 __err |= ios_base::eofbit;
196 else
197 {
198 ++_M_gcount;
199 __sb->sbumpc();
200 }
adb31ad6
PC
201 }
202 }
bc2631e0 203 __catch(__cxxabiv1::__forced_unwind&)
d05f74f1
JM
204 {
205 this->_M_setstate(ios_base::badbit);
206 __throw_exception_again;
207 }
bc2631e0 208 __catch(...)
adb31ad6
PC
209 { this->_M_setstate(ios_base::badbit); }
210 if (__err)
211 this->setstate(__err);
212 }
213 return *this;
214 }
215
17abcc77
JW
216 void
217 __istream_extract(istream& __in, char* __s, streamsize __num)
ceed88b1
PC
218 {
219 typedef basic_istream<char> __istream_type;
220 typedef __istream_type::int_type __int_type;
221 typedef __istream_type::char_type __char_type;
222 typedef __istream_type::traits_type __traits_type;
223 typedef __istream_type::__streambuf_type __streambuf_type;
224 typedef __istream_type::__ctype_type __ctype_type;
225
226 streamsize __extracted = 0;
6f0398bb 227 ios_base::iostate __err = ios_base::goodbit;
ceed88b1 228 __istream_type::sentry __cerb(__in, false);
880b527f 229 if (__cerb)
ceed88b1 230 {
bc2631e0 231 __try
ceed88b1
PC
232 {
233 // Figure out how many characters to extract.
17abcc77
JW
234 streamsize __width = __in.width();
235 if (0 < __width && __width < __num)
236 __num = __width;
ceed88b1
PC
237
238 const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
239
240 const __int_type __eof = __traits_type::eof();
241 __streambuf_type* __sb = __in.rdbuf();
242 __int_type __c = __sb->sgetc();
243
244 while (__extracted < __num - 1
245 && !__traits_type::eq_int_type(__c, __eof)
246 && !__ct.is(ctype_base::space,
247 __traits_type::to_char_type(__c)))
248 {
249 streamsize __size = std::min(streamsize(__sb->egptr()
250 - __sb->gptr()),
251 streamsize(__num - __extracted
252 - 1));
253 if (__size > 1)
254 {
255 __size = (__ct.scan_is(ctype_base::space,
256 __sb->gptr() + 1,
257 __sb->gptr() + __size)
258 - __sb->gptr());
259 __traits_type::copy(__s, __sb->gptr(), __size);
260 __s += __size;
1139a735 261 __sb->__safe_gbump(__size);
ceed88b1
PC
262 __extracted += __size;
263 __c = __sb->sgetc();
264 }
265 else
266 {
267 *__s++ = __traits_type::to_char_type(__c);
268 ++__extracted;
269 __c = __sb->snextc();
270 }
271 }
272
4e39f563
JW
273 if (__extracted < __num - 1
274 && __traits_type::eq_int_type(__c, __eof))
ceed88b1
PC
275 __err |= ios_base::eofbit;
276
277 // _GLIBCXX_RESOLVE_LIB_DEFECTS
278 // 68. Extractors for char* should store null at end
279 *__s = __char_type();
280 __in.width(0);
281 }
bc2631e0 282 __catch(__cxxabiv1::__forced_unwind&)
d05f74f1
JM
283 {
284 __in._M_setstate(ios_base::badbit);
285 __throw_exception_again;
286 }
bc2631e0 287 __catch(...)
ceed88b1
PC
288 { __in._M_setstate(ios_base::badbit); }
289 }
290 if (!__extracted)
291 __err |= ios_base::failbit;
292 if (__err)
293 __in.setstate(__err);
ceed88b1
PC
294 }
295
adb31ad6
PC
296#ifdef _GLIBCXX_USE_WCHAR_T
297 template<>
298 basic_istream<wchar_t>&
299 basic_istream<wchar_t>::
300 getline(char_type* __s, streamsize __n, char_type __delim)
301 {
302 _M_gcount = 0;
6f0398bb 303 ios_base::iostate __err = ios_base::goodbit;
adb31ad6 304 sentry __cerb(*this, true);
880b527f 305 if (__cerb)
adb31ad6 306 {
bc2631e0 307 __try
adb31ad6
PC
308 {
309 const int_type __idelim = traits_type::to_int_type(__delim);
310 const int_type __eof = traits_type::eof();
311 __streambuf_type* __sb = this->rdbuf();
312 int_type __c = __sb->sgetc();
f92ab29f 313
adb31ad6
PC
314 while (_M_gcount + 1 < __n
315 && !traits_type::eq_int_type(__c, __eof)
316 && !traits_type::eq_int_type(__c, __idelim))
317 {
318 streamsize __size = std::min(streamsize(__sb->egptr()
319 - __sb->gptr()),
320 streamsize(__n - _M_gcount
321 - 1));
322 if (__size > 1)
323 {
324 const char_type* __p = traits_type::find(__sb->gptr(),
325 __size,
326 __delim);
327 if (__p)
328 __size = __p - __sb->gptr();
329 traits_type::copy(__s, __sb->gptr(), __size);
330 __s += __size;
1139a735 331 __sb->__safe_gbump(__size);
adb31ad6
PC
332 _M_gcount += __size;
333 __c = __sb->sgetc();
334 }
335 else
336 {
337 *__s++ = traits_type::to_char_type(__c);
338 ++_M_gcount;
339 __c = __sb->snextc();
340 }
341 }
342
343 if (traits_type::eq_int_type(__c, __eof))
344 __err |= ios_base::eofbit;
345 else if (traits_type::eq_int_type(__c, __idelim))
346 {
f92ab29f 347 ++_M_gcount;
adb31ad6
PC
348 __sb->sbumpc();
349 }
350 else
351 __err |= ios_base::failbit;
352 }
bc2631e0 353 __catch(__cxxabiv1::__forced_unwind&)
d05f74f1
JM
354 {
355 this->_M_setstate(ios_base::badbit);
356 __throw_exception_again;
357 }
bc2631e0 358 __catch(...)
adb31ad6
PC
359 { this->_M_setstate(ios_base::badbit); }
360 }
75a25e3f
PC
361 // _GLIBCXX_RESOLVE_LIB_DEFECTS
362 // 243. get and getline when sentry reports failure.
363 if (__n > 0)
364 *__s = char_type();
adb31ad6
PC
365 if (!_M_gcount)
366 __err |= ios_base::failbit;
367 if (__err)
368 this->setstate(__err);
369 return *this;
370 }
371
adb31ad6
PC
372 template<>
373 basic_istream<wchar_t>&
374 basic_istream<wchar_t>::
375 ignore(streamsize __n, int_type __delim)
376 {
377 if (traits_type::eq_int_type(__delim, traits_type::eof()))
378 return ignore(__n);
379
380 _M_gcount = 0;
381 sentry __cerb(*this, true);
880b527f 382 if (__n > 0 && __cerb)
adb31ad6 383 {
6f0398bb 384 ios_base::iostate __err = ios_base::goodbit;
bc2631e0 385 __try
adb31ad6 386 {
880b527f 387 const char_type __cdelim = traits_type::to_char_type(__delim);
adb31ad6
PC
388 const int_type __eof = traits_type::eof();
389 __streambuf_type* __sb = this->rdbuf();
390 int_type __c = __sb->sgetc();
391
78593d78 392 bool __large_ignore = false;
bea53dbf 393 while (true)
adb31ad6 394 {
bea53dbf
PC
395 while (_M_gcount < __n
396 && !traits_type::eq_int_type(__c, __eof)
397 && !traits_type::eq_int_type(__c, __delim))
adb31ad6 398 {
bea53dbf
PC
399 streamsize __size = std::min(streamsize(__sb->egptr()
400 - __sb->gptr()),
401 streamsize(__n - _M_gcount));
402 if (__size > 1)
403 {
404 const char_type* __p = traits_type::find(__sb->gptr(),
405 __size,
406 __cdelim);
407 if (__p)
408 __size = __p - __sb->gptr();
1139a735 409 __sb->__safe_gbump(__size);
bea53dbf
PC
410 _M_gcount += __size;
411 __c = __sb->sgetc();
412 }
413 else
414 {
415 ++_M_gcount;
416 __c = __sb->snextc();
417 }
adb31ad6 418 }
6725add5 419 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max
bea53dbf
PC
420 && !traits_type::eq_int_type(__c, __eof)
421 && !traits_type::eq_int_type(__c, __delim))
78593d78 422 {
6725add5
PC
423 _M_gcount =
424 __gnu_cxx::__numeric_traits<streamsize>::__min;
78593d78
PC
425 __large_ignore = true;
426 }
adb31ad6 427 else
bea53dbf 428 break;
adb31ad6 429 }
bea53dbf 430
ba8fe4b4
JW
431 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max)
432 {
433 if (__large_ignore)
434 _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max;
78593d78 435
ba8fe4b4
JW
436 if (traits_type::eq_int_type(__c, __eof))
437 __err |= ios_base::eofbit;
438 else
439 {
440 if (_M_gcount != __n)
441 ++_M_gcount;
442 __sb->sbumpc();
443 }
444 }
445 else if (_M_gcount < __n) // implies __c == __delim or EOF
adb31ad6 446 {
ba8fe4b4
JW
447 if (traits_type::eq_int_type(__c, __eof))
448 __err |= ios_base::eofbit;
449 else
450 {
451 ++_M_gcount;
452 __sb->sbumpc();
453 }
adb31ad6
PC
454 }
455 }
bc2631e0 456 __catch(__cxxabiv1::__forced_unwind&)
d05f74f1
JM
457 {
458 this->_M_setstate(ios_base::badbit);
459 __throw_exception_again;
460 }
bc2631e0 461 __catch(...)
adb31ad6
PC
462 { this->_M_setstate(ios_base::badbit); }
463 if (__err)
464 this->setstate(__err);
465 }
466 return *this;
467 }
468#endif
3cbc7af0 469
34a2b755 470
12ffa228
BK
471_GLIBCXX_END_NAMESPACE_VERSION
472} // namespace