lichray/nvi2

Segfault in filename expansion

bentley opened this issue · 6 comments

I’ve encountered an occasional crash on OpenBSD. To cause it, open nvi in a directory with lots of files in it, type “:r *”, and press enter. Whether it crashes at this point or not seems to depend on the specific filenames in the current directory and unfortunately I haven’t come up with a sensible test case yet.

(gdb) bt
#0  argv_sexp (sp=0x31e4239e630, bpp=0x7f7ffffcd418, blenp=0x7f7ffffcd428, 
    lenp=0x7f7ffffcd420)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/ex/ex_argv.c:763
#1  0x0000031c059287ac in argv_exp2 (sp=0x31e4239e630, excp=0x31eca36c0e0, 
    cmd=0x31eab2e8900, cmdlen=Variable "cmdlen" is not available.
)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/ex/ex_argv.c:194
#2  0x0000031c0592ff19 in ex_read (sp=0x31e4239e630, cmdp=0x31eca36c0e0)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/ex/ex_read.c:193
#3  0x0000031c059231ed in ex_cmd (sp=0x31e4239e630)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/ex/ex.c:1383
#4  0x0000031c0593b928 in v_ex (sp=0x31e4239e630, vp=0x7f7ffffcd800)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/vi/v_ex.c:405
#5  0x0000031c05949cf5 in vi (spp=0x7f7ffffcda28)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/vi/vi.c:230
#6  0x0000031c05917af3 in editor (gp=0x31eca36c000, argc=1, 
    argv=0x7f7ffffcdc30)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/common/main.c:421
#7  0x0000031c0590d4af in main (argc=1, argv=0x7f7ffffcdc28)
    at /usr/ports/pobj/nvi-2.1.3-iconv/nvi2-2.1.3/cl/cl_main.c:119

I hate 1.8x code! The sizeof(CHAR_T) on https://github.com/lichray/nvi2/blob/master/ex/ex_argv.c#L763 is wrong; please try change that part back to (as in https://svnweb.freebsd.org/base/stable/8/contrib/nvi/ex/ex_argv.c?view=markup#l710) --blen and see whether the issue is solved.

No, even making that change it still segfaults in the same place.

Hmm, can you copy the filenames under that directory to me?

Okay, an otherwise empty directory containing these files seems to sporadically trigger this crash. (If it doesn’t crash, it prints *: expanded into too many file names.)

ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

If I remove one of these filenames I can’t seem to reproduce the crash; it just prints *: expanded into too many file names. all the time.

Errr, the change I suggested is only making it worse. Can you try the one below, on your "real" directory?

diff --git a/ex/ex_argv.c b/ex/ex_argv.c
index 09c6361..a22abe8 100644
--- a/ex/ex_argv.c
+++ b/ex/ex_argv.c
@@ -760,11 +760,11 @@ err:      if (ifp != NULL)
     * shell that does that is broken.
     */
    for (p = bp, len = 0, ch = EOF;
-       (ch = GETC(ifp)) != EOF; *p++ = ch, blen-=sizeof(CHAR_T), ++len)
+       (ch = GETC(ifp)) != EOF; *p++ = ch, blen -= sizeof(CHAR_T), ++len)
        if (blen < 5) {
-           ADD_SPACE_GOTOW(sp, bp, *blenp, *blenp * 2);
+           ADD_SPACE_GOTOW(sp, bp, *blenp, len * 2);
            p = bp + len;
-           blen = *blenp - len;
+           blen = *blenp - len * sizeof(CHAR_T);
        }

    /* Delete the final newline, nul terminate the string. */

@bentley ping. Can you give it a test?