]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xgettext: In language C, report out-of-range hexadecimal escapes.
authorBruno Haible <bruno@clisp.org>
Sat, 11 Mar 2023 00:02:47 +0000 (01:02 +0100)
committerBruno Haible <bruno@clisp.org>
Tue, 14 Mar 2023 01:57:28 +0000 (02:57 +0100)
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.

gettext-tools/src/x-c.c
gettext-tools/tests/Makefile.am
gettext-tools/tests/xgettext-c-7 [new file with mode: 0755]

index b49ddd9ccd8c15f96ac3f1f1efe1032e93d9fd8e..a5a1ea504b3f622e71403781bdff22548b4b79d2 100644 (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 '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++)
index 240a88a5185f6de10ca6ac1a77e9462f6432a170..dc9802da89919d00c4aaa19b25521d1358a126bf 100644 (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 \
diff --git a/gettext-tools/tests/xgettext-c-7 b/gettext-tools/tests/xgettext-c-7
new file mode 100755 (executable)
index 0000000..08e3144
--- /dev/null
@@ -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