Surrogates not allowed in UTF-8 data. Added UTF-8 tests.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 3 Feb 2004 21:27:21 +0000 (21:27 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 3 Feb 2004 21:27:21 +0000 (21:27 +0000)
CHANGES
lib/silcutil/silcstrutil.c
lib/silcutil/tests/Makefile.am [new file with mode: 0644]
lib/silcutil/tests/test_silcstrutil.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 4f36eee814b029bcd1fb4c7f0e69d0cc6395b845..0f505a0ad4fc8f527daed279937acb37e8ca1514 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+Tue Feb  3 23:25:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Surrogates not allowed in UTF-8 strings, updated decoder.
+         Affected file lib/silcutil/silcstrutil.c.  Added UTF-8
+         testers in lib/silcutil/tests/ directory.
+
 Wed Jan 14 18:42:44 EET 2004  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SILC_CLIENT_CONN_ERROR_KE, ERROR_AUTH, ERROR_RESUME and
@@ -16,7 +22,7 @@ Tue Jan 04 12:16:04 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
        * Added DIST_SUBDIRS symbols to include all subdirs in distributions.
          Affected files lib/silcutil/Makefile.am, lib/silcmath/Makefile.am
 
-       * Typofix in Irssi::Silc module.  Affected file 
+       * Typofix in Irssi::Silc module.  Affected file
          irssi/src/perl/silc/Silc.xs.
 
 Tue Jan 04 02:43:44 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
@@ -27,12 +33,12 @@ Tue Jan 04 02:43:44 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
          irssi/src/fe-common/silc/module-formats.[ch], fe-silc-messages.c;
          irssi/src/silc/core/client_ops.c, silc-channels.c, silc-servers.c
 
-       * Fixed typo in /ACTION help.  Affected file 
+       * Fixed typo in /ACTION help.  Affected file
          irssi/docs/help/in/action.in
 
 Mon Jan 03 23:26:38 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
 
-       * Fixed typo in perl module.  Affected file 
+       * Fixed typo in perl module.  Affected file
          irssi/src/perl/silc/Server.xs
 
        * Changed the way ACTION flagged messages are treated. Added support
index 61b994a2ae65c2ba6be377b5bb7d370b8eec4c2d..f3cfdaad0c64a28ba80c3c7e3bf20a844889cd80 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcstrutil.c 
+  silcstrutil.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2003 Pekka Riikonen
+  Copyright (C) 2002 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -391,10 +391,16 @@ SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
       if (i + 2 >= utf8_len)
        return 0;
 
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
          ((utf8[i + 2] & 0xc0) != 0x80))
         return 0;
 
+      /* Surrogates not allowed (D800-DFFF) */
+      if (utf8[i] == 0xed &&
+         utf8[i + 1] >= 0xa0 && utf8[i + 1] <= 0xbf &&
+         utf8[i + 2] >= 0x80 && utf8[i + 2] <= 0xbf)
+       return 0;
+
       charval = (utf8[i++]  & 0xf)  << 12;
       charval |= (utf8[i++] & 0x3f) << 6;
       charval |= utf8[i] & 0x3f;
@@ -404,7 +410,7 @@ SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
       if (i + 3 >= utf8_len)
        return 0;
 
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
          ((utf8[i + 2] & 0xc0) != 0x80) ||
          ((utf8[i + 3] & 0xc0) != 0x80))
         return 0;
@@ -419,7 +425,7 @@ SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
       if (i + 4 >= utf8_len)
        return 0;
 
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
          ((utf8[i + 2] & 0xc0) != 0x80) ||
          ((utf8[i + 3] & 0xc0) != 0x80) ||
          ((utf8[i + 4] & 0xc0) != 0x80))
@@ -436,7 +442,7 @@ SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
       if (i + 5 >= utf8_len)
        return 0;
 
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
          ((utf8[i + 2] & 0xc0) != 0x80) ||
          ((utf8[i + 3] & 0xc0) != 0x80) ||
          ((utf8[i + 4] & 0xc0) != 0x80) ||
@@ -559,13 +565,13 @@ do {                                                                      \
 
 /* Parses MIME object and MIME header in it. */
 
-bool 
+bool
 silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
                 char *version, SilcUInt32 version_size,
                 char *content_type, SilcUInt32 content_type_size,
                 char *transfer_encoding, SilcUInt32 transfer_encoding_size,
                 unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len)
-{ 
+{
   int i;
   unsigned char *tmp;
 
@@ -582,7 +588,7 @@ silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
     return FALSE;
 
   if (mime_data_ptr)
-    *mime_data_ptr = (unsigned char *)mime + i + 
+    *mime_data_ptr = (unsigned char *)mime + i +
            (mime[i] == '\n' ? 2 : 4);
   if (mime_data_len)
     *mime_data_len = mime_len - (i + (mime[i] == '\n' ? 2 : 4));
@@ -591,7 +597,7 @@ silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
   tmp = strstr(mime, MIME_CONTENT_TYPE);
   if (!tmp || (tmp - mime) >= i)
     return FALSE;
-  
+
   /* Get MIME version, Content-Type and Transfer Encoding fields */
   MIME_GET_FIELD(mime, mime_len,
                 MIME_VERSION, MIME_VERSION_LEN,
diff --git a/lib/silcutil/tests/Makefile.am b/lib/silcutil/tests/Makefile.am
new file mode 100644 (file)
index 0000000..ec7d5f3
--- /dev/null
@@ -0,0 +1,27 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2004 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+bin_PROGRAMS =         test_silcstrutil
+
+test_silcstrutil_SOURCES = test_silcstrutil.c
+
+LIBS = $(SILC_COMMON_LIBS)
+LDADD = -L.. -L../.. -lsilc
+
+include $(top_srcdir)/Makefile.defines.in
diff --git a/lib/silcutil/tests/test_silcstrutil.c b/lib/silcutil/tests/test_silcstrutil.c
new file mode 100644 (file)
index 0000000..1e537a6
--- /dev/null
@@ -0,0 +1,85 @@
+/* UTF-8 decoding tests */
+
+#include "silcincludes.h"
+
+#define utf8fail(n, data, len)                 \
+const unsigned char u##n[] = (data);           \
+int u##n##l = len;
+
+#define utf8failc(n)                                                         \
+do {                                                                         \
+  if (!silc_utf8_valid(u##n, u##n##l))                                       \
+    SILC_LOG_DEBUG(("%d: not valid UTF-8, correctly detected, no error", n)); \
+  else {                                                                     \
+    SILC_LOG_DEBUG(("%d: parser did not detect malformed UTF-8, error", n));  \
+    goto err;                                                                \
+  }                                                                          \
+} while(0)
+
+/* UTF-8 Test vectors that MUST fail */
+utf8fail(1, "\x80", 1);
+utf8fail(2, "\xbf", 1);
+utf8fail(3, "\xfe", 1);
+utf8fail(4, "\xff", 1);
+utf8fail(5, "\xfe\xfe\xff\xff", 4);
+utf8fail(6, "\xc0\xa0", 2);
+utf8fail(7, "\xe0\x80\xaf", 3);
+utf8fail(8, "\xf0\x80\x80\xaf", 4);
+utf8fail(9, "\xf8\x80\x80\x80\xaf", 5);
+utf8fail(10, "\xfc\x80\x80\x80\x80\xaf", 6);
+utf8fail(11, "\xc0\x80", 2);
+utf8fail(12, "\xe0\x80\x80", 3);
+utf8fail(13, "\xf0\x80\x80\x80", 4);
+utf8fail(14, "\xf8\x80\x80\x80\x80", 5);
+utf8fail(15, "\xfc\x80\x80\x80\x80\x80", 6);
+utf8fail(16, "\xc1\xbf", 2);
+utf8fail(17, "\xe0\x9f\xbf", 3);
+utf8fail(18, "\xf0\x8f\xbf\xbf", 4);
+utf8fail(19, "\xf8\x87\xbf\xbf\xbf", 5);
+utf8fail(20, "\xfc\x83\xbf\xbf\xbf\xbf", 6);
+utf8fail(21, "\xed\xa0\x80", 3);
+utf8fail(22, "\xed\xad\xbf", 3);
+utf8fail(23, "\xed\xae\x80", 3);
+utf8fail(24, "\xed\xaf\xbf", 3);
+utf8fail(25, "\xed\xb0\x80", 3);
+utf8fail(26, "\xed\xbe\x80", 3);
+utf8fail(27, "\xed\xbf\xbf", 3);
+utf8fail(28, "\xfc\x20\xfd\x20", 4);
+utf8fail(29, "\xf8\xf9\xfa\xfb", 4);
+utf8fail(30, "\xf0\x20\xf9\x20\xfa\x20\xfb\x20", 8);
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*strutil*");
+  }
+
+  /* Failure tests */
+  utf8failc(1);  utf8failc(2);
+  utf8failc(3);  utf8failc(4);
+  utf8failc(5);  utf8failc(6);
+  utf8failc(7);  utf8failc(8);
+  utf8failc(9);  utf8failc(10);
+  utf8failc(11);  utf8failc(12);
+  utf8failc(13);  utf8failc(14);
+  utf8failc(15);  utf8failc(16);
+  utf8failc(17);  utf8failc(18);
+  utf8failc(19);  utf8failc(20);
+  utf8failc(21);  utf8failc(22);
+  utf8failc(23);  utf8failc(24);
+  utf8failc(25);  utf8failc(26);
+  utf8failc(27);  utf8failc(28);
+  utf8failc(29);  utf8failc(30);
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}