]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/newlib-tumbl.git/commitdiff
* libc/posix/wordfree.c (wordfree): The wrong words are freed
authorCorinna Vinschen <corinna@vinschen.de>
Tue, 9 Oct 2012 12:05:50 +0000 (12:05 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Tue, 9 Oct 2012 12:05:50 +0000 (12:05 +0000)
when WRDE_DOOFFS is in use. Restructure the code so that the memory
needed to be freed is instead kept in an internal linked list...
* libc/posix/wordexp2.h: ...as defined here...
* libc/posix/wordexp.c (wordexp): ...and build this internal
linked list here, avoiding wasteful strdup calls in the process.

newlib/ChangeLog
newlib/libc/posix/wordexp.c
newlib/libc/posix/wordexp2.h [new file with mode: 0644]
newlib/libc/posix/wordfree.c

index 298fc39e1b4615a080649c20b09e27bba2d0a273..ff157f9410a0656d8c89a2b3f5ace98e07e74098 100644 (file)
@@ -1,3 +1,12 @@
+2012-10-09  Peter Rosin  <peda@lysator.liu.se>
+
+       * libc/posix/wordfree.c (wordfree): The wrong words are freed
+       when WRDE_DOOFFS is in use. Restructure the code so that the memory
+       needed to be freed is instead kept in an internal linked list...
+       * libc/posix/wordexp2.h: ...as defined here...
+       * libc/posix/wordexp.c (wordexp): ...and build this internal
+       linked list here, avoiding wasteful strdup calls in the process.
+
 2012-10-09  Peter Rosin  <peda@lysator.liu.se>
 
        * libc/posix/wordexp.c (wordexp): Return WRDE_NOSPACE on resource
index b2f63cfad164a2865bc00d931940ac1e8eed2860..5c58e461ade0a022afe267a45ad4661e66277335 100644 (file)
 #include <string.h>
 #include <unistd.h>
 #include <sys/wait.h>
+#include <sys/queue.h>
 
 #include <wordexp.h>
+#include "wordexp2.h"
 
 #define MAXLINELEN 500
 
@@ -41,9 +43,9 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
   int fd[2];
   int fd_err[2];
   int err = WRDE_NOSPACE;
-  char **wordv;
-  char *ewords = NULL;
+  ext_wordv_t *wordv = NULL;
   char *eword;
+  struct ewords_entry *entry;
 
   if (pwordexp == NULL)
     {
@@ -63,10 +65,14 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
     {
       offs = pwordexp->we_offs;
 
-      wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *));
+      if (pwordexp->we_wordv)
+        wordv = WE_WORDV_TO_EXT_WORDV(pwordexp->we_wordv);
+      wordv = (ext_wordv_t *)realloc(wordv, sizeof(ext_wordv_t) + (offs + pwordexp->we_wordc) * sizeof(char *));
       if (!wordv)
         return err;
-      pwordexp->we_wordv = wordv;
+      if (!pwordexp->we_wordv)
+        SLIST_INIT(&wordv->list);
+      pwordexp->we_wordv = wordv->we_wordv;
 
       for (i = 0; i < offs; i++)
         pwordexp->we_wordv[i] = NULL;
@@ -142,11 +148,14 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
 
       num_words = atoi(tmp);
 
-      wordv = (char **)realloc(pwordexp->we_wordv,
-                               (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
+      if (pwordexp->we_wordv)
+        wordv = WE_WORDV_TO_EXT_WORDV(pwordexp->we_wordv);
+      wordv = (ext_wordv_t *)realloc(wordv, sizeof(ext_wordv_t) + (offs + pwordexp->we_wordc + num_words) * sizeof(char *));
       if (!wordv)
-        goto cleanup;
-      pwordexp->we_wordv = wordv;
+        return err;
+      if (!pwordexp->we_wordv)
+        SLIST_INIT(&wordv->list);
+      pwordexp->we_wordv = wordv->we_wordv;
 
       /* Get number of bytes required for storage of all num_words words. */
       if (!fgets(tmp, MAXLINELEN, f))
@@ -157,36 +166,32 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
 
       num_bytes = atoi(tmp);
 
-      /* Get expansion from the shell output. */
-      if (!(ewords = (char *)malloc(num_bytes + num_words + 1)))
+      if (!(entry = (struct ewords_entry *)malloc(sizeof(struct ewords_entry) + num_bytes + num_words)))
         goto cleanup;
-      if (!fread(ewords, 1, num_bytes + num_words, f))
+      SLIST_INSERT_HEAD(&wordv->list, entry, next);
+
+      /* Get expansion from the shell output. */
+      if (!fread(entry->ewords, 1, num_bytes + num_words, f))
         goto cleanup;
-      ewords[num_bytes + num_words] = 0;
+      entry->ewords[num_bytes + num_words] = 0;
 
       /* Store each entry in pwordexp's we_wordv vector. */
-      eword = ewords;
-      for(i = 0; i < num_words; i++)
+      eword = entry->ewords;
+      for(i = 0; i < num_words; i++, eword = iter)
         {
-          if (eword && (iter = strchr(eword, '\n')))
-            *iter = '\0';
-
-          if (!eword ||
-              !(pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = strdup(eword)))
-            {
-              pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
-              pwordexp->we_wordc += i;
-              goto cleanup;
-            }
-          eword = iter ? iter + 1 : iter;
+          if (!eword)
+            break;
+          pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = eword;
+          if ((iter = strchr(eword, '\n')))
+            *iter++ = '\0';
         }
 
-      pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
+      pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = NULL;
       pwordexp->we_wordc += num_words;
-      err = WRDE_SUCCESS;
+      if (i == num_words)
+        err = WRDE_SUCCESS;
 
 cleanup:
-      free(ewords);
       if (f)
         fclose(f);
       else
diff --git a/newlib/libc/posix/wordexp2.h b/newlib/libc/posix/wordexp2.h
new file mode 100644 (file)
index 0000000..2030832
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 2012 by  Peter Rosin. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+#ifndef _WORDEXP2_H_
+
+struct ewords_entry {
+  SLIST_ENTRY(ewords_entry) next;
+  char ewords[1];
+};
+
+typedef struct {
+  SLIST_HEAD(ewords_head, ewords_entry) list;
+  char *we_wordv[1];
+} ext_wordv_t;
+
+#define WE_WORDV_TO_EXT_WORDV(wordv) \
+  (ext_wordv_t *)((void *)(wordv) - offsetof(ext_wordv_t, we_wordv))
+
+#endif /* !_WORDEXP2_H_ */
index 2d1208c3e9e6c640c171e13364c46e6ee51a60df..024a619d99130659579420180ae945df9f13751f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/queue.h>
 
 #include <wordexp.h>
+#include "wordexp2.h"
 
 void
 wordfree(wordexp_t *pwordexp)
 {
-  int i;
+  ext_wordv_t *wordv;
 
   if (pwordexp == NULL)
     return;
@@ -32,10 +34,14 @@ wordfree(wordexp_t *pwordexp)
   if (pwordexp->we_wordv == NULL)
     return;
 
-  for(i = 0; i < pwordexp->we_wordc; i++)
-    free(pwordexp->we_wordv[i]);
+  wordv = WE_WORDV_TO_EXT_WORDV(pwordexp->we_wordv);
+  while (!SLIST_EMPTY(&wordv->list)) {
+    struct ewords_entry *entry = SLIST_FIRST(&wordv->list);
+    SLIST_REMOVE_HEAD(&wordv->list, next);
+    free(entry);
+  }
 
-  free(pwordexp->we_wordv);
+  free(wordv);
   pwordexp->we_wordv = NULL;
 }