NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/44888: [patch] libedit read.c: fix logic



>Number:         44888
>Category:       lib
>Synopsis:       [patch] libedit read.c: fix logic
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 20 22:45:00 +0000 2011
>Originator:     Lucius Windschuh
>Release:        FreeBSD 9-CURRENT
>Organization:
>Environment:
does not apply, using libedit on FreeBSD
>Description:
wpa_supplicant segfaults on my FreeBSD machine since NetBSD's libedit readline 
support was imported.

Digging deeper, libedit's el_push in read.c looked suspicious (here in 
FreeBSD's version, but with the same logic):



public void

el_push(EditLine *el, const char *str)

{

  c_macro_t *ma = &el->el_chared.c_macro;



  if (str != NULL && ma->level + 1 < EL_MAXMACRO) {

    ma->level++;

    if ((ma->macro[ma->level] = el_strdup(str)) != NULL)

      return;

    ma->level--;

  }

  term_beep(el);

  term__flush();

}



It is strange to me that ma->level is not permanently incremented, only in the 
edge case where strdup returns NULL (which happens in my case).


So, I propose the fix blow, which not only fixes the segfaults for me, but also 
makes the logic consistent to me:
ma->level is incremented iff strdup() succeeds, reflecting the macro level 
change.

The fix to the NetBSD code is similar, the bug exists since read.c version 1.30.
>How-To-Repeat:
How to reproduce (at least on FreeBSD with enabled malloc debugging): 

$ wpa_cli

> disco

> reass

(wait until more output is generated)

(press enter)

-> segfault


Backtrace from gdb:
(gdb)  bt
#0  0x281f05f7 in kill () from /lib/libc.so.7
#1  0x281f0516 in raise () from /lib/libc.so.7
#2  0x281eefca in abort () from /lib/libc.so.7
#3  0x281704f3 in malloc_usable_size () from /lib/libc.so.7
#4  0x28171fda in malloc_usable_size () from /lib/libc.so.7
#5  0x28172f5a in free () from /lib/libc.so.7
#6  0x280aaf02 in read_pop (ma=0xbfbfe22c) at read.c:311
#7  0x280adb41 in el_getc (el=0x2844e300, 
    cp=0xbfbfe49b 
"ZD&#65533;\v(<&#65533;\v(\002\201D(&#65533;&#65533;&#65533;\017\203\n(") at 
read.c:345
#8  0x280b704f in el_gets (el=0x2844e300, nread=0xbfbfe4c8) at read.c:239
#9  0x280a830f in readline (p=0x805002a "> ") at 
/usr/src/lib/libedit/readline.c:404
#10 0x0804c4de in main (argc=Error accessing memory address 0x5: Bad address.
)
    at 
/usr/src/usr.sbin/wpa/wpa_cli/../../../contrib/wpa//wpa_supplicant/wpa_cli.c:2038

>Fix:
Index: read.c

===================================================================

--- read.c      (Revision 220736)

+++ read.c      (Arbeitskopie)

@@ -217,9 +217,10 @@

 

        if (str != NULL && ma->level + 1 < EL_MAXMACRO) {

                ma->level++;

-               if ((ma->macro[ma->level] = el_strdup(str)) != NULL)

+               if ((ma->macro[ma->level] = el_strdup(str)) != NULL) {

+                       ma->level--;

                        return;

-               ma->level--;

+               }

        }

        term_beep(el);

        term__flush();



Home | Main Index | Thread Index | Old Index