summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-09-18 04:10:26 +0200
committerLennart Poettering <lennart@poettering.net>2009-09-18 04:14:38 +0200
commit05f6236a83414573587c73dbc439e68dae5f529e (patch)
tree3859bd06816c3b5ec714a4f8fb36e38b43e496a8
parentfdec460661faa802c1acf9d985990c2d1b4fa1a3 (diff)
timeval: make pa_timeval_sub saturating
-rw-r--r--src/pulse/timeval.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 376cf13c..1a0d3cef 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -33,6 +33,7 @@
#include <pulsecore/winsock.h>
#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
#include "timeval.h"
@@ -54,9 +55,9 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
#define EPOCHFILETIME (116444736000000000LL)
#endif
- FILETIME ft;
- LARGE_INTEGER li;
- __int64 t;
+ FILETIME ft;
+ LARGE_INTEGER li;
+ int64_t t;
pa_assert(tv);
@@ -128,40 +129,65 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) {
}
struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec += (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+ if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
+ goto overflow;
+
+ tv->tv_sec += secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
tv->tv_usec += (suseconds_t) v;
/* Normalize */
- while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) {
+ while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
+
+ if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
+ goto overflow;
+
tv->tv_sec++;
tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
}
return tv;
+
+overflow:
+ tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+ tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+ return tv;
}
struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec -= (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+
+ if (PA_UNLIKELY(tv->tv_sec < secs))
+ goto underflow;
+
+ tv->tv_sec -= secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
if (tv->tv_usec >= (suseconds_t) v)
tv->tv_usec -= (suseconds_t) v;
else {
+
+ if (PA_UNLIKELY(tv->tv_sec <= 0))
+ goto underflow;
+
tv->tv_sec --;
tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
}
return tv;
+
+underflow:
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ return tv;
}
struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {