about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--catgets/Makefile4
-rw-r--r--elf/dl-close.c30
-rw-r--r--posix/wordexp-test.c16
-rw-r--r--posix/wordexp.c62
5 files changed, 95 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c0236f192..31b91d2a4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+1998-03-15  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* posix/wordexp-test.c: Add more tests.
+	(testit): Fix logic.
+
+	* posix/wordexp.c (exec_comm): In the child, redirect stderr to
+	/dev/null instead of closing it, close pipe.  Always chop off all
+	trailing newlines.  Kill and reap child before returning error.
+	(w_addword, parse_glob): Fix memory leak.
+	(wordexp): Fix dangling pointer problem.
+
+1998-03-16  Ulrich Drepper  <drepper@cygnus.com>
+
+	* elf/dl-close.c (_dl_close): Correct and simplify unmapping.
+
+	* posix/wordexp-test.c (main): Fix little thinkos and typos.
+
+	* catgets/Makefile (CPPFLAGS): Change NLSPATH to also examine
+	directory index by only the language.
+
 1998-03-16 13:02  Tim Waugh  <tim@cyberelk.demon.co.uk>
 
 	* posix/wordexp-tst.sh: Store test results in the
diff --git a/catgets/Makefile b/catgets/Makefile
index 0631599f18..ee464c1adc 100644
--- a/catgets/Makefile
+++ b/catgets/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -38,5 +38,5 @@ include ../Rules
 
 $(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o)
 
-CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:"' \
+CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:$(localedir)/%l/%N:$(localedir)/%l/LC_MESSAGES/%N:"' \
 	    -DHAVE_CONFIG_H $(CPPFLAGS)
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 253b073367..f2155031e6 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -80,7 +80,8 @@ _dl_close (struct link_map *map)
 	  /* That was the last reference, and this was a dlopen-loaded
 	     object.  We can unmap it.  */
 	  const ElfW(Phdr) *ph;
-	  const ElfW(Phdr) *eph;
+	  const ElfW(Phdr) *first, *last;
+	  ElfW(Addr) mapstart, mapend;
 
 	  if (imap->l_info[DT_FINI])
 	    /* Call its termination function.  */
@@ -100,24 +101,23 @@ _dl_close (struct link_map *map)
 	      _dl_global_scope_end[1] = NULL;
 	    }
 
-	  /* Find the first entry specifying a load command.  We have
-	     to determine this now since the table itself is also loaded.  */
-	  for (eph = imap->l_phdr; eph < imap->l_phdr + imap->l_phnum; ++eph)
-	    if (eph->p_type == PT_LOAD)
-	      break;
-
-	  /* Unmap the segments.  */
-	  for (ph = imap->l_phdr + (imap->l_phnum - 1); ph >= eph; --ph)
+	  /* We can unmap all the maps at once.  We just have to determine
+	     the length and the `munmap' call does the rest.  */
+	  first = last = NULL;
+	  for (ph = imap->l_phdr; ph < imap->l_phdr + imap->l_phnum; ++ph)
 	    if (ph->p_type == PT_LOAD)
 	      {
-		ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1);
-		ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz
-				      + ph->p_align - 1)
-				     & ~(ph->p_align - 1));
-		__munmap ((caddr_t) (imap->l_addr + mapstart),
-			  mapend - mapstart);
+		if (first == NULL)
+		  first = ph;
+		last = ph;
 	      }
 
+	  /* Now we have all the information we need for the unmapping.
+	     See the method used in `_dl_map_object_from_fd'.  */
+	  mapstart = first->p_vaddr & ~(first->p_align - 1);
+	  mapend = last->p_vaddr + last->p_memsz;
+	  __munmap ((caddr_t) (imap->l_addr + mapstart), mapend - mapstart);
+
 	  /* Finally, unlink the data structure and free it.  */
 	  if (imap->l_prev)
 	    imap->l_prev->l_next = imap->l_next;
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
index b8a83c5211..2fc5f0ffac 100644
--- a/posix/wordexp-test.c
+++ b/posix/wordexp-test.c
@@ -47,6 +47,9 @@ struct test_case_struct
     /* Simple parameter expansion */
     { 0, "foo", "${var}", 0, 1, { "foo", } },
     { 0, "foo", "$var", 0, 1, { "foo", } },
+    { 0, "foo", "\\\"$var\\\"", 0, 1, { "\"foo\"", } },
+    { 0, "foo", "%$var%", 0, 1, { "%foo%", } },
+    { 0, "foo", "-$var-", 0, 1, { "-foo-", } },
 
     /* Simple quote removal */
     { 0, NULL, "\"quoted\"", 0, 1, { "quoted", } },
@@ -58,12 +61,15 @@ struct test_case_struct
     { 0, NULL, "$( (echo hello) )", 0, 1, { "hello", } },
     { 0, NULL, "$((echo hello);(echo there))", 0, 2, { "hello", "there", } },
     { 0, NULL, "`echo one two`", 0, 2, { "one", "two", } },
+    { 0, NULL, "$(echo ')')", 0, 1, { ")" } },
+    { 0, NULL, "$(echo hello; echo)", 0, 1, { "hello", } },
 
     /* Simple arithmetic expansion */
     { 0, NULL, "$((1 + 1))", 0, 1, { "2", } },
     { 0, NULL, "$((2-3))", 0, 1, { "-1", } },
     { 0, NULL, "$((-1))", 0, 1, { "-1", } },
     { 0, NULL, "$[50+20]", 0, 1, { "70", } },
+    { 0, NULL, "$(((2+3)*(4+5)))", 0, 1, { "45", } },
 
     /* Advanced parameter expansion */
     { 0, NULL, "${var:-bar}", 0, 1, { "bar", } },
@@ -83,11 +89,14 @@ struct test_case_struct
     { 0, "foo", "${var:+bar}", 0, 1, { "bar", } },
     { 0, "", "${var+bar}", 0, 1, { "bar", } },
     { 0, "12345", "${#var}", 0, 1, { "5", } },
+    { 0, NULL, "${var:-'}'}", 0, 1, { "}", } },
+    { 0, NULL, "${var-}", 0, 0, { NULL } },
 
     { 0, "banana", "${var%na*}", 0, 1, { "bana", } },
     { 0, "banana", "${var%%na*}", 0, 1, { "ba", } },
     { 0, "borabora-island", "${var#*bora}", 0, 1, { "bora-island", } },
     { 0, "borabora-island", "${var##*bora}", 0, 1, {"-island", } },
+    { 0, "100%", "${var%0%}", 0, 1, { "10" } },
 
     /* Pathname expansion */
     { 0, NULL, "???", 0, 2, { "one", "two", } },
@@ -155,6 +164,7 @@ main (int argc, char *argv[])
   const char *globfile[] = { "one", "two", "three", NULL };
   char tmpdir[32];
   struct passwd *pw;
+  char *cwd;
   int test;
   int fail = 0;
   int i;
@@ -206,8 +216,8 @@ main (int argc, char *argv[])
   for (i = 0; globfile[i]; ++i)
     remove (globfile[i]);
 
-  if (cwd = NULL)
-    strcpy (cwd, "..");
+  if (cwd == NULL)
+    cwd = "..";
 
   chdir (cwd);
   rmdir (tmpdir);
@@ -233,7 +243,7 @@ testit (struct test_case_struct *tc)
   printf ("Test %d: ", ++test);
   retval = wordexp (tc->words, &we, tc->flags);
 
-  if (retval != tc->retval || (retval != 0 && we.we_wordc != tc->wordc))
+  if (retval != tc->retval || (retval == 0 && we.we_wordc != tc->wordc))
     bzzzt = 1;
   else
     for (i = 0; i < we.we_wordc; ++i)
diff --git a/posix/wordexp.c b/posix/wordexp.c
index 5e0e985006..443dc4697d 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -63,6 +63,11 @@ static int parse_backtick (char **word, size_t *word_length,
 			   size_t *offset, int flags, wordexp_t *pwordexp,
 			   const char *ifs, const char *ifs_white)
      internal_function;
+static int parse_dquote (char **word, size_t *word_length, size_t *max_length,
+			 const char *words, size_t *offset, int flags,
+			 wordexp_t *pwordexp, const char *ifs,
+			 const char *ifs_white)
+     internal_function;
 static int eval_expr (char *expr, long int *result) internal_function;
 
 /* The w_*() functions manipulate word lists. */
@@ -145,11 +150,13 @@ w_addword (wordexp_t *pwordexp, char *word)
 {
   /* Add a word to the wordlist */
   size_t num_p;
+  char **new_wordv;
 
   num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
-  pwordexp->we_wordv = realloc (pwordexp->we_wordv, sizeof (char *) * num_p);
-  if (pwordexp->we_wordv != NULL)
+  new_wordv = realloc (pwordexp->we_wordv, sizeof (char *) * num_p);
+  if (new_wordv != NULL)
     {
+      pwordexp->we_wordv = new_wordv;
       pwordexp->we_wordv[pwordexp->we_wordc++] = word;
       pwordexp->we_wordv[pwordexp->we_wordc] = NULL;
       return 0;
@@ -418,9 +425,13 @@ parse_glob (char **word, size_t *word_length, size_t *max_length,
     {
       /* No field splitting allowed */
       size_t length = strlen (globbuf.gl_pathv[0]);
+      char *old_word = *word;
       *word = realloc (*word, length + 1);
       if (*word == NULL)
-	goto no_space;
+	{
+	  free (old_word);
+	  goto no_space;
+	}
 
       memcpy (*word, globbuf.gl_pathv[0], length + 1);
       *word_length = length;
@@ -792,13 +803,24 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
       /* Child */
       const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
 
-      /* Redirect input and output */
+      /* Redirect output.  */
       dup2 (fildes[1], 1);
+      close (fildes[1]);
 
-      /* Close stderr if we have to */
+      /* Redirect stderr to /dev/null if we have to.  */
       if ((flags & WRDE_SHOWERR) == 0)
-	close (2);
+	{
+	  int fd;
+	  close (2);
+	  fd = open (_PATH_DEVNULL, O_WRONLY);
+	  if (fd >= 0 && fd != 2)
+	    {
+	      dup2 (fd, 2);
+	      close (fd);
+	    }
+	}
 
+      close (fildes[0]);
       __execve (_PATH_BSHELL, (char *const *) args, __environ);
 
       /* Bad.  What now?  */
@@ -826,18 +848,12 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 	  *word = w_addmem (*word, word_length, max_length, buffer, buflen);
 	  if (*word == NULL)
 	    {
+	      kill (pid, SIGKILL);
+	      __waitpid (pid, NULL, 0);
 	      close (fildes[0]);
 	      return WRDE_NOSPACE;
 	    }
 	}
-
-      close (fildes[0]);
-
-      /* bash chops off a terminating linefeed, which seems sensible */
-      if ((*word)[*word_length - 1] == '\n')
-	(*word)[--*word_length] = '\0';
-
-      return 0;
     }
   else
     /* Not quoted - split fields */
@@ -903,6 +919,8 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 		      *word = w_addchar (*word, word_length, max_length, 0);
 		      if (*word == NULL)
 			{
+			  kill (pid, SIGKILL);
+			  __waitpid (pid, NULL, 0);
 			  close (fildes[0]);
 			  return WRDE_NOSPACE;
 			}
@@ -910,7 +928,8 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 
 		  if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
 		    {
-		      /* Should do __waitpid? */
+		      kill (pid, SIGKILL);
+		      __waitpid (pid, NULL, 0);
 		      close (fildes[0]);
 		      return WRDE_NOSPACE;
 		    }
@@ -928,6 +947,8 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 				     buffer[i]);
 		  if (*word == NULL)
 		    {
+		      kill (pid, SIGKILL);
+		      __waitpid (pid, NULL, 0);
 		      close (fildes[0]);
 		      return WRDE_NOSPACE;
 		    }
@@ -936,6 +957,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 	}
     }
 
+  /* Bash chops off trailing newlines, which seems sensible.  */
+  while (*word_length > 0 && (*word)[*word_length - 1] == '\n')
+    (*word)[--*word_length] = '\0';
+
   close (fildes[0]);
   return 0;
 }
@@ -1991,8 +2016,11 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
   size_t old_wordc = (flags & WRDE_REUSE) ? pwordexp->we_wordc : 0;
 
   if (flags & WRDE_REUSE)
-    /* Minimal implementation of WRDE_REUSE for now */
-    wordfree (pwordexp);
+    {
+      /* Minimal implementation of WRDE_REUSE for now */
+      wordfree (pwordexp);
+      old_wordv = NULL;
+    }
 
   if (flags & WRDE_DOOFFS)
     {