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.
This commit is contained in:
Bruno Haible 2023-03-11 01:02:47 +01:00
parent 53a2b763b8
commit 0c0345632a
3 changed files with 92 additions and 40 deletions

View File

@ -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 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
n = n * 16 + 10 + c - 'a';
break;
}
c = phase3_getc ();
}
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':
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++)

View File

@ -85,6 +85,7 @@ TESTS = gettext-1 gettext-2 \
xgettext-awk-1 xgettext-awk-2 \
xgettext-awk-stackovfl-1 xgettext-awk-stackovfl-2 \
xgettext-c-2 xgettext-c-3 xgettext-c-4 xgettext-c-5 xgettext-c-6 \
xgettext-c-7 \
xgettext-c-comment-1 xgettext-c-comment-2 xgettext-c-comment-3 \
xgettext-c-comment-4 xgettext-c-comment-5 xgettext-c-comment-6 \
xgettext-c-escape-1 xgettext-c-escape-2 xgettext-c-escape-3 \

View File

@ -0,0 +1,24 @@
#! /bin/sh
. "${srcdir=.}/init.sh"; path_prepend_ . ../src
# Test C support: out-of-range hexadecimal escape sequences.
: ${XGETTEXT=xgettext}
cat <<\EOF > xg-c-7.c
gettext("\x678888");
EOF
${XGETTEXT} --omit-header --no-location -o xg-c-7.tmp xg-c-7.c || Exit 1
func_filter_POT_Creation_Date xg-c-7.tmp xg-c-7.po
cat <<\EOF > xg-c-7.ok
msgid "g"
msgstr ""
EOF
: ${DIFF=diff}
${DIFF} xg-c-7.ok xg-c-7.po
result=$?
exit $result