Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-05-22 13:45:17 +0400
committerCorinna Vinschen <corinna@vinschen.de>2014-05-22 13:45:17 +0400
commited2cfab440e844bdc5e14831ae2350df8c68d8a3 (patch)
treef01e0333b616049e8908ed7637b2e1541b10b7b3 /winsup/cygwin/libc
parent59ce289027e9d4c60d753daed22689c1bb01957c (diff)
* libc/bsdlib.cc (forkpty): Close master and slave if fork fails to
avoid resource leak (CID 59997). * libc/fts.c: Update to FreeBSD version 1.39 (CID 59947). * libc/minires.c (minires_get_search): Fix out-of-bounds read from words array (CID 59937).
Diffstat (limited to 'winsup/cygwin/libc')
-rw-r--r--winsup/cygwin/libc/bsdlib.cc2
-rw-r--r--winsup/cygwin/libc/fts.c182
-rw-r--r--winsup/cygwin/libc/minires.c2
3 files changed, 76 insertions, 110 deletions
diff --git a/winsup/cygwin/libc/bsdlib.cc b/winsup/cygwin/libc/bsdlib.cc
index 66cffc7d3..696a9f856 100644
--- a/winsup/cygwin/libc/bsdlib.cc
+++ b/winsup/cygwin/libc/bsdlib.cc
@@ -150,6 +150,8 @@ forkpty (int *amaster, char *name, const struct termios *termp,
switch (pid = fork ())
{
case -1:
+ close (master);
+ close (slave);
return -1;
case 0:
close (master);
diff --git a/winsup/cygwin/libc/fts.c b/winsup/cygwin/libc/fts.c
index e82ec3fd7..003f85146 100644
--- a/winsup/cygwin/libc/fts.c
+++ b/winsup/cygwin/libc/fts.c
@@ -34,14 +34,9 @@
static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#endif /* LIBC_SCCS and not lint */
#endif
-#ifdef __CYGWIN__
-#include "winsup.h"
-#include <sys/statfs.h>
-#define _open open
-#define _close close
-#endif
+
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/fts.c,v 1.27 2004/06/08 06:23:23 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fts.c,v 1.39 2013/02/11 02:00:16 svnexp Exp $");
#ifndef __CYGWIN__
#include "namespace.h"
@@ -57,19 +52,37 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/fts.c,v 1.27 2004/06/08 06:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifndef __CYGWIN__
+#ifdef __CYGWIN__
+#include "winsup.h"
+#include <sys/statfs.h>
+#define _open open
+#define _close close
+#define _dirfd dirfd
+#ifdef __x86_64__
+#define _fstat fstat
+#else
+extern int stat64 (const char *path, struct stat *buf);
+extern int fstat64 (int fd, struct stat *buf);
+extern int lstat64 (const char *path, struct stat *buf);
+#define stat(a,b) stat64((a),(b))
+#define _fstat(a,b) fstat64((a),(b))
+#define lstat(a,b) lstat64((a),(b))
+#endif
+#else
#include "un-namespace.h"
+
+#include "gen-private.h"
#endif
-static FTSENT *fts_alloc(FTS *, const char *, int);
+static FTSENT *fts_alloc(FTS *, const char *, size_t);
static FTSENT *fts_build(FTS *, int);
static void fts_lfree(FTSENT *);
static void fts_load(FTS *, FTSENT *);
static size_t fts_maxarglen(char * const *);
static void fts_padjust(FTS *, FTSENT *);
static int fts_palloc(FTS *, size_t);
-static FTSENT *fts_sort(FTS *, FTSENT *, int);
-static u_short fts_stat(FTS *, FTSENT *, int);
+static FTSENT *fts_sort(FTS *, FTSENT *, size_t);
+static int fts_stat(FTS *, FTSENT *, int);
static int fts_safe_changedir(FTS *, FTSENT *, int, const char *);
static int fts_ufslinks(FTS *, const FTSENT *);
@@ -110,6 +123,7 @@ struct _fts_private {
#ifndef __CYGWIN__
static const char *ufslike_filesystems[] = {
"ufs",
+ "zfs",
"nfs",
"nfs4",
"ext2fs",
@@ -126,9 +140,8 @@ fts_open(argv, options, compar)
struct _fts_private *priv;
FTS *sp;
FTSENT *p, *root;
- int nitems;
FTSENT *parent, *tmp;
- int len;
+ size_t len, nitems;
/* Options check. */
if (options & ~FTS_OPTIONMASK) {
@@ -136,10 +149,15 @@ fts_open(argv, options, compar)
return (NULL);
}
+ /* fts_open() requires at least one path */
+ if (*argv == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
/* Allocate/initialize the stream. */
- if ((priv = malloc(sizeof(*priv))) == NULL)
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
return (NULL);
- memset(priv, 0, sizeof(*priv));
sp = &priv->ftsp_fts;
sp->fts_compar = compar;
sp->fts_options = options;
@@ -218,7 +236,8 @@ fts_open(argv, options, compar)
* and ".." are all fairly nasty problems. Note, if we can't get the
* descriptor we run anyway, just more slowly.
*/
- if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+ if (!ISSET(FTS_NOCHDIR) &&
+ (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
SET(FTS_NOCHDIR);
return (sp);
@@ -231,11 +250,9 @@ mem1: free(sp);
}
static void
-fts_load(sp, p)
- FTS *sp;
- FTSENT *p;
+fts_load(FTS *sp, FTSENT *p)
{
- int len;
+ size_t len;
char *cp;
/*
@@ -257,8 +274,7 @@ fts_load(sp, p)
}
int
-fts_close(sp)
- FTS *sp;
+fts_close(FTS *sp)
{
FTSENT *freep, *p;
int saved_errno;
@@ -312,8 +328,7 @@ fts_close(sp)
? p->fts_pathlen - 1 : p->fts_pathlen)
FTSENT *
-fts_read(sp)
- FTS *sp;
+fts_read(FTS *sp)
{
FTSENT *p, *tmp;
int instr;
@@ -347,7 +362,8 @@ fts_read(sp)
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
- if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+ if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
+ 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -438,7 +454,7 @@ next: tmp = p;
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
if ((p->fts_symfd =
- _open(".", O_RDONLY, 0)) < 0) {
+ _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -506,10 +522,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
*/
/* ARGSUSED */
int
-fts_set(sp, p, instr)
- FTS *sp __attribute__ ((unused));
- FTSENT *p;
- int instr;
+fts_set(FTS *sp, FTSENT *p, int instr)
{
if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
instr != FTS_NOINSTR && instr != FTS_SKIP) {
@@ -521,9 +534,7 @@ fts_set(sp, p, instr)
}
FTSENT *
-fts_children(sp, instr)
- FTS *sp;
- int instr;
+fts_children(FTS *sp, int instr)
{
FTSENT *p;
int fd;
@@ -579,11 +590,13 @@ fts_children(sp, instr)
ISSET(FTS_NOCHDIR))
return (sp->fts_child = fts_build(sp, instr));
- if ((fd = _open(".", O_RDONLY, 0)) < 0)
+ if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
- if (fchdir(fd))
+ if (fchdir(fd)) {
+ (void)_close(fd);
return (NULL);
+ }
(void)_close(fd);
return (sp->fts_child);
}
@@ -631,20 +644,18 @@ fts_set_clientptr(FTS *sp, void *clientptr)
* been found, cutting the stat calls by about 2/3.
*/
static FTSENT *
-fts_build(sp, type)
- FTS *sp;
- int type;
+fts_build(FTS *sp, int type)
{
struct dirent *dp;
FTSENT *p, *head;
- int nitems;
FTSENT *cur, *tail;
DIR *dirp;
void *oldaddr;
- size_t dnamlen;
- int cderrno, descend, len, level, maxlen, nlinks, /*oflag,*/ saved_errno,
- nostat, doadjust;
char *cp;
+ int cderrno, descend, /* oflag, */ saved_errno, nostat, doadjust;
+ long level;
+ long nlinks; /* has to be signed because -1 is a magic value */
+ size_t dnamlen, len, maxlen, nitems;
/* Set current node pointer. */
cur = sp->fts_cur;
@@ -711,7 +722,7 @@ fts_build(sp, type)
*/
cderrno = 0;
if (nlinks || type == BREAD) {
- if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+ if (fts_safe_changedir(sp, cur, _dirfd(dirp), NULL)) {
if (nlinks && type == BREAD)
cur->fts_errno = errno;
cur->fts_flags |= FTS_DONTCHDIR;
@@ -756,9 +767,9 @@ fts_build(sp, type)
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
continue;
- if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL)
+ if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
goto mem1;
- if ((int) dnamlen >= maxlen) { /* include space for NUL */
+ if (dnamlen >= maxlen) { /* include space for NUL */
oldaddr = sp->fts_path;
if (fts_palloc(sp, dnamlen + len + 1)) {
/*
@@ -785,21 +796,6 @@ mem1: saved_errno = errno;
maxlen = sp->fts_pathlen - len;
}
- if (len + dnamlen >= USHRT_MAX) {
- /*
- * In an FTSENT, fts_pathlen is a u_short so it is
- * possible to wraparound here. If we do, free up
- * the current structure and the structures already
- * allocated, then error out with ENAMETOOLONG.
- */
- free(p);
- fts_lfree(head);
- (void)closedir(dirp);
- cur->fts_info = FTS_ERR;
- SET(FTS_STOP);
- errno = ENAMETOOLONG;
- return (NULL);
- }
p->fts_level = level;
p->fts_parent = sp->fts_cur;
p->fts_pathlen = len + dnamlen;
@@ -817,7 +813,7 @@ mem1: saved_errno = errno;
p->fts_info = FTS_NSOK;
p->fts_accpath = cur->fts_accpath;
} else if (nlinks == 0
-#if defined(DT_DIR)
+#ifdef DT_DIR
|| (nostat &&
dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
#endif
@@ -865,11 +861,8 @@ mem1: saved_errno = errno;
* If not changing directories, reset the path back to original
* state.
*/
- if (ISSET(FTS_NOCHDIR)) {
- if (len == sp->fts_pathlen || nitems == 0)
- --cp;
- *cp = '\0';
- }
+ if (ISSET(FTS_NOCHDIR))
+ sp->fts_path[cur->fts_pathlen] = '\0';
/*
* If descended after called from fts_children or after called from
@@ -900,11 +893,8 @@ mem1: saved_errno = errno;
return (head);
}
-static u_short
-fts_stat(sp, p, follow)
- FTS *sp;
- FTSENT *p;
- int follow;
+static int
+fts_stat(FTS *sp, FTSENT *p, int follow)
{
FTSENT *t;
dev_t dev;
@@ -932,16 +922,16 @@ fts_stat(sp, p, follow)
* fail, set the errno from the stat call.
*/
if (ISSET(FTS_LOGICAL) || follow) {
- if (stat64(p->fts_accpath, sbp)) {
+ if (stat(p->fts_accpath, sbp)) {
saved_errno = errno;
- if (!lstat64(p->fts_accpath, sbp)) {
+ if (!lstat(p->fts_accpath, sbp)) {
errno = 0;
return (FTS_SLNONE);
}
p->fts_errno = saved_errno;
goto err;
}
- } else if (lstat64(p->fts_accpath, sbp)) {
+ } else if (lstat(p->fts_accpath, sbp)) {
p->fts_errno = errno;
err: memset(sbp, 0, sizeof(struct stat));
return (FTS_NS);
@@ -999,10 +989,7 @@ fts_compar(const void *a, const void *b)
}
static FTSENT *
-fts_sort(sp, head, nitems)
- FTS *sp;
- FTSENT *head;
- int nitems;
+fts_sort(FTS *sp, FTSENT *head, size_t nitems)
{
FTSENT **ap, *p;
@@ -1031,10 +1018,7 @@ fts_sort(sp, head, nitems)
}
static FTSENT *
-fts_alloc(sp, name, namelen)
- FTS *sp;
- const char *name;
- int namelen;
+fts_alloc(FTS *sp, const char *name, size_t namelen)
{
FTSENT *p;
size_t len;
@@ -1081,8 +1065,7 @@ fts_alloc(sp, name, namelen)
}
static void
-fts_lfree(head)
- FTSENT *head;
+fts_lfree(FTSENT *head)
{
FTSENT *p;
@@ -1100,24 +1083,10 @@ fts_lfree(head)
* plus 256 bytes so don't realloc the path 2 bytes at a time.
*/
static int
-fts_palloc(sp, more)
- FTS *sp;
- size_t more;
+fts_palloc(FTS *sp, size_t more)
{
sp->fts_pathlen += more + 256;
- /*
- * Check for possible wraparound. In an FTS, fts_pathlen is
- * a signed int but in an FTSENT it is an unsigned short.
- * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
- */
- if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
- if (sp->fts_path)
- free(sp->fts_path);
- sp->fts_path = NULL;
- errno = ENAMETOOLONG;
- return (1);
- }
sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
return (sp->fts_path == NULL);
}
@@ -1127,9 +1096,7 @@ fts_palloc(sp, more)
* already returned.
*/
static void
-fts_padjust(sp, head)
- FTS *sp;
- FTSENT *head;
+fts_padjust(FTS *sp, FTSENT *head)
{
FTSENT *p;
char *addr = sp->fts_path;
@@ -1170,11 +1137,7 @@ fts_maxarglen(argv)
* Assumes p->fts_dev and p->fts_ino are filled in.
*/
static int
-fts_safe_changedir(sp, p, fd, path)
- FTS *sp;
- FTSENT *p;
- int fd;
- const char *path;
+fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path)
{
int ret, oerrno, newfd;
struct stat sb;
@@ -1182,9 +1145,10 @@ fts_safe_changedir(sp, p, fd, path)
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
- if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+ if (fd < 0 && (newfd = _open(path, O_RDONLY | O_DIRECTORY |
+ O_CLOEXEC, 0)) < 0)
return (-1);
- if (fstat64(newfd, &sb)) {
+ if (_fstat(newfd, &sb)) {
ret = -1;
goto bail;
}
diff --git a/winsup/cygwin/libc/minires.c b/winsup/cygwin/libc/minires.c
index c73ad3c58..b25c927c9 100644
--- a/winsup/cygwin/libc/minires.c
+++ b/winsup/cygwin/libc/minires.c
@@ -77,7 +77,7 @@ void minires_get_search(char * string, res_state statp)
ptr += sizes[j];
DPRINTF(debug, "search \"%s\"\n", words[j]);
}
- else
+ else if (j < MAXDNSRCH + 1)
DPRINTF(debug, "no space for \"%s\"\n", words[j]);
}
}