diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-07 23:36:45 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-07 23:37:07 -0800 |
commit | 6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4 (patch) | |
tree | 0ed8138e49f63f79593d5f5e81a64ef48e01c6ba /lib/timespec-add.c | |
parent | b9acb9502fd7c4d3cd32b1fd46e644acba4bd878 (diff) | |
download | emacs-6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4.tar.gz |
Merge from gnulib
This incorporates:
2015-11-05 timespec-sub: fix overflow bug; add tests
2015-11-04 intprops: revise _WRAPV macros, revert _OVERFLOW
2015-11-03 intprops: add parentheses
* lib/intprops.h, lib/timespec-add.c, lib/timespec-sub.c:
Copy from gnulib.
Diffstat (limited to 'lib/timespec-add.c')
-rw-r--r-- | lib/timespec-add.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/timespec-add.c b/lib/timespec-add.c index 255489eeb13..e8f6aac29d0 100644 --- a/lib/timespec-add.c +++ b/lib/timespec-add.c @@ -33,36 +33,39 @@ timespec_add (struct timespec a, struct timespec b) int ns = a.tv_nsec + b.tv_nsec; int nsd = ns - TIMESPEC_RESOLUTION; int rns = ns; + time_t tmin = TYPE_MINIMUM (time_t); + time_t tmax = TYPE_MAXIMUM (time_t); if (0 <= nsd) { rns = nsd; - if (rs == TYPE_MAXIMUM (time_t)) - { - if (0 <= bs) - goto high_overflow; - bs++; - } - else + if (bs < tmax) + bs++; + else if (rs < 0) rs++; + else + goto high_overflow; } - if (INT_ADD_OVERFLOW (rs, bs)) + /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned. + In theory time_t might be narrower than int, so plain + INT_ADD_OVERFLOW does not suffice. */ + if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax) + rs += bs; + else { if (rs < 0) { - rs = TYPE_MINIMUM (time_t); + rs = tmin; rns = 0; } else { high_overflow: - rs = TYPE_MAXIMUM (time_t); + rs = tmax; rns = TIMESPEC_RESOLUTION - 1; } } - else - rs += bs; return make_timespec (rs, rns); } |