This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix two bugs in argz


> > Corinna Vinschen wrote:
> > >[...]
> > >	* libc/argz/argz_create_sep.c (argz_create_sep): Initialize *argz_len
> > >	to zero.
> > >	* libc/include/argz.h: Guard against multiple inclusion.  Guard for
> > >	use with C++.
> 
> Thanks, applied.

More problems with argz:

- Per the glibc documentation, (NULL, 0) is a valid argz vector.  For
  instance, glibc's argz_create_sep returns an (argz, argz_len) vector
  of (NULL, 0) if the input string is empty, while newlib's
  argz_create_sep returns ("", 1) instead of (NULL, 0).  Newlib doesn't
  handle the (NULL, 0) vector always correctly.  The below patch is
  supposed to fix that.

- argz_extract has a subtil bug.  Consider the above case where the
  (argz, argz_len) vector is ("", 1).  This is a valid value, one empty
  argument.  When calling argz_extract on that vector, the loop counter
  variable i is initialized to argz_len - 2, which is -1 in this case.
  The problem is, i is of type size_t, which is an *unsigned* type.  So,
  actually i gets initialized to 4294967295 and the loop invariably
  crashes at one point, accessing invalid memory addresses.


Fix below.  Ok to apply?


Corinna

	* libc/argz/argz_add_sep.c (argz_add_sep): Handle empty string
	argument.
	* libc/argz/argz_append.c (argz_append): Handle empty buf argument.
	* libc/argz/argz_create_sep.c (argz_create_sep): Return (NULL, 0)
	on empty input strings.
	* libc/argz/argz_extract.c (argz_extract): Check argz_len before
	looping through argz.
	* libc/argz/argz_stringify.c (argz_stringify): Ditto.


Index: libc/argz/argz_add_sep.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/argz/argz_add_sep.c,v
retrieving revision 1.2
diff -u -p -r1.2 argz_add_sep.c
--- libc/argz/argz_add_sep.c	6 Jun 2003 19:57:51 -0000	1.2
+++ libc/argz/argz_add_sep.c	24 May 2007 12:35:11 -0000
@@ -23,11 +23,14 @@ _DEFUN (argz_add_sep, (argz, argz_len, s
 
   argz_create_sep (str, sep, &str_argz, &str_argz_len);
 
-  *argz_len += str_argz_len;
+  if (str_argz_len)
+    {
+      *argz_len += str_argz_len;
 
-  if(!(*argz = (char *)realloc(*argz, *argz_len)))
-    return ENOMEM;
+      if(!(*argz = (char *)realloc(*argz, *argz_len)))
+	return ENOMEM;
 
-  memcpy(*argz + last, str_argz, str_argz_len);
+      memcpy(*argz + last, str_argz, str_argz_len);
+    }
   return 0;
 }
Index: libc/argz/argz_append.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/argz/argz_append.c,v
retrieving revision 1.2
diff -u -p -r1.2 argz_append.c
--- libc/argz/argz_append.c	6 Jun 2003 19:57:51 -0000	1.2
+++ libc/argz/argz_append.c	24 May 2007 12:35:11 -0000
@@ -16,13 +16,16 @@ _DEFUN (argz_append, (argz, argz_len, bu
        const char *buf _AND
        size_t buf_len)
 {
-  size_t last = *argz_len;
+  if (buf_len)
+    {
+      size_t last = *argz_len;
 
-  *argz_len += buf_len;
+      *argz_len += buf_len;
 
-  if(!(*argz = (char *)realloc(*argz, *argz_len)))
-    return ENOMEM;
+      if(!(*argz = (char *)realloc(*argz, *argz_len)))
+	return ENOMEM;
 
-  memcpy(*argz + last, buf, buf_len);
+      memcpy(*argz + last, buf, buf_len);
+    }
   return 0;
 }
Index: libc/argz/argz_create_sep.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/argz/argz_create_sep.c,v
retrieving revision 1.3
diff -u -p -r1.3 argz_create_sep.c
--- libc/argz/argz_create_sep.c	23 May 2007 16:36:22 -0000	1.3
+++ libc/argz/argz_create_sep.c	24 May 2007 12:35:11 -0000
@@ -25,13 +25,21 @@ _DEFUN (argz_create_sep, (string, sep, a
   char *token = 0;
   char *iter = 0;
 
+  *argz_len = 0;
+
+  if (!string || string[0] == '\0')
+    {
+      *argz= NULL;
+      *argz_len = 0;
+      return 0;
+    }
+
   delim[0] = sep;
   delim[1] = '\0';
 
   running = strdup(string);
   old_running = running;
 
-  *argz_len = 0;
   while ((token = strsep(&running, delim)))
     {
       len = strlen(token);
Index: libc/argz/argz_extract.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/argz/argz_extract.c,v
retrieving revision 1.2
diff -u -p -r1.2 argz_extract.c
--- libc/argz/argz_extract.c	6 Jun 2003 19:57:51 -0000	1.2
+++ libc/argz/argz_extract.c	24 May 2007 12:35:11 -0000
@@ -17,14 +17,15 @@ _DEFUN (argz_extract, (argz, argz_len, a
   int j = 0;
   const size_t count = argz_count(argz, argz_len);
 
-  for (i = argz_len - 2; i > 0; i--)
-    {
-      if (argz[i] == '\0')
-        {
-          j++;
-          argv[count - j] = &argz[i + 1];
-        }
-    }
+  if (argz_len > 1)
+    for (i = argz_len - 2; i > 0; i--)
+      {
+	if (argz[i] == '\0')
+	  {
+	    j++;
+	    argv[count - j] = &argz[i + 1];
+	  }
+      }
   argv[0] = &argz[0];
   argv[count] = NULL;
 }
Index: libc/argz/argz_stringify.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/argz/argz_stringify.c,v
retrieving revision 1.2
diff -u -p -r1.2 argz_stringify.c
--- libc/argz/argz_stringify.c	6 Jun 2003 19:57:51 -0000	1.2
+++ libc/argz/argz_stringify.c	24 May 2007 12:35:11 -0000
@@ -16,9 +16,10 @@ _DEFUN (argz_stringify, (argz, argz_len,
   size_t i;
 
   /* len includes trailing \0, which we don't want to replace. */
-  for (i = 0; i < argz_len - 1; i++)
-    {
-      if (argz[i] == '\0')
-        argz[i] = sep;
-    }
+  if (argz_len > 1)
+    for (i = 0; i < argz_len - 1; i++)
+      {
+	if (argz[i] == '\0')
+	  argz[i] = sep;
+      }
 }


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]