summaryrefslogtreecommitdiffstats
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-08-05 11:31:33 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-08-05 11:31:33 +0000
commit8cba692063d085c2a5a3095d71c7bafc45722bf6 (patch)
tree01796bd0b304a710f13610cedafec924e44af0f0 /winsup
parentd607be551d90ec42a5441b5a865a81b7db9f01d8 (diff)
downloadcygnal-8cba692063d085c2a5a3095d71c7bafc45722bf6.tar.gz
cygnal-8cba692063d085c2a5a3095d71c7bafc45722bf6.tar.bz2
cygnal-8cba692063d085c2a5a3095d71c7bafc45722bf6.zip
* thread.cc (pthread_cond_timedwait): Check abstime for validity
according to SUSv3. Rewrite timeout check and waitlength calculation to avoid overflow problems.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/thread.cc20
2 files changed, 22 insertions, 4 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a8eec0fe8..bd28a343e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,9 @@
+2005-08-05 Corinna Vinschen <corinna@vinschen.de>
+
+ * thread.cc (pthread_cond_timedwait): Check abstime for validity
+ according to SUSv3. Rewrite timeout check and waitlength calculation
+ to avoid overflow problems.
+
2005-08-02 Yitzchak Scott-Thoennes <sthoenna@efn.org>
* include/sys/termios.h: Define TIOCMBIS and TIOCMBIC.
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index ea4f64930..03bebb1a3 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -2615,7 +2615,7 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime)
{
struct timeval tv;
- long waitlength;
+ DWORD waitlength;
myfault efault;
if (efault.faulted ())
@@ -2623,11 +2623,23 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
pthread_testcancel ();
+ /* According to SUSv3, the abstime value must be checked for validity. */
+ if (abstime->tv_sec < 0
+ || abstime->tv_nsec < 0
+ || abstime->tv_nsec > 999999999)
+ return EINVAL;
+
gettimeofday (&tv, NULL);
- waitlength = abstime->tv_sec * 1000 + abstime->tv_nsec / (1000 * 1000);
- waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000;
- if (waitlength < 0)
+ /* Check for immediate timeout before converting to microseconds, since
+ the resulting value can easily overflow long. This also allows to
+ evaluate microseconds directly in DWORD. */
+ if (tv.tv_sec > abstime->tv_sec
+ || (tv.tv_sec == abstime->tv_sec
+ && tv.tv_usec > abstime->tv_nsec / 1000))
return ETIMEDOUT;
+
+ waitlength = (abstime->tv_sec - tv.tv_sec) * 1000;
+ waitlength += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
return __pthread_cond_dowait (cond, mutex, waitlength);
}