NetBSD-Bugs archive

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

lib/60593: libedit: buffer overruns and arithmetic overflow



>Number:         60593
>Category:       lib
>Synopsis:       libedit: buffer overruns and arithmetic overflow
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Aug 14 22:35:00 +0000 2026
>Originator:     Taylor R Campbell
>Release:        current, 11, 10, 9
>Organization:
The NetBSD Editation, Inc.
>Environment:
>Description:

1.	In libedit/readline.c getfrom, a 2021 fix for an off-by-one
	error in a bounds check (to verify that there is space in the
	buffer for len bytes plus a NUL byte) inadvertently turned it
	into an off-by-two error in a bounds check:

    693 	char *what = el_realloc(*fromp, size * sizeof(*what));
...
    699 	for (; *cmd && *cmd != delim; cmd++) {
    700 		if (*cmd == '\\' && cmd[1] == delim)
    701 			cmd++;
 => 702 		if (len - 1 >= size) {
    703 			char *nwhat;
    704 			nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
    705 			if (nwhat == NULL) {
    706 				el_free(what);
    707 				el_free(*fromp);
    708 				*cmdp = cmd;
    709 				*fromp = NULL;
    710 				return 0;
    711 			}
    712 			what = nwhat;
    713 		}
    714 		what[len++] = *cmd;
    715 	}
    716 	what[len] = '\0';

https://nxr.netbsd.org/xref/src/lib/libedit/readline.c?r=1.184#687

	The attempted fix was in rev. 1.166:

@@ -676,7 +674,7 @@ getfrom(const char **cmdp, char **fromp, const char *search, int delim)
 	for (; *cmd && *cmd != delim; cmd++) {
 		if (*cmd == '\\' && cmd[1] == delim)
 			cmd++;
-		if (len >= size) {
+		if (len - 1 >= size) {
 			char *nwhat;
 			nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
 			if (nwhat == NULL) {

	Additionally, size << 1 (i.e., size * 2) could in principle
	overflow; should verify size < SIZE_MAX/2/sizeof(*nwhat) before
	computing (size << 1) * sizeof(*nwhat).

2. 	Possible three-wchar buffer overrun in vi mode searching:

     73 	el->el_search.patbuf = el_calloc(EL_BUFSIZ,
     74 	    sizeof(*el->el_search.patbuf));
...
    489 		if (el->el_search.patbuf[0] != '.' &&
    490 		    el->el_search.patbuf[0] != '*') {
    491 			(void) wcsncpy(tmpbuf, el->el_search.patbuf,
    492 			    sizeof(tmpbuf) / sizeof(*tmpbuf) - 1);
    493 			el->el_search.patbuf[0] = '.';
    494 			el->el_search.patbuf[1] = '*';
    495 			(void) wcsncpy(&el->el_search.patbuf[2], tmpbuf,
    496 			    EL_BUFSIZ - 3);
    497 			el->el_search.patlen++;
    498 			el->el_search.patbuf[el->el_search.patlen++] = '.';
    499 			el->el_search.patbuf[el->el_search.patlen++] = '*';
    500 			el->el_search.patbuf[el->el_search.patlen] = '\0';
    501 		}

https://nxr.netbsd.org/xref/src/lib/libedit/search.c?r=1.53#488

	If, on input, the search already has a maximum-length patbuf
	(and I see no way to rule this out), el->el_search.patlen++ may
	advance past the end of the buffer.

	Reported by Miroslav Lichvar <mlichvar%redhat.com@localhost>.

>How-To-Repeat:

	code inspection
	abuse^Wheavy use of interactive history editing or search features


>Fix:

1.	Fix the bounds check by saying `+ 1' instead of `- 1', and
	check for arithmetic overflow.

2.	Fail if el->el_search.patlen >= EL_BUFSIZE - 3.




Home | Main Index | Thread Index | Old Index