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]

[patch 4/4] wordexp: step past we_offs words when freeing


2012-09-13  Peter Rosin  <peda@lysator.liu.se>

	* libc/posix/wordexp.c (wordexp): Help wordfree step past
	we_offs entries when freeing.
	* libc/posix/wordfree.c (wordfree): Step past we_offs words
	before starting to free.

Index: newlib/libc/posix/wordexp.c
===================================================================
--- newlib.orig/libc/posix/wordexp.c
+++ newlib/libc/posix/wordexp.c
@@ -63,10 +63,17 @@ wordexp(const char *words, wordexp_t *pw
     {
       offs = pwordexp->we_offs;
 
-      wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *));
+      /* See the comment near the *other* realloc call for an explanation of
+       * this mess.
+       */
+      wordv = pwordexp->we_wordv;
+      if (wordv)
+        --wordv;
+      wordv = (char **)realloc(wordv, (1 + pwordexp->we_wordc + offs + 1) * sizeof(char *));
       if (!wordv)
         return err;
-      pwordexp->we_wordv = wordv;
+      *wordv = (char *)(wordv + 1 + offs);
+      pwordexp->we_wordv = wordv + 1;
 
       for (i = 0; i < offs; i++)
         pwordexp->we_wordv[i] = NULL;
@@ -142,11 +149,25 @@ wordexp(const char *words, wordexp_t *pw
 
       num_words = atoi(tmp);
 
-      wordv = (char **)realloc(pwordexp->we_wordv,
-                               (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
+      /* POSIX does not give us the liberty to trust the we_offs member if
+       * WRDE_DOOFFS is not given, and we can therefore not use it to store
+       * the fact that no offset has been given. Changing the size of
+       * wordexp_t breaks existing applications. Therefore, when allocating
+       * storage for the expanded words, allocate one extra pointer at the
+       * start and make the we_wordv member point one pointer into the
+       * allocated storage. Use the extra pointer to store where the
+       * real expanded words begin, i.e. always keep track of the offset
+       * even if WRDE_DOOFFS is not given.
+       */
+      wordv = pwordexp->we_wordv;
+      if (wordv)
+        --wordv;
+      wordv = (char **)realloc(wordv,
+                               (1 + pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
       if (!wordv)
         goto cleanup;
-      pwordexp->we_wordv = wordv;
+      *wordv = (char *)(wordv + 1 + offs);
+      pwordexp->we_wordv = wordv + 1;
 
       /* Get number of bytes required for storage of all num_words words. */
       if (!fgets(tmp, MAXLINELEN, f))
Index: newlib/libc/posix/wordfree.c
===================================================================
--- newlib.orig/libc/posix/wordfree.c
+++ newlib/libc/posix/wordfree.c
@@ -25,6 +25,7 @@ void
 wordfree(wordexp_t *pwordexp)
 {
   int i;
+  char **wordv;
 
   if (pwordexp == NULL)
     return;
@@ -32,10 +33,15 @@ wordfree(wordexp_t *pwordexp)
   if (pwordexp->we_wordv == NULL)
     return;
 
+  /* we_wordv points one pointer into the allocated storage, the
+   * the extra pointer points at the address of the pointer to the
+   * first expanded word.
+   */
+  wordv = (char **)(*(pwordexp->we_wordv - 1));
   for(i = 0; i < pwordexp->we_wordc; i++)
-    free(pwordexp->we_wordv[i]);
+    free(*wordv++);
 
-  free(pwordexp->we_wordv);
+  free(pwordexp->we_wordv - 1);
   pwordexp->we_wordv = NULL;
 }
 


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