added g_strlcat() and g_strlcpy() wrappers, supplied by David Wheeler
authorTim Janik <timj@gtk.org>
Wed, 26 Jul 2000 03:51:07 +0000 (03:51 +0000)
committerTim Janik <timj@src.gnome.org>
Wed, 26 Jul 2000 03:51:07 +0000 (03:51 +0000)
Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>

        * configure.in:
        * testglib.c:
        * gstrfuncs.c:
        * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
        David Wheeler <dwheeler@ida.org>:

        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
          safe manipulation of fixed-length string buffers.
          These functions were originally developed by Todd Miller to simplify
          development of security-related programs, and
          are available on many (but not all) Unix-like systems,
          including OpenBSD, FreeBSD, and Solaris.  See
          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
          and http://www.openbsd.org/security.html.
          If there's a strlcpy/strlcat on the system, it's called, otherwise
          an implementation is provided.

        * testglib.c: Added tests for g_strlcpy, g_strlcat.

16 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
acconfig.h
configure.in
glib.h
glib/glib.h
glib/gstrfuncs.c
gstrfuncs.c
testglib.c
tests/testglib.c

index 572c768..460973a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index 572c768..460973a 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul 26 05:47:48 2000  Tim Janik  <timj@gtk.org>
+
+       * configure.in:
+       * testglib.c:
+       * gstrfuncs.c:
+       * glib.h: added g_strlcat() and g_strlcpy() wrappers, supplied by
+       David Wheeler <dwheeler@ida.org>:
+
+        * glib.h, gstrfuncs.c: added g_strlcpy and g_strlcat to support
+          safe manipulation of fixed-length string buffers.
+          These functions were originally developed by Todd Miller to simplify
+          development of security-related programs, and
+          are available on many (but not all) Unix-like systems,
+          including OpenBSD, FreeBSD, and Solaris.  See
+          ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+          and http://www.openbsd.org/security.html.
+          If there's a strlcpy/strlcat on the system, it's called, otherwise
+          an implementation is provided.
+
+        * testglib.c: Added tests for g_strlcpy, g_strlcat.
+
 Wed Jul 26 05:03:24 2000  Tim Janik  <timj@gtk.org>
 
        * acglib.m4 (GLIB_SIZEOF): include <stdlib.h> and <stddef.h> if
index f79d400..a3d1ea4 100644 (file)
@@ -65,6 +65,7 @@
 #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
 #undef HAVE_PWD_H
 #undef HAVE_PW_GECOS
+#undef HAVE_STRLCPY
 #undef HAVE_SYS_PARAM_H
 #undef HAVE_SYS_POLL_H
 #undef HAVE_SYS_SELECT_H
index 978ea5f..3722b19 100644 (file)
@@ -456,8 +456,24 @@ AC_TRY_COMPILE([#include <langinfo.h>],
    AC_DEFINE(HAVE_CODESET)
    have_codeset=yes,
    have_codeset=no)
-
 AC_MSG_RESULT($have_codeset)
+
+
+dnl ****************************************
+dnl *** strlcpy/strlcat                  ***
+dnl ****************************************
+# Check for strlcpy
+AC_MSG_CHECKING(for strlcpy/strlcat)
+AC_TRY_LINK([#include <stdlib.h>
+#include <string.h>], [
+char *p = malloc(10);
+(void) strlcpy(p, "hi", 10);
+(void) strlcat(p, "bye", 10);
+], glib_ok=yes, glib_ok=no)
+AC_MSG_RESULT($glib_ok)
+if test $glib_ok = yes; then
+    AC_DEFINE(HAVE_STRLCPY)
+fi
   
 
 dnl **********************
diff --git a/glib.h b/glib.h
index 7f31ba9..bbc23dc 100644 (file)
--- a/glib.h
+++ b/glib.h
@@ -1654,6 +1654,12 @@ gint      g_strncasecmp          (const gchar *s1,
 gchar*  g_strdown              (gchar       *string);
 gchar*  g_strup                (gchar       *string);
 gchar*  g_strreverse           (gchar       *string);
+gsize   g_strlcpy              (gchar       *dest,
+                                const gchar *src,
+                                gsize        dest_size);
+gsize   g_strlcat              (gchar       *dest,
+                                const gchar *src,
+                                gsize        dest_size);
 /* removes leading spaces */
 gchar*   g_strchug              (gchar        *string);
 /* removes trailing spaces */
index 7f31ba9..bbc23dc 100644 (file)
@@ -1654,6 +1654,12 @@ gint      g_strncasecmp          (const gchar *s1,
 gchar*  g_strdown              (gchar       *string);
 gchar*  g_strup                (gchar       *string);
 gchar*  g_strreverse           (gchar       *string);
+gsize   g_strlcpy              (gchar       *dest,
+                                const gchar *src,
+                                gsize        dest_size);
+gsize   g_strlcat              (gchar       *dest,
+                                const gchar *src,
+                                gsize        dest_size);
 /* removes leading spaces */
 gchar*   g_strchug              (gchar        *string);
 /* removes trailing spaces */
index 0bec543..b14f7ee 100644 (file)
@@ -797,25 +797,150 @@ extern const char * strsignal(int);
     }
 
   sprintf (msg, "unknown signal (%d)", signum);
-
+  
   return msg;
 }
 
+/* Functions g_strlcpy and g_strlcat were originally developed by
+ * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
+ * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+ * for more information.
+ */
+
+#ifdef HAVE_STRLCPY
+/* Use the native ones, if available; they might be implemented in assembly */
+gsize
+g_strlcpy (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  return strlcpy (dest, src, dest_size);
+}
+
+gsize
+g_strlcat (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  return strlcat (dest, src, dest_size);
+}
+
+#else /* ! HAVE_STRLCPY */
+/* g_strlcpy
+ *
+ * Copy string src to buffer dest (of buffer size dest_size).  At most
+ * dest_size-1 characters will be copied.  Always NUL terminates
+ * (unless dest_size == 0).  This function does NOT allocate memory.
+ * Unlike strncpy, this function doesn't pad dest (so it's often faster).
+ * Returns size of attempted result, strlen(src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcpy (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize n = dest_size;
+  
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  /* Copy as many bytes as will fit */
+  if (n != 0 && --n != 0)
+    do
+      {
+       register gchar c = *s++;
+       
+       *d++ = c;
+       if (c == 0)
+         break;
+      }
+    while (--n != 0);
+  
+  /* If not enough room in dest, add NUL and traverse rest of src */
+  if (n == 0)
+    {
+      if (dest_size != 0)
+       *d = 0;
+      while (*s++)
+       ;
+    }
+  
+  return s - src - 1;  /* count does not include NUL */
+}
+
+/* g_strlcat
+ *
+ * Appends string src to buffer dest (of buffer size dest_size).
+ * At most dest_size-1 characters will be copied.
+ * Unlike strncat, dest_size is the full size of dest, not the space left over.
+ * This function does NOT allocate memory.
+ * This always NUL terminates (unless siz == 0 or there were no NUL characters
+ * in the dest_size characters of dest to start with).
+ * Returns size of attempted result, which is
+ * MIN (dest_size, strlen (original dest)) + strlen (src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcat (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize bytes_left = dest_size;
+  gsize dlength;  /* Logically, MIN (strlen (d), dest_size) */
+  
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  /* Find the end of dst and adjust bytes left but don't go past end */
+  while (*d != 0 && bytes_left-- != 0)
+    d++;
+  dlength = d - dest;
+  bytes_left = dest_size - dlength;
+  
+  if (bytes_left == 0)
+    return dlength + strlen (s);
+  
+  while (*s != 0)
+    {
+      if (bytes_left != 1)
+       {
+         *d++ = *s;
+         bytes_left--;
+       }
+      s++;
+    }
+  *d = 0;
+  
+  return dlength + (s - src);  /* count does not include NUL */
+}
+#endif /* ! HAVE_STRLCPY */
+
 gchar*
 g_strdown (gchar *string)
 {
   register guchar *s;
-
+  
   g_return_val_if_fail (string != NULL, NULL);
-
+  
   s = string;
-
+  
   while (*s)
     {
       *s = tolower (*s);
       s++;
     }
-
+  
   return string;
 }
 
index 0bec543..b14f7ee 100644 (file)
@@ -797,25 +797,150 @@ extern const char * strsignal(int);
     }
 
   sprintf (msg, "unknown signal (%d)", signum);
-
+  
   return msg;
 }
 
+/* Functions g_strlcpy and g_strlcat were originally developed by
+ * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
+ * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+ * for more information.
+ */
+
+#ifdef HAVE_STRLCPY
+/* Use the native ones, if available; they might be implemented in assembly */
+gsize
+g_strlcpy (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  return strlcpy (dest, src, dest_size);
+}
+
+gsize
+g_strlcat (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  return strlcat (dest, src, dest_size);
+}
+
+#else /* ! HAVE_STRLCPY */
+/* g_strlcpy
+ *
+ * Copy string src to buffer dest (of buffer size dest_size).  At most
+ * dest_size-1 characters will be copied.  Always NUL terminates
+ * (unless dest_size == 0).  This function does NOT allocate memory.
+ * Unlike strncpy, this function doesn't pad dest (so it's often faster).
+ * Returns size of attempted result, strlen(src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcpy (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize n = dest_size;
+  
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  /* Copy as many bytes as will fit */
+  if (n != 0 && --n != 0)
+    do
+      {
+       register gchar c = *s++;
+       
+       *d++ = c;
+       if (c == 0)
+         break;
+      }
+    while (--n != 0);
+  
+  /* If not enough room in dest, add NUL and traverse rest of src */
+  if (n == 0)
+    {
+      if (dest_size != 0)
+       *d = 0;
+      while (*s++)
+       ;
+    }
+  
+  return s - src - 1;  /* count does not include NUL */
+}
+
+/* g_strlcat
+ *
+ * Appends string src to buffer dest (of buffer size dest_size).
+ * At most dest_size-1 characters will be copied.
+ * Unlike strncat, dest_size is the full size of dest, not the space left over.
+ * This function does NOT allocate memory.
+ * This always NUL terminates (unless siz == 0 or there were no NUL characters
+ * in the dest_size characters of dest to start with).
+ * Returns size of attempted result, which is
+ * MIN (dest_size, strlen (original dest)) + strlen (src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcat (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize bytes_left = dest_size;
+  gsize dlength;  /* Logically, MIN (strlen (d), dest_size) */
+  
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src  != NULL, NULL);
+  
+  /* Find the end of dst and adjust bytes left but don't go past end */
+  while (*d != 0 && bytes_left-- != 0)
+    d++;
+  dlength = d - dest;
+  bytes_left = dest_size - dlength;
+  
+  if (bytes_left == 0)
+    return dlength + strlen (s);
+  
+  while (*s != 0)
+    {
+      if (bytes_left != 1)
+       {
+         *d++ = *s;
+         bytes_left--;
+       }
+      s++;
+    }
+  *d = 0;
+  
+  return dlength + (s - src);  /* count does not include NUL */
+}
+#endif /* ! HAVE_STRLCPY */
+
 gchar*
 g_strdown (gchar *string)
 {
   register guchar *s;
-
+  
   g_return_val_if_fail (string != NULL, NULL);
-
+  
   s = string;
-
+  
   while (*s)
     {
       *s = tolower (*s);
       s++;
     }
-
+  
   return string;
 }
 
index 7e3f865..f5fc215 100644 (file)
@@ -372,6 +372,7 @@ main (int   argc,
   TEST (NULL, sizeof (gint16) == 2);
   g_print ("\nchecking size of gint32: %d", (int)sizeof (gint32));
   TEST (NULL, sizeof (gint32) == 4);
+  g_print ("\nchecking size of gsize: %d", (int)sizeof (gsize));
 #ifdef G_HAVE_GINT64
   g_print ("\nchecking size of gint64: %d", (int)sizeof (gint64));
   TEST (NULL, sizeof (gint64) == 8);
@@ -879,9 +880,66 @@ main (int   argc,
   g_assert(strcmp(string, GLIB_TEST_STRING GLIB_TEST_STRING
                          GLIB_TEST_STRING) == 0);
   g_free(string);
-  
   g_print ("ok\n");
+  
 
+  g_print("checking g_strlcpy/g_strlcat...");
+  /* The following is a torture test for strlcpy/strlcat, with lots of
+   * checking; normal users wouldn't use them this way!
+   */
+  string = g_malloc (6);
+  *(string + 5) = 'Z'; /* guard value, shouldn't change during test */
+  *string = 'q';
+  g_assert (g_strlcpy(string, "" , 5) == 0);
+  g_assert ( *string == '\0' );
+  *string = 'q';
+  g_assert (g_strlcpy(string, "abc" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "abc"));
+  g_assert (g_strlcpy(string, "abcd" , 5) == 4);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  g_assert (g_strlcpy(string, "abcde" , 5) == 5);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  g_assert (g_strlcpy(string, "abcdef" , 5) == 6);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  *string = 'Y';
+  *(string + 1)= '\0';
+  g_assert (g_strlcpy(string, "Hello" , 0) == 5);
+  g_assert (*string == 'Y');
+  *string = '\0';
+  g_assert (g_strlcat(string, "123" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "123"));
+  g_assert (g_strlcat(string, "" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "123"));
+  g_assert (g_strlcat(string, "4", 5) == 4);
+  g_assert (g_str_equal(string, "1234"));
+  g_assert (g_strlcat(string, "5", 5) == 5);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert (g_str_equal(string, "1234"));
+  g_assert ( *(string + 5) == 'Z' );
+  *string = 'Y';
+  *(string + 1)= '\0';
+  g_assert (g_strlcat(string, "123" , 0) == 3);
+  g_assert (*string == 'Y');
+  
+  /* A few more tests, demonstrating more "normal" use  */
+  g_assert (g_strlcpy(string, "hi", 5) == 2);
+  g_assert (g_str_equal(string, "hi"));
+  g_assert (g_strlcat(string, "t", 5) == 3);
+  g_assert (g_str_equal(string, "hit"));
+  g_free(string);
+
+  g_print ("ok\n");
+  
+  
   g_print ("checking g_strdup_printf...");
   string = g_strdup_printf ("%05d %-5s", 21, "test");
   g_assert (string != NULL);
index 7e3f865..f5fc215 100644 (file)
@@ -372,6 +372,7 @@ main (int   argc,
   TEST (NULL, sizeof (gint16) == 2);
   g_print ("\nchecking size of gint32: %d", (int)sizeof (gint32));
   TEST (NULL, sizeof (gint32) == 4);
+  g_print ("\nchecking size of gsize: %d", (int)sizeof (gsize));
 #ifdef G_HAVE_GINT64
   g_print ("\nchecking size of gint64: %d", (int)sizeof (gint64));
   TEST (NULL, sizeof (gint64) == 8);
@@ -879,9 +880,66 @@ main (int   argc,
   g_assert(strcmp(string, GLIB_TEST_STRING GLIB_TEST_STRING
                          GLIB_TEST_STRING) == 0);
   g_free(string);
-  
   g_print ("ok\n");
+  
 
+  g_print("checking g_strlcpy/g_strlcat...");
+  /* The following is a torture test for strlcpy/strlcat, with lots of
+   * checking; normal users wouldn't use them this way!
+   */
+  string = g_malloc (6);
+  *(string + 5) = 'Z'; /* guard value, shouldn't change during test */
+  *string = 'q';
+  g_assert (g_strlcpy(string, "" , 5) == 0);
+  g_assert ( *string == '\0' );
+  *string = 'q';
+  g_assert (g_strlcpy(string, "abc" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "abc"));
+  g_assert (g_strlcpy(string, "abcd" , 5) == 4);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  g_assert (g_strlcpy(string, "abcde" , 5) == 5);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  g_assert (g_strlcpy(string, "abcdef" , 5) == 6);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert ( *(string + 5) == 'Z' );
+  g_assert (g_str_equal(string, "abcd"));
+  *string = 'Y';
+  *(string + 1)= '\0';
+  g_assert (g_strlcpy(string, "Hello" , 0) == 5);
+  g_assert (*string == 'Y');
+  *string = '\0';
+  g_assert (g_strlcat(string, "123" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "123"));
+  g_assert (g_strlcat(string, "" , 5) == 3);
+  g_assert ( *(string + 3) == '\0' );
+  g_assert (g_str_equal(string, "123"));
+  g_assert (g_strlcat(string, "4", 5) == 4);
+  g_assert (g_str_equal(string, "1234"));
+  g_assert (g_strlcat(string, "5", 5) == 5);
+  g_assert ( *(string + 4) == '\0' );
+  g_assert (g_str_equal(string, "1234"));
+  g_assert ( *(string + 5) == 'Z' );
+  *string = 'Y';
+  *(string + 1)= '\0';
+  g_assert (g_strlcat(string, "123" , 0) == 3);
+  g_assert (*string == 'Y');
+  
+  /* A few more tests, demonstrating more "normal" use  */
+  g_assert (g_strlcpy(string, "hi", 5) == 2);
+  g_assert (g_str_equal(string, "hi"));
+  g_assert (g_strlcat(string, "t", 5) == 3);
+  g_assert (g_str_equal(string, "hit"));
+  g_free(string);
+
+  g_print ("ok\n");
+  
+  
   g_print ("checking g_strdup_printf...");
   string = g_strdup_printf ("%05d %-5s", 21, "test");
   g_assert (string != NULL);