Hopefully fix Coverity CID 1008328 (Out-of-bounds write) in /bin/sh.
Replace the magic constant 127 in the loop interation count with "PROMPTLEN - 1". gethostname() is not guaranteed to NUL terminate the destination string if it is too short. Decrease the length passed to gethostname() by one, and add a NUL at the end of the buffer to make sure the following loop to find the end of the name properly terminates. The default: case is the likely cause of Coverity CID 1008328. If i is 126 at the top of the loop interation where the default case is triggered, i will be incremented to 127 by the default case, then incremented to 128 at the top of the loop before being compared to 127 (PROMPTLENT - 1) and terminating the loop. Then the NUL termination code after the loop will write to ps[128]. Fix by checking for overflow before incrementing the index and storing the second character in the buffer. These fixes are not guaranteed to satisfy Coverity. The code that increments i in the 'h'/'H' and 'w'/'W' cases may be beyond its capability to analyze, but the code appears to be safe. Reported by: Coverity CID: 1008328 Reviewed by: jilles, cem MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6482
This commit is contained in:
parent
359a939783
commit
d142cf7cea
@ -1998,7 +1998,7 @@ getprompt(void *unused __unused)
|
|||||||
/*
|
/*
|
||||||
* Format prompt string.
|
* Format prompt string.
|
||||||
*/
|
*/
|
||||||
for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++)
|
for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++)
|
||||||
if (*fmt == '\\')
|
if (*fmt == '\\')
|
||||||
switch (*++fmt) {
|
switch (*++fmt) {
|
||||||
|
|
||||||
@ -2011,7 +2011,8 @@ getprompt(void *unused __unused)
|
|||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
case 'H':
|
||||||
ps[i] = '\0';
|
ps[i] = '\0';
|
||||||
gethostname(&ps[i], PROMPTLEN - i);
|
gethostname(&ps[i], PROMPTLEN - i - 1);
|
||||||
|
ps[PROMPTLEN - 1] = '\0';
|
||||||
/* Skip to end of hostname. */
|
/* Skip to end of hostname. */
|
||||||
trim = (*fmt == 'h') ? '.' : '\0';
|
trim = (*fmt == 'h') ? '.' : '\0';
|
||||||
while ((ps[i] != '\0') && (ps[i] != trim))
|
while ((ps[i] != '\0') && (ps[i] != trim))
|
||||||
@ -2061,8 +2062,9 @@ getprompt(void *unused __unused)
|
|||||||
* Emit unrecognized formats verbatim.
|
* Emit unrecognized formats verbatim.
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
ps[i++] = '\\';
|
ps[i] = '\\';
|
||||||
ps[i] = *fmt;
|
if (i < PROMPTLEN - 1)
|
||||||
|
ps[++i] = *fmt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user