summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorrpokala <rpokala@FreeBSD.org>2016-01-09 05:05:15 +0000
committerrpokala <rpokala@FreeBSD.org>2016-01-09 05:05:15 +0000
commitd5fe9e0efae46c54e8bfb0f9b09b0cb13f97bec2 (patch)
tree8dbc85705f814106c6d8c1fa2177ba886d8b525a /lib
parentc2abf823f04419a32871560f6942c35e63ba1e02 (diff)
downloadFreeBSD-src-d5fe9e0efae46c54e8bfb0f9b09b0cb13f97bec2.zip
FreeBSD-src-d5fe9e0efae46c54e8bfb0f9b09b0cb13f97bec2.tar.gz
MFC r291114: popen() requires check for fdopen() failure
Move fdopen() up near other resource allocation like malloc(); do proper deallocation on failure later on in the function. Approved by: jhb Sponsored by: Panasas, Inc.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/popen.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index b0597c8..f834df0 100644
--- a/lib/libc/gen/popen.c
+++ b/lib/libc/gen/popen.c
@@ -73,6 +73,7 @@ popen(command, type)
struct pid *cur;
FILE *iop;
int pdes[2], pid, twoway, cloexec;
+ int pdes_unused_in_parent;
char *argv[4];
struct pid *p;
@@ -99,6 +100,20 @@ popen(command, type)
return (NULL);
}
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ pdes_unused_in_parent = pdes[1];
+ } else {
+ iop = fdopen(pdes[1], type);
+ pdes_unused_in_parent = pdes[0];
+ }
+ if (iop == NULL) {
+ (void)_close(pdes[0]);
+ (void)_close(pdes[1]);
+ free(cur);
+ return (NULL);
+ }
+
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *)command;
@@ -108,9 +123,14 @@ popen(command, type)
switch (pid = vfork()) {
case -1: /* Error. */
THREAD_UNLOCK();
- (void)_close(pdes[0]);
- (void)_close(pdes[1]);
+ /*
+ * The _close() closes the unused end of pdes[], while
+ * the fclose() closes the used end of pdes[], *and* cleans
+ * up iop.
+ */
+ (void)_close(pdes_unused_in_parent);
free(cur);
+ (void)fclose(iop);
return (NULL);
/* NOTREACHED */
case 0: /* Child. */
@@ -155,14 +175,8 @@ popen(command, type)
}
THREAD_UNLOCK();
- /* Parent; assume fdopen can't fail. */
- if (*type == 'r') {
- iop = fdopen(pdes[0], type);
- (void)_close(pdes[1]);
- } else {
- iop = fdopen(pdes[1], type);
- (void)_close(pdes[0]);
- }
+ /* Parent. */
+ (void)_close(pdes_unused_in_parent);
/* Link into list of file descriptors. */
cur->fp = iop;
OpenPOWER on IntegriCloud