aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-03-05 12:48:06 +0000
committerRon Yorston <rmy@pobox.com>2021-03-05 12:48:06 +0000
commitdfa16f84deb0bf0d1f1cc8d223f695b2f971fc40 (patch)
tree4aaa042a72fe85c0722763fccc1cb5e3347c5025 /win32
parentb4506956a5703ae2df062ec307d76ac935be0258 (diff)
downloadbusybox-w32-dfa16f84deb0bf0d1f1cc8d223f695b2f971fc40.tar.gz
busybox-w32-dfa16f84deb0bf0d1f1cc8d223f695b2f971fc40.tar.bz2
busybox-w32-dfa16f84deb0bf0d1f1cc8d223f695b2f971fc40.zip
winansi: fix ansi emulation
The following commands (reported in GitHub issue #201): printf "\033[38;2;255;0;0mX\033[m\n" printf "\033[38;2;255;0;0m;\033[m\n" produce different results. The first correctly displays a red 'X' while the second incorrectly displays a white ';'. The problem is that process_24bit() overruns the extent of the escape sequence. As a result the loop in process_escape() which handles 'ESC[...m' sequences sees the ';' in the text as a continuation of the escape sequence. Fix this by: - reworking process_24bit() so that the overrun is avoided; - changing the test in the loop in process_escape() so that even if an overrun happens it stops processing at the end of the escape sequence. Also, save a few bytes by replacing '++str' with 'str + 1' in a few places.
Diffstat (limited to 'win32')
-rw-r--r--win32/winansi.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/win32/winansi.c b/win32/winansi.c
index 971702f18..68b568b81 100644
--- a/win32/winansi.c
+++ b/win32/winansi.c
@@ -375,17 +375,18 @@ static WORD rgb_to_console(int *rgb)
375/* 24-bit colour */ 375/* 24-bit colour */
376static char *process_24bit(char *str, WORD *attr) 376static char *process_24bit(char *str, WORD *attr)
377{ 377{
378 int count = 0; 378 int count;
379 int rgb[3] = {0, 0, 0}; 379 int rgb[3];
380 380
381 do { 381 for (count = 0; count < 3; ++count) {
382 rgb[count++] = strtol(str, (char **)&str, 10); 382 rgb[count] = strtol(str, (char **)&str, 10);
383 ++str; 383 if (*str == ';')
384 } while (*(str-1) == ';' && count < 3); 384 ++str;
385 }
385 386
386 *attr = rgb_to_console(rgb); 387 *attr = rgb_to_console(rgb);
387 388
388 return str; 389 return *(str - 1) == ';' ? str - 1 : str;
389} 390}
390 391
391/* 8-bit colour */ 392/* 8-bit colour */
@@ -435,10 +436,10 @@ static char *process_colour(char *str, WORD *attr)
435 *attr = -1; /* error return */ 436 *attr = -1; /* error return */
436 switch (val) { 437 switch (val) {
437 case 2: 438 case 2:
438 str = process_24bit(++str, attr); 439 str = process_24bit(str + 1, attr);
439 break; 440 break;
440 case 5: 441 case 5:
441 str = process_8bit(++str, attr); 442 str = process_8bit(str + 1, attr);
442 break; 443 break;
443 default: 444 default:
444 break; 445 break;
@@ -541,7 +542,7 @@ static char *process_escape(char *pos)
541 attr |= colour_1bit[val - 30]; 542 attr |= colour_1bit[val - 30];
542 break; 543 break;
543 case 38: /* 8/24 bit */ 544 case 38: /* 8/24 bit */
544 str = process_colour(++str, &t); 545 str = process_colour(str + 1, &t);
545 if (t != -1) { 546 if (t != -1) {
546 attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); 547 attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY);
547 attr |= t; 548 attr |= t;
@@ -565,7 +566,7 @@ static char *process_escape(char *pos)
565 attr |= colour_1bit[val - 40] << 4; 566 attr |= colour_1bit[val - 40] << 4;
566 break; 567 break;
567 case 48: /* 8/24 bit */ 568 case 48: /* 8/24 bit */
568 str = process_colour(++str, &t); 569 str = process_colour(str + 1, &t);
569 if (t != -1) { 570 if (t != -1) {
570 attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); 571 attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY);
571 attr |= t << 4; 572 attr |= t << 4;
@@ -581,7 +582,7 @@ static char *process_escape(char *pos)
581 return pos; 582 return pos;
582 } 583 }
583 str++; 584 str++;
584 } while (*(str-1) == ';'); 585 } while (str < func);
585 586
586 current_attr = attr; 587 current_attr = attr;
587 if (reverse) 588 if (reverse)