summaryrefslogtreecommitdiffstats
path: root/newlib
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-10-09 09:26:15 +0000
committerCorinna Vinschen <corinna@vinschen.de>2012-10-09 09:26:15 +0000
commit277e7f0e2e6fc9fb533b301fc0627cfe4fd9d1ae (patch)
treea3c8bd42069556628b50a4f0076b97b74ccdc3fa /newlib
parent4a6ec9ec528cc15023aef73d1c53785eda06c3ff (diff)
downloadcygnal-277e7f0e2e6fc9fb533b301fc0627cfe4fd9d1ae.tar.gz
cygnal-277e7f0e2e6fc9fb533b301fc0627cfe4fd9d1ae.tar.bz2
cygnal-277e7f0e2e6fc9fb533b301fc0627cfe4fd9d1ae.zip
* libc/posix/wordexp.c (wordexp): Return WRDE_NOSPACE on resource
allocation failure. Cleanup leftover resources when failing.
Diffstat (limited to 'newlib')
-rw-r--r--newlib/ChangeLog5
-rw-r--r--newlib/libc/posix/wordexp.c94
2 files changed, 72 insertions, 27 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 7991e5ed9..298fc39e1 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,5 +1,10 @@
2012-10-09 Peter Rosin <peda@lysator.liu.se>
+ * libc/posix/wordexp.c (wordexp): Return WRDE_NOSPACE on resource
+ allocation failure. Cleanup leftover resources when failing.
+
+2012-10-09 Peter Rosin <peda@lysator.liu.se>
+
* libc/posix/wordexp.c (wordexp): Handle expanded words longer
than 500 bytes.
diff --git a/newlib/libc/posix/wordexp.c b/newlib/libc/posix/wordexp.c
index 0b4bf7702..b2f63cfad 100644
--- a/newlib/libc/posix/wordexp.c
+++ b/newlib/libc/posix/wordexp.c
@@ -29,8 +29,8 @@
int
wordexp(const char *words, wordexp_t *pwordexp, int flags)
{
- FILE *f;
- FILE *f_err;
+ FILE *f = NULL;
+ FILE *f_err = NULL;
char tmp[MAXLINELEN];
int i = 0;
int offs = 0;
@@ -40,8 +40,9 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
int num_bytes = 0;
int fd[2];
int fd_err[2];
- int err = 0;
- char *ewords;
+ int err = WRDE_NOSPACE;
+ char **wordv;
+ char *ewords = NULL;
char *eword;
if (pwordexp == NULL)
@@ -62,18 +63,35 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
{
offs = pwordexp->we_offs;
- if(!(pwordexp->we_wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *))))
- return WRDE_NOSPACE;
+ wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *));
+ if (!wordv)
+ return err;
+ pwordexp->we_wordv = wordv;
for (i = 0; i < offs; i++)
pwordexp->we_wordv[i] = NULL;
}
- pipe(fd);
- pipe(fd_err);
+ if (pipe(fd))
+ return err;
+ if (pipe(fd_err))
+ {
+ close(fd[0]);
+ close(fd[1]);
+ return err;
+ }
pid = fork();
- if (pid > 0)
+ if (pid == -1)
+ {
+ /* In "parent" process, but fork failed */
+ close(fd_err[0]);
+ close(fd_err[1]);
+ close(fd[0]);
+ close(fd[1]);
+ return err;
+ }
+ else if (pid > 0)
{
/* In parent process. */
@@ -82,7 +100,8 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
close(fd_err[1]);
/* f_err is the standard error from the shell command. */
- f_err = fdopen(fd_err[0], "r");
+ if (!(f_err = fdopen(fd_err[0], "r")))
+ goto cleanup;
/* Check for errors. */
if (fgets(tmp, MAXLINELEN, f_err))
@@ -107,26 +126,31 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
fprintf(stderr, tmp);
}
- return err;
+ goto cleanup;
}
/* f is the standard output from the shell command. */
- f = fdopen(fd[0], "r");
+ if (!(f = fdopen(fd[0], "r")))
+ goto cleanup;
/* Get number of words expanded by shell. */
- fgets(tmp, MAXLINELEN, f);
+ if (!fgets(tmp, MAXLINELEN, f))
+ goto cleanup;
if((iter = strchr(tmp, '\n')))
*iter = '\0';
num_words = atoi(tmp);
- if(!(pwordexp->we_wordv = (char **)realloc(pwordexp->we_wordv,
- (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *))))
- return WRDE_NOSPACE;
+ wordv = (char **)realloc(pwordexp->we_wordv,
+ (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
+ if (!wordv)
+ goto cleanup;
+ pwordexp->we_wordv = wordv;
/* Get number of bytes required for storage of all num_words words. */
- fgets(tmp, MAXLINELEN, f);
+ if (!fgets(tmp, MAXLINELEN, f))
+ goto cleanup;
if((iter = strchr(tmp, '\n')))
*iter = '\0';
@@ -135,8 +159,9 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
/* Get expansion from the shell output. */
if (!(ewords = (char *)malloc(num_bytes + num_words + 1)))
- return WRDE_NOSPACE;
- fread(ewords, 1, num_bytes + num_words, f);
+ goto cleanup;
+ if (!fread(ewords, 1, num_bytes + num_words, f))
+ goto cleanup;
ewords[num_bytes + num_words] = 0;
/* Store each entry in pwordexp's we_wordv vector. */
@@ -146,23 +171,35 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
if (eword && (iter = strchr(eword, '\n')))
*iter = '\0';
- if (eword)
- eword = strdup(eword);
- pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = eword;
+ 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;
}
pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
pwordexp->we_wordc += num_words;
+ err = WRDE_SUCCESS;
+cleanup:
free(ewords);
- fclose(f);
- fclose(f_err);
+ if (f)
+ fclose(f);
+ else
+ close(fd[0]);
+ if (f_err)
+ fclose(f_err);
+ else
+ close(fd_err[0]);
/* Wait for child to finish. */
waitpid (pid, NULL, 0);
- return WRDE_SUCCESS;
+ return err;
}
else
{
@@ -175,7 +212,8 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
/* Pipe standard output to parent process via fd. */
if (fd[1] != STDOUT_FILENO)
{
- dup2(fd[1], STDOUT_FILENO);
+ if (dup2(fd[1], STDOUT_FILENO) == -1)
+ _exit(EXIT_FAILURE);
/* fd[1] no longer required. */
close(fd[1]);
}
@@ -183,7 +221,8 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
/* Pipe standard error to parent process via fd_err. */
if (fd_err[1] != STDERR_FILENO)
{
- dup2(fd_err[1], STDERR_FILENO);
+ if (dup2(fd_err[1], STDERR_FILENO) == -1)
+ _exit(EXIT_FAILURE);
/* fd_err[1] no longer required. */
close(fd_err[1]);
}
@@ -192,6 +231,7 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
execl("/bin/bash", "bash", "--protected", "--wordexp", words, (char *)0);
else
execl("/bin/bash", "bash", "--wordexp", words, (char *)0);
+ _exit(EXIT_FAILURE);
}
return WRDE_SUCCESS;
}