Hi,

On Wed, 10 Oct 2018 08:00:14 +0900 (JST)
Masato Asou <[email protected]> wrote:
> When I use /usr/bin/bc command with MALLOC_OPTIONS=UJ, SEGV was
> occurred in libedit.
> 
> $ MALLOC_OPTIONS=UJ /usr/bin/bc
> 100000 + 200000 + 300000 + 400000 + 500000 + 600000 + 700000 + 800000 + 
> 900000 + Segmentation fault (core dumped)

Yes, it repeats.

- appending chars beyond the terminal width
- then hit <Backspace>

sometime causes SIGSEGV.

I think the root problem is that

  - In re_fastputc() case  (simply appendding a char)
  - The line buffers other than first line is not initialized before
    being used.
    
In re_fastputc():

   1068         if (el->el_cursor.h >= el->el_terminal.t_size.h) {

if new line begin,

   1069                 /* if we must overflow */
   1070                 el->el_cursor.h = 0;
   1071 
   1072                 /*
   1073                  * If we would overflow (input is longer than terminal 
size),
   1074                  * emulate scroll by dropping first line and shuffling 
the rest.
   1075                  * We do this via pointer shuffling - it's safe in this 
case
   1076                  * and we avoid memcpy().
   1077                  */
   1078                 if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {

if it was at the last line of the terminal

   1079                         int i, lins = el->el_terminal.t_size.v;
   1080                         lastline = el->el_display[0];
   1081                         for(i = 1; i < lins; i++)
   1082                                 el->el_display[i - 1] = 
el->el_display[i];
   1083                         el->el_display[i - 1] = lastline;
   1084                 } else {
   1085                         el->el_cursor.v++;
   1086                         lastline = 
el->el_display[el->el_refresh.r_oldcv++];
   1087                 }
   1088                 re__copy_and_pad(lastline, L"", 
el->el_terminal.t_size.h);

initialize new line.

See #1086, "lastline" is set to previous lastline.  Then new line is not 
initialized.

I think the following diff is better since it initializes the line in
the same way for first line.

diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
index f2d001d67cb..9bf46faa777 100644
--- a/lib/libedit/refresh.c
+++ b/lib/libedit/refresh.c
@@ -1083,7 +1083,7 @@ re_fastputc(EditLine *el, wint_t c)
                        el->el_display[i - 1] = lastline;
                } else {
                        el->el_cursor.v++;
-                       lastline = el->el_display[el->el_refresh.r_oldcv++];
+                       lastline = el->el_display[++el->el_refresh.r_oldcv];
                }
                re__copy_and_pad(lastline, L"", el->el_terminal.t_size.h);
 

Reply via email to