replxx
replxx copied to clipboard
segmentation fault on down arrow keypress
The following REPL session break replxx for me:
--> (+ 0.18 0.2)
0.38
-->
On the third line, after pressing arrow down (history next, while there is no next element) segfaults my program. I presume there's a guard against a common case like this missing.
GDB backtrace:
#0 __memmove_avx_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:443
#1 0x000000000042f42a in std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<char32_t> (__first=0x0, __result=0x4ba340 U"\xf7886c00翿\xf7886c00翿",
__last=<optimized out>)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algobase.h:431
#2 std::__copy_move_a2<false, char32_t const*, char32_t*> (__first=0x0,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=<optimized out>)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algobase.h:494
#3 std::__copy_move_a1<false, char32_t const*, char32_t*> (__first=0x0,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=<optimized out>)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algobase.h:522
#4 std::__copy_move_a<false, __gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > >, char32_t*> (
__first=non-dereferenceable iterator for std::vector,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algobase.h:530
#5 std::copy<__gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > >, char32_t*> (
__first=non-dereferenceable iterator for std::vector,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_algobase.h:619
#6 std::__uninitialized_copy<true>::__uninit_copy<__gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > >, char32_t*> (
__first=non-dereferenceable iterator for std::vector,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:110
#7 std::uninitialized_copy<__gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > >, char32_t*> (
__first=non-dereferenceable iterator for std::vector,
--Type <RET> for more, q to quit, c to continue without paging--
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:148
#8 std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > >, char32_t*, char32_t> (
__first=non-dereferenceable iterator for std::vector,
__result=0x4ba340 U"\xf7886c00翿\xf7886c00翿", __last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_uninitialized.h:333
#9 std::vector<char32_t, std::allocator<char32_t> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<char32_t const*, std::vector<char32_t, std::allocator<char32_t> > > > (
this=0x4b2f78, __n=250, __first=non-dereferenceable iterator for std::vector,
__last=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_vector.h:1514
#10 std::vector<char32_t, std::allocator<char32_t> >::operator= (this=0x4b2f78,
__x=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/vector.tcc:226
#11 0x000000000044533f in replxx::UnicodeString::assign (this=0x4b2f78, other_=...)
at replxx/unicodestring.hxx:93
#12 replxx::Replxx::ReplxxImpl::history_move (this=0x4b2f60, previous_=<optimized out>)
at replxx/replxx_impl.cxx:1956
#13 0x000000000043d419 in replxx::Replxx::ReplxxImpl::line_next (this=0x4ba340)
at replxx/replxx_impl.cxx:1932
#14 0x000000000043ce77 in replxx::Replxx::ReplxxImpl::action (this=0x4b2f60,
actionTrait_=6, handler_=<optimized out>, code_=63712 U'')
at replxx/replxx_impl.cxx:1408
#15 0x0000000000446b4f in replxx::Replxx::ReplxxImpl::input (this=0x4b2f60, prompt=...)
at /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590
#16 0x0000000000417444 in main (argc=<optimized out>, argv=<optimized out>)
at replxx/replxx.cxx:150
My code is located in the kspalaiologos/kamilalisp repository. NB: I keep my own copy of replxx, since I dislike the bloaty buildsystem bundled with the official distribution.
i have reproduced this in my own app.
valgrind gives a better stack trace
==182348== Conditional jump or move depends on uninitialised value(s)
==182348== at 0x6EC301: std::vector<char32_t, std::allocator<char32_t> >::operator=(std::vector<char32_t, std::allocator<char32_t> > const&) [clone .isra.0] (vector.tcc:224)
==182348== by 0x6F2BAB: assign (unicodestring.hxx:74)
==182348== by 0x6F2BAB: history_move (replxx_impl.cxx:1657)
==182348== by 0x6F2BAB: history_move (replxx_impl.cxx:1644)
==182348== by 0x6F2BAB: replxx::Replxx::ReplxxImpl::history_next(char32_t) (replxx_impl.cxx:1636)
the code is
UnicodeString& assign( UnicodeString const& other_ ) {
> _data = other_._data;
return *this;
}
---
history_move
> _data.assign( _history.current() );
---
Replxx::ACTION_RESULT Replxx::ReplxxImpl::history_next( char32_t ) {
> return ( history_move( false ) );
}
_history._current._data is an uninitialized std::vector object.
std::vector of length 266338303, capacity 2 = {<error reading variable>}
_history.current() is implemented like this:
UnicodeString const& current( void ) const {
return ( _current->text() );
}
So _current is an iterator (a pointer) that initially does not point at a valid object (because there is no history yet).
Here we are calling _history.current() at a time when _current doesn't point to a valid object, so current() returns garbage and then we crash.
Workaround: add repl.history_add(""); before any invocation to input. Might break when you log repl history somewhere, but it's not the case for me.
Thanks for the workaround Kamila. Merry Christmas and/or Newtonmas and/or Winter Solstice!