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;
+ }
}