diff options
author | Bruno Haible <bruno@clisp.org> | 2023-03-11 01:02:47 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2023-03-14 02:57:28 +0100 |
commit | 0c0345632aedfb254b69f72cce268728113edf2e (patch) | |
tree | c6e019f7e266bffb4ea938da868b9a3f1f2dbbb1 /gettext-tools/src/x-c.c | |
parent | 53a2b763b8dc516bd20258ea5aead80bc7ab7cf3 (diff) | |
download | gettext-0c0345632aedfb254b69f72cce268728113edf2e.tar.gz |
xgettext: In language C, report out-of-range hexadecimal escapes.
This avoids a later crash
"Assertion `UNICODE_VALUE (c) >= 0 && UNICODE_VALUE (c) < 0x110000' failed."
* gettext-tools/src/x-c.c (phase7_getc): When the value of a hexadecimal escape
sequence overflows, warn and use the last value before it overflowed.
* gettext-tools/tests/xgettext-c-7: New file.
* gettext-tools/tests/Makefile.am (TESTS): Add it.
Diffstat (limited to 'gettext-tools/src/x-c.c')
-rw-r--r-- | gettext-tools/src/x-c.c | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/gettext-tools/src/x-c.c b/gettext-tools/src/x-c.c index b49ddd9cc..a5a1ea504 100644 --- a/gettext-tools/src/x-c.c +++ b/gettext-tools/src/x-c.c @@ -994,7 +994,7 @@ struct token_ty static int phase7_getc () { - int c, n, j; + int c, j; /* Use phase 3, because phase 4 elides comments. */ c = phase3_getc (); @@ -1072,56 +1072,83 @@ phase7_getc () case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': break; } - n = 0; - for (;;) - { - switch (c) - { - default: - phase3_ungetc (c); - return n; + { + int n; + bool overflow; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - n = n * 16 + c - '0'; - break; + n = 0; + overflow = false; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - n = n * 16 + 10 + c - 'A'; - break; + for (;;) + { + switch (c) + { + default: + phase3_ungetc (c); + if (overflow) + { + error_with_progname = false; + error (0, 0, _("%s:%d: warning: hexadecimal escape sequence out of range"), + logical_file_name, line_number); + error_with_progname = true; + } + return n; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (n < 0x100 / 16) + n = n * 16 + c - '0'; + else + overflow = true; + break; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - n = n * 16 + 10 + c - 'a'; - break; - } - c = phase3_getc (); - } - return n; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + if (n < 0x100 / 16) + n = n * 16 + 10 + c - 'A'; + else + overflow = true; + break; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + if (n < 0x100 / 16) + n = n * 16 + 10 + c - 'a'; + else + overflow = true; + break; + } + c = phase3_getc (); + } + } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - n = 0; - for (j = 0; j < 3; ++j) - { - n = n * 8 + c - '0'; - c = phase3_getc (); - switch (c) - { - default: - break; + { + int n; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - continue; - } - break; - } - phase3_ungetc (c); - return n; + n = 0; + for (j = 0; j < 3; ++j) + { + n = n * 8 + c - '0'; + c = phase3_getc (); + switch (c) + { + default: + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + continue; + } + break; + } + phase3_ungetc (c); + return n; + } case 'U': case 'u': { unsigned char buf[8]; + int n; n = 0; for (j = 0; j < (c == 'u' ? 4 : 8); j++) |