top: Fix out-of-bounds read/write in show_special().
This patch fixes two problems: 1/ In the switch case 0, if sub_end is at the very end of lin[], the two null-byte writes are off-by-two (a stack-based buffer overflow). Replace this end-of-string "emulation" with an equivalent test on ch (and then goto/break out of the loop). 2/ "sub_end += 2" jumps over the null-byte terminator in lin[] if the line contains a raw (without a tilde) \001-\010 character. Detect such a null-byte terminator and goto/break out of the loop. Note: in the case of a raw \001-\010 character, the character at "sub_end + 1" is never processed (it is skipped/jumped over); this is not a security problem anymore (since 2/ was fixed), so we decided not to change this behavior, for backward-compatibility.
This commit is contained in:
parent
6b8b102cf2
commit
ed8f6d9cc6
@ -972,8 +972,6 @@ static void show_special (int interact, const char *glob) {
|
||||
if ('~' == ch) ch = *(sub_end + 1) - '0';
|
||||
switch (ch) {
|
||||
case 0: // no end delim, captab makes normal
|
||||
*(sub_end + 1) = '\0'; // extend str end, then fall through
|
||||
*(sub_end + 2) = '\0'; // ( +1 optimization for usual path )
|
||||
case 1: case 2: case 3: case 4:
|
||||
case 5: case 6: case 7: case 8:
|
||||
*sub_end = '\0';
|
||||
@ -982,6 +980,8 @@ static void show_special (int interact, const char *glob) {
|
||||
rp = scat(rp, tmp, row, sizeof(row));
|
||||
room -= (sub_end - sub_beg);
|
||||
room += utf8_delta(sub_beg);
|
||||
if (!ch) goto done_substrings;
|
||||
if (!*(sub_end + 1)) goto done_substrings;
|
||||
sub_beg = (sub_end += 2);
|
||||
break;
|
||||
default: // nothin' special, just text
|
||||
@ -989,6 +989,7 @@ static void show_special (int interact, const char *glob) {
|
||||
}
|
||||
if (0 >= room) break; // skip substrings that won't fit
|
||||
}
|
||||
done_substrings:
|
||||
|
||||
if (interact) PUTT("%s%s\n", row, Cap_clr_eol);
|
||||
else PUFF("%s%s\n", row, Caps_endline);
|
||||
|
Loading…
Reference in New Issue
Block a user