ios_base::register_callback(event_callback __fn, int __index)
{ _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
- // 27.4.2.5 iword/pword storage
+ // 27.4.2.5 [ios.base.storage] iword/pword storage
ios_base::_Words&
ios_base::_M_grow_words(int __ix, bool __iword)
{
// Precondition: _M_word_size <= __ix
int __newsize = _S_local_word_size;
_Words* __words = _M_local_word;
- if (__ix > _S_local_word_size - 1)
+ const char* __error = nullptr;
+ if ((unsigned)__ix >= (unsigned)numeric_limits<int>::max())
+ __error = __N("ios_base::_M_grow_words is not valid");
+ else if (__ix > _S_local_word_size - 1)
{
- if (__ix < numeric_limits<int>::max())
+ __newsize = __ix + 1;
+ /* We still need to catch bad_alloc even though we use
+ a nothrow new, because the new-expression can throw
+ a bad_array_new_length. */
+ __try
+ { __words = new (std::nothrow) _Words[__newsize]; }
+ __catch(const std::bad_alloc&)
+ { __words = nullptr; }
+ if (!__words)
+ __error = __N("ios_base::_M_grow_words allocation failed");
+ else
{
- __newsize = __ix + 1;
- /* We still need to catch bad_alloc even though we use
- a nothrow new, because the new-expression can throw
- a bad_array_new_length. */
- __try
- { __words = new (std::nothrow) _Words[__newsize]; }
- __catch(const std::bad_alloc&)
- { __words = nullptr; }
- if (!__words)
- {
- _M_streambuf_state |= badbit;
- if (_M_streambuf_state & _M_exception)
- __throw_ios_failure(__N("ios_base::_M_grow_words "
- "allocation failed"));
- if (__iword)
- _M_word_zero._M_iword = 0;
- else
- _M_word_zero._M_pword = 0;
- return _M_word_zero;
- }
for (int __i = 0; __i < _M_word_size; __i++)
__words[__i] = _M_word[__i];
if (_M_word && _M_word != _M_local_word)
_M_word = 0;
}
}
+ }
+ if (__error)
+ {
+ _M_streambuf_state |= badbit;
+ if (_M_streambuf_state & _M_exception)
+ __throw_ios_failure(__error);
+ if (__iword)
+ _M_word_zero._M_iword = 0;
else
- {
- _M_streambuf_state |= badbit;
- if (_M_streambuf_state & _M_exception)
- __throw_ios_failure(__N("ios_base::_M_grow_words is not valid"));
- if (__iword)
- _M_word_zero._M_iword = 0;
- else
- _M_word_zero._M_pword = 0;
- return _M_word_zero;
- }
+ _M_word_zero._M_pword = 0;
+ return _M_word_zero;
}
_M_word = __words;
_M_word_size = __newsize;
--- /dev/null
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <ios>
+#include <climits>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/68197
+
+struct sbuf : std::streambuf { } sb;
+
+void
+test01()
+{
+ std::ios ios(&sb);
+ long& i1 = ios.iword(-1);
+ VERIFY( i1 == 0 );
+ VERIFY( ios.bad() );
+ ios.clear();
+ i1 = 1;
+ VERIFY( ios.iword(-1) == 0 );
+ VERIFY( ios.bad() );
+ ios.clear();
+ long& i2 = ios.iword(INT_MIN);
+ VERIFY( i2 == 0 );
+ VERIFY( ios.bad() );
+ ios.clear();
+ i2 = 2;
+ VERIFY( ios.iword(INT_MIN) == 0 );
+ VERIFY( ios.bad() );
+ ios.clear();
+
+ bool caught = false;
+ ios.exceptions(std::ios::badbit);
+ try {
+ ios.iword(-1);
+ } catch (const std::exception&) {
+ caught = true;
+ }
+ VERIFY( caught );
+}
+
+void
+test02()
+{
+ std::ios ios(&sb);
+ void*& p1 = ios.pword(-1);
+ VERIFY( p1 == nullptr );
+ VERIFY( ios.bad() );
+ ios.clear();
+ p1 = &p1;
+ VERIFY( ios.pword(-1) == nullptr );
+ VERIFY( ios.bad() );
+ ios.clear();
+ void*& p2 = ios.pword(INT_MIN);
+ VERIFY( p2 == nullptr );
+ VERIFY( ios.bad() );
+ ios.clear();
+ p2 = &p2;
+ VERIFY( ios.pword(INT_MIN) == nullptr );
+ VERIFY( ios.bad() );
+ ios.clear();
+
+ bool caught = false;
+ ios.exceptions(std::ios::badbit);
+ try {
+ ios.pword(-1);
+ } catch (const std::exception&) {
+ caught = true;
+ }
+ VERIFY( caught );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}