diff options
author | truckman <truckman@FreeBSD.org> | 2016-05-23 01:01:23 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2016-05-23 01:01:23 +0000 |
commit | d142cf7cea6adc20a96a0a7aa48a1c2ae61c7264 (patch) | |
tree | ee28858c22f7e3cd82d1b61ced08e18fb2efe8dc /bin | |
parent | 359a9397836436cfa9d00eafcc8e54af71328f1c (diff) | |
download | FreeBSD-src-d142cf7cea6adc20a96a0a7aa48a1c2ae61c7264.zip FreeBSD-src-d142cf7cea6adc20a96a0a7aa48a1c2ae61c7264.tar.gz |
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
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/parser.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c index f3cc98d..cc04a2a 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -1998,7 +1998,7 @@ getprompt(void *unused __unused) /* * Format prompt string. */ - for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++) + for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++) if (*fmt == '\\') switch (*++fmt) { @@ -2011,7 +2011,8 @@ getprompt(void *unused __unused) case 'h': case 'H': ps[i] = '\0'; - gethostname(&ps[i], PROMPTLEN - i); + gethostname(&ps[i], PROMPTLEN - i - 1); + ps[PROMPTLEN - 1] = '\0'; /* Skip to end of hostname. */ trim = (*fmt == 'h') ? '.' : '\0'; while ((ps[i] != '\0') && (ps[i] != trim)) @@ -2061,8 +2062,9 @@ getprompt(void *unused __unused) * Emit unrecognized formats verbatim. */ default: - ps[i++] = '\\'; - ps[i] = *fmt; + ps[i] = '\\'; + if (i < PROMPTLEN - 1) + ps[++i] = *fmt; break; } else |