From 3a4ce7315fb87d51ef8dd46b9064ee766d5dda62 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 23 Nov 2013 13:51:53 +0000 Subject: [PATCH] dup2: fix off-by-one crash * dtable.cc (dup3): Fix off-by-one. (find_unused_handle): Reduce time spent expanding during dup. * syscalls.cc (setdtablesize): Report error on invalid value. --- winsup/cygwin/ChangeLog | 7 +++++++ winsup/cygwin/dtable.cc | 4 ++-- winsup/cygwin/syscalls.cc | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index cd3f75d88..8293a0f35 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2013-11-23 Eric Blake + + dup2: fix off-by-one crash + * dtable.cc (dup3): Fix off-by-one. + (find_unused_handle): Reduce time spent expanding during dup. + * syscalls.cc (setdtablesize): Report error on invalid value. + 2013-11-20 Corinna Vinschen * include/cygwin/stdlib.h (realpath): Drop declaration. It's declared diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 2501a26fd..c2982a8a7 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -233,7 +233,7 @@ dtable::find_unused_handle (int start) if (fds[i] == NULL) return i; } - while (extend (NOFILE_INCR)); + while (extend (MAX (NOFILE_INCR, start - size))); return -1; } @@ -754,7 +754,7 @@ dtable::dup3 (int oldfd, int newfd, int flags) if (!not_open (newfd)) close (newfd); - else if ((size_t) newfd > size + else if ((size_t) newfd >= size && find_unused_handle (newfd) < 0) /* couldn't extend fdtab */ { diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index e1886e617..e686e33fc 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -2578,6 +2578,12 @@ system (const char *cmdstring) extern "C" int setdtablesize (int size) { + if (size < 0) + { + set_errno (EINVAL); + return -1; + } + if (size <= (int)cygheap->fdtab.size || cygheap->fdtab.extend (size - cygheap->fdtab.size)) return 0;