time: Introduce function to check correctness of nanoseconds value

The valid_nanoseconds () static inline function has been introduced to
check if nanoseconds value is in the correct range - greater or equal to
zero and less than 1000000000.

The explicit #include <time.h> has been added to files where it was
missing.

The __syscall_slong_t type for ns has been used to avoid issues on x32.

Tested with:
- scripts/build-many-glibcs.py
- make PARALLELMFLAGS="-j12" && make PARALLELMFLAGS="-j12" xcheck on x86_64
This commit is contained in:
Lukasz Majewski 2019-10-24 16:20:56 +02:00
parent 513aaa0d78
commit 4812365660
24 changed files with 49 additions and 36 deletions

View file

@ -71,7 +71,7 @@ __lll_abstimed_lock (void *ptr,
{
if (atomic_exchange_acq ((int *)ptr, 2) == 0)
return 0;
else if (tsp->tv_nsec < 0 || tsp->tv_nsec >= 1000000000)
else if (! valid_nanoseconds (tsp->tv_nsec))
return EINVAL;
int mlsec = compute_reltime (tsp, clk);

View file

@ -27,6 +27,7 @@
#include <assert.h>
#include <stdint.h>
#include <limits.h>
#include <time.h>
/* All user select types. */
#define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
@ -89,8 +90,7 @@ _hurd_select (int nfds,
{
struct timeval now;
if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
timeout->tv_nsec >= 1000000000)
if (timeout->tv_sec < 0 || ! valid_nanoseconds (timeout->tv_nsec))
{
errno = EINVAL;
return -1;

View file

@ -236,5 +236,13 @@ valid_timespec64_to_timeval (const struct __timespec64 ts64)
return tv;
}
/* Check if a value is in the valid nanoseconds range. Return true if
it is, false otherwise. */
static inline bool
valid_nanoseconds (__syscall_slong_t ns)
{
return __glibc_likely (0 <= ns && ns < 1000000000);
}
#endif
#endif

View file

@ -22,6 +22,7 @@
#include <stddef.h> /* For NULL. */
#include <sys/poll.h>
#include <sysdep-cancel.h>
#include <time.h>
int
@ -33,8 +34,7 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
/* poll uses a simple millisecond value. Convert it. */
if (timeout != NULL)
{
if (timeout->tv_sec < 0
|| timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)
if (timeout->tv_sec < 0 || ! valid_nanoseconds (timeout->tv_nsec))
{
__set_errno (EINVAL);
return -1;

View file

@ -21,6 +21,7 @@
#include <errno.h>
#include <lowlevellock.h>
#include <sys/time.h>
#include <time.h>
int
@ -28,7 +29,7 @@ __lll_clocklock_wait (int *futex, clockid_t clockid,
const struct timespec *abstime, int private)
{
/* Reject invalid timeouts. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Try locking. */

View file

@ -645,7 +645,7 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
{
/* Check parameter validity. This should also tell the compiler that
it can assume that abstime is not NULL. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Relaxed MO is suffice because clock ID bit is only modified
@ -668,7 +668,7 @@ __pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
{
/* Check parameter validity. This should also tell the compiler that
it can assume that abstime is not NULL. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
if (!futex_abstimed_supported_clockid (clockid))

View file

@ -19,6 +19,7 @@
#include "pthreadP.h"
#include <atomic.h>
#include <stap-probe.h>
#include <time.h>
static void
cleanup (void *arg)
@ -40,7 +41,7 @@ timedwait_tid (pid_t *tidp, const struct timespec *abstime)
{
pid_t tid;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Repeat until thread terminated. */

View file

@ -235,7 +235,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
}
/* We are about to block; check whether the timeout is invalid. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Work around the fact that the kernel rejects negative timeout
values despite them being valid. */
@ -561,7 +561,7 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
if (oldval != ceilval)
{
/* Reject invalid timeouts. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
{
result = EINVAL;
goto failpp;

View file

@ -24,6 +24,7 @@
#include <stap-probe.h>
#include <atomic.h>
#include <futex-internal.h>
#include <time.h>
/* A reader--writer lock that fulfills the POSIX requirements (but operations
@ -290,8 +291,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
if the lock can be immediately acquired" (i.e., we need not but may check
it). */
if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
|| abstime->tv_nsec >= 1000000000
|| abstime->tv_nsec < 0))
|| ! valid_nanoseconds (abstime->tv_nsec)))
return EINVAL;
/* Make sure we are not holding the rwlock as a writer. This is a deadlock
@ -596,8 +596,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
if the lock can be immediately acquired" (i.e., we need not but may check
it). */
if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
|| abstime->tv_nsec >= 1000000000
|| abstime->tv_nsec < 0))
|| ! valid_nanoseconds (abstime->tv_nsec)))
return EINVAL;
/* Make sure we are not holding the rwlock as a writer. This is a deadlock

View file

@ -18,6 +18,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <time.h>
#include "sem_waitcommon.c"
int
@ -32,7 +33,7 @@ sem_clockwait (sem_t *sem, clockid_t clockid,
return -1;
}
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
{
__set_errno (EINVAL);
return -1;

View file

@ -17,6 +17,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <time.h>
#include "sem_waitcommon.c"
/* This is in a separate file because because sem_timedwait is only provided
@ -24,7 +25,7 @@
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
{
__set_errno (EINVAL);
return -1;

View file

@ -20,6 +20,7 @@
#include <pt-internal.h>
#include <pthreadP.h>
#include <time.h>
extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond,
pthread_mutex_t *mutex,
@ -74,7 +75,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond,
int cancelled, oldtype, drain;
clockid_t clock_id = __pthread_default_condattr.__clock;
if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
if (abstime && ! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
struct __pthread *self = _pthread_self ();

View file

@ -18,6 +18,7 @@
#include <pthread.h>
#include <assert.h>
#include <time.h>
#include <pt-internal.h>
@ -119,7 +120,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex,
#endif
assert (mutex->__owner);
if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Add ourselves to the queue. */

View file

@ -18,6 +18,7 @@
#include <pthread.h>
#include <assert.h>
#include <time.h>
#include <pt-internal.h>
@ -60,7 +61,7 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
/* Better be blocked by a writer. */
assert (rwlock->__readers == 0);
if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
self = _pthread_self ();

View file

@ -18,6 +18,7 @@
#include <pthread.h>
#include <assert.h>
#include <time.h>
#include <pt-internal.h>
@ -46,7 +47,7 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
/* The lock is busy. */
if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
self = _pthread_self ();

View file

@ -19,6 +19,7 @@
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <time.h>
#include <pt-internal.h>
@ -39,7 +40,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
return 0;
}
if (timeout != NULL && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000))
if (timeout != NULL && ! valid_nanoseconds (timeout->tv_nsec))
{
errno = EINVAL;
return -1;

View file

@ -19,6 +19,7 @@
#include <pthread.h>
#include <assert.h>
#include <hurd/signal.h>
#include <time.h>
#include <pt-internal.h>
@ -69,7 +70,7 @@ __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
assert (ss->intr_port == MACH_PORT_NULL); /* Sanity check for signal bugs. */
if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
/* Atomically enqueue our thread on the condition variable's queue of

View file

@ -30,8 +30,7 @@ __libc_nanosleep (const struct timespec *requested_time,
struct timeval before, after;
if (requested_time->tv_sec < 0
|| requested_time->tv_nsec < 0
|| requested_time->tv_nsec >= 1000000000)
|| ! valid_nanoseconds (requested_time->tv_nsec))
{
errno = EINVAL;
return -1;

View file

@ -41,10 +41,8 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
goto bail;
}
if (value->it_interval.tv_nsec < 0
|| value->it_interval.tv_nsec >= 1000000000
|| value->it_value.tv_nsec < 0
|| value->it_value.tv_nsec >= 1000000000)
if (! valid_nanoseconds (value->it_interval.tv_nsec)
|| ! valid_nanoseconds (value->it_value.tv_nsec))
{
__set_errno (EINVAL);
goto bail;

View file

@ -21,6 +21,7 @@
#include <sysdep.h>
#include <lowlevellock.h>
#include <sys/time.h>
#include <time.h>
void
@ -56,7 +57,7 @@ __lll_clocklock_wait (int *futex, clockid_t clockid,
const struct timespec *abstime, int private)
{
/* Reject invalid timeouts. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
if (! valid_nanoseconds (abstime->tv_nsec))
return EINVAL;
do

View file

@ -30,8 +30,7 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
{
struct timespec now;
if (__builtin_expect (req->tv_nsec, 0) < 0
|| __builtin_expect (req->tv_nsec, 0) >= 1000000000)
if (! valid_nanoseconds (req->tv_nsec))
return EINVAL;
if (clock_id == CLOCK_THREAD_CPUTIME_ID)

View file

@ -27,7 +27,7 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
int retval = -1;
/* Make sure the time cvalue is OK. */
if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
if (! valid_nanoseconds (tp->tv_nsec))
{
__set_errno (EINVAL);
return -1;

View file

@ -26,7 +26,7 @@ int
__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
{
/* Make sure the time cvalue is OK. */
if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
if (! valid_nanoseconds (tp->tv_nsec))
{
__set_errno (EINVAL);
return -1;

View file

@ -24,8 +24,7 @@ int
__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
struct timespec *rem)
{
if (__builtin_expect (req->tv_nsec, 0) < 0
|| __builtin_expect (req->tv_nsec, 0) >= 1000000000)
if (! valid_nanoseconds (req->tv_nsec))
return EINVAL;
if (flags != TIMER_ABSTIME && flags != 0)