diff options
| author | Paul Eggert | 2015-11-07 23:36:45 -0800 |
|---|---|---|
| committer | Paul Eggert | 2015-11-07 23:37:07 -0800 |
| commit | 6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4 (patch) | |
| tree | 0ed8138e49f63f79593d5f5e81a64ef48e01c6ba /lib | |
| parent | b9acb9502fd7c4d3cd32b1fd46e644acba4bd878 (diff) | |
| download | emacs-6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4.tar.gz emacs-6ea4ff5a362a150fb9e22eff1d8f2b87d017b7a4.zip | |
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')
| -rw-r--r-- | lib/intprops.h | 218 | ||||
| -rw-r--r-- | lib/timespec-add.c | 27 | ||||
| -rw-r--r-- | lib/timespec-sub.c | 27 |
3 files changed, 135 insertions, 137 deletions
diff --git a/lib/intprops.h b/lib/intprops.h index 4441f1c294e..c55c4db1034 100644 --- a/lib/intprops.h +++ b/lib/intprops.h | |||
| @@ -267,25 +267,22 @@ | |||
| 267 | 267 | ||
| 268 | The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators | 268 | The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators |
| 269 | might not yield numerically correct answers due to arithmetic overflow. | 269 | might not yield numerically correct answers due to arithmetic overflow. |
| 270 | The INT_<op>_WRAPV macros return the low-order bits of the answer. | 270 | The INT_<op>_WRAPV macros also store the low-order bits of the answer. |
| 271 | For example, INT_ADD_WRAPV (INT_MAX, 1) returns INT_MIN on a two's | ||
| 272 | complement host, even if INT_MAX + 1 would trap. | ||
| 273 | |||
| 274 | These macros work correctly on all known practical hosts, and do not rely | 271 | These macros work correctly on all known practical hosts, and do not rely |
| 275 | on undefined behavior due to signed arithmetic overflow. | 272 | on undefined behavior due to signed arithmetic overflow. |
| 276 | 273 | ||
| 277 | Example usage: | 274 | Example usage, assuming A and B are long int: |
| 278 | 275 | ||
| 279 | long int a = ...; | ||
| 280 | long int b = ...; | ||
| 281 | long int result = INT_MULTIPLY_WRAPV (a, b); | 276 | long int result = INT_MULTIPLY_WRAPV (a, b); |
| 282 | printf ("result is %ld (%s)\n", result, | 277 | printf ("result is %ld (%s)\n", result, |
| 283 | INT_MULTIPLY_OVERFLOW (a, b) ? "after overflow" : "no overflow"); | 278 | INT_MULTIPLY_OVERFLOW (a, b) ? "after overflow" : "no overflow"); |
| 284 | 279 | ||
| 285 | enum { | 280 | Example usage with WRAPV flavor: |
| 286 | INT_PRODUCTS_FIT_IN_LONG | 281 | |
| 287 | = ! INT_CONST_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN) | 282 | long int result; |
| 288 | }; | 283 | bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); |
| 284 | printf ("result is %ld (%s)\n", result, | ||
| 285 | overflow ? "after overflow" : "no overflow"); | ||
| 289 | 286 | ||
| 290 | Restrictions on these macros: | 287 | Restrictions on these macros: |
| 291 | 288 | ||
| @@ -296,35 +293,21 @@ | |||
| 296 | These macros may evaluate their arguments zero or multiple times, so the | 293 | These macros may evaluate their arguments zero or multiple times, so the |
| 297 | arguments should not have side effects. | 294 | arguments should not have side effects. |
| 298 | 295 | ||
| 299 | On non-GCC-compatible compilers that do not support C11, the type | 296 | The WRAPV macros are not constant expressions. They support only |
| 300 | of INT_<op>_WRAPV (A, B) might differ from the native type of (A op | 297 | +, binary -, and *. The result type must be signed. |
| 301 | B), so it is wise to convert the result to the native type. Such a | ||
| 302 | conversion is safe and cannot trap. | ||
| 303 | |||
| 304 | For runtime efficiency GCC 5 and later has builtin functions for +, | ||
| 305 | -, * when doing integer overflow checking or wraparound arithmetic. | ||
| 306 | Unfortunately, these builtins require nonnull pointer arguments and | ||
| 307 | so cannot be used in constant expressions; see GCC bug 68120 | ||
| 308 | <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68120>. In constant | ||
| 309 | expressions, use the macros INT_CONST_ADD_OVERFLOW and | ||
| 310 | INT_CONST_ADD_WRAPV instead, and similarly for SUBTRACT and | ||
| 311 | MULTIPLY; these macros avoid the builtins and are slower in | ||
| 312 | non-constant expressions. Perhaps someday GCC's API for overflow | ||
| 313 | checking will be improved and we can remove the need for the | ||
| 314 | INT_CONST_ variants. | ||
| 315 | 298 | ||
| 316 | These macros are tuned for their last argument being a constant. | 299 | These macros are tuned for their last argument being a constant. |
| 317 | 300 | ||
| 318 | Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, | 301 | Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, |
| 319 | A % B, and A << B would overflow, respectively. */ | 302 | A % B, and A << B would overflow, respectively. */ |
| 320 | 303 | ||
| 321 | #define INT_CONST_ADD_OVERFLOW(a, b) \ | 304 | #define INT_ADD_OVERFLOW(a, b) \ |
| 322 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) | 305 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) |
| 323 | #define INT_CONST_SUBTRACT_OVERFLOW(a, b) \ | 306 | #define INT_SUBTRACT_OVERFLOW(a, b) \ |
| 324 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) | 307 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) |
| 325 | #define INT_NEGATE_OVERFLOW(a) \ | 308 | #define INT_NEGATE_OVERFLOW(a) \ |
| 326 | INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) | 309 | INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) |
| 327 | #define INT_CONST_MULTIPLY_OVERFLOW(a, b) \ | 310 | #define INT_MULTIPLY_OVERFLOW(a, b) \ |
| 328 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) | 311 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) |
| 329 | #define INT_DIVIDE_OVERFLOW(a, b) \ | 312 | #define INT_DIVIDE_OVERFLOW(a, b) \ |
| 330 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) | 313 | _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) |
| @@ -343,95 +326,104 @@ | |||
| 343 | _GL_INT_MINIMUM (0 * (b) + (a)), \ | 326 | _GL_INT_MINIMUM (0 * (b) + (a)), \ |
| 344 | _GL_INT_MAXIMUM (0 * (b) + (a))) | 327 | _GL_INT_MAXIMUM (0 * (b) + (a))) |
| 345 | 328 | ||
| 346 | /* Return the low order bits of the integer expressions | 329 | /* Compute A + B, A - B, A * B, respectively, storing the result into *R. |
| 347 | A * B, A - B, -A, A * B, A / B, A % B, and A << B, respectively. | 330 | Return 1 if the result overflows. See above for restrictions. */ |
| 348 | See above for restrictions. */ | 331 | #define INT_ADD_WRAPV(a, b, r) \ |
| 349 | #define INT_CONST_ADD_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, +) | 332 | _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW) |
| 350 | #define INT_CONST_SUBTRACT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, -) | 333 | #define INT_SUBTRACT_WRAPV(a, b, r) \ |
| 351 | #define INT_NEGATE_WRAPV(a) INT_CONST_SUBTRACT_WRAPV (0, a) | 334 | _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW) |
| 352 | #define INT_CONST_MULTIPLY_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, *) | 335 | #define INT_MULTIPLY_WRAPV(a, b, r) \ |
| 353 | #define INT_DIVIDE_WRAPV(a, b) \ | 336 | _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW) |
| 354 | (INT_DIVIDE_OVERFLOW(a, b) ? INT_NEGATE_WRAPV (a) : (a) / (b)) | 337 | |
| 355 | #define INT_REMAINDER_WRAPV(a, b) \ | 338 | #ifndef __has_builtin |
| 356 | (INT_REMAINDER_OVERFLOW(a, b) ? 0 : (a) % (b)) | 339 | # define __has_builtin(x) 0 |
| 357 | #define INT_LEFT_SHIFT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, <<) | 340 | #endif |
| 358 | 341 | ||
| 359 | /* Return the low order bits of A <op> B, where OP specifies the operation. | 342 | /* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: |
| 360 | See above for restrictions. */ | 343 | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 |
| 361 | #if !_GL_HAVE___TYPEOF__ && 201112 <= __STDC_VERSION__ | 344 | https://llvm.org/bugs/show_bug.cgi?id=25390 |
| 362 | # define _GL_INT_OP_WRAPV(a, b, op) \ | 345 | For now, assume all versions of GCC-like compilers generate bogus |
| 363 | _Generic ((a) op (b), \ | 346 | warnings for _Generic. This matters only for older compilers that |
| 364 | int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int), \ | 347 | lack __builtin_add_overflow. */ |
| 365 | long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int), \ | 348 | #if __GNUC__ |
| 366 | long long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, \ | 349 | # define _GL__GENERIC_BOGUS 1 |
| 367 | long long int), \ | ||
| 368 | default: (a) op (b)) | ||
| 369 | #else | 350 | #else |
| 370 | # define _GL_INT_OP_WRAPV(a, b, op) \ | 351 | # define _GL__GENERIC_BOGUS 0 |
| 371 | (! _GL_INT_SIGNED ((0 * (a)) op (0 * (b))) \ | 352 | #endif |
| 372 | ? ((a) op (b)) \ | ||
| 373 | : _GL_EXPR_CAST ((a) op (b), \ | ||
| 374 | (sizeof ((a) op (b)) <= sizeof (int) \ | ||
| 375 | ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int) \ | ||
| 376 | : _GL_INT_OP_WRAPV_LONGISH (a, b, op)))) | ||
| 377 | |||
| 378 | /* Cast to E's type the value of V if possible. Yield V as-is otherwise. */ | ||
| 379 | # if _GL_HAVE___TYPEOF__ | ||
| 380 | # define _GL_EXPR_CAST(e, v) ((__typeof__ (e)) (v)) | ||
| 381 | # else | ||
| 382 | # define _GL_EXPR_CAST(e, v) (v) | ||
| 383 | # endif | ||
| 384 | 353 | ||
| 354 | /* Store A <op> B into *R, where OP specifies the operation. | ||
| 355 | BUILTIN is the builtin operation, and OVERFLOW the overflow predicate. | ||
| 356 | See above for restrictions. */ | ||
| 357 | #if 5 <= __GNUC__ || __has_builtin (__builtin_add_oveflow) | ||
| 358 | # define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r) | ||
| 359 | #elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS | ||
| 360 | # define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ | ||
| 361 | (_Generic \ | ||
| 362 | (*(r), \ | ||
| 363 | signed char: \ | ||
| 364 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \ | ||
| 365 | signed char, SCHAR_MIN, SCHAR_MAX), \ | ||
| 366 | short int: \ | ||
| 367 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \ | ||
| 368 | short int, SHRT_MIN, SHRT_MAX), \ | ||
| 369 | int: \ | ||
| 370 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ | ||
| 371 | int, INT_MIN, INT_MAX), \ | ||
| 372 | long int: \ | ||
| 373 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ | ||
| 374 | long int, LONG_MIN, LONG_MAX), \ | ||
| 375 | long long int: \ | ||
| 376 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ | ||
| 377 | long long int, LLONG_MIN, LLONG_MAX))) | ||
| 378 | #else | ||
| 379 | # define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ | ||
| 380 | (sizeof *(r) == sizeof (signed char) \ | ||
| 381 | ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \ | ||
| 382 | signed char, SCHAR_MIN, SCHAR_MAX) \ | ||
| 383 | : sizeof *(r) == sizeof (short int) \ | ||
| 384 | ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \ | ||
| 385 | short int, SHRT_MIN, SHRT_MAX) \ | ||
| 386 | : sizeof *(r) == sizeof (int) \ | ||
| 387 | ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ | ||
| 388 | int, INT_MIN, INT_MAX) \ | ||
| 389 | : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) | ||
| 385 | # ifdef LLONG_MAX | 390 | # ifdef LLONG_MAX |
| 386 | # define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \ | 391 | # define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ |
| 387 | (sizeof ((a) op (b)) <= sizeof (long int) \ | 392 | (sizeof *(r) == sizeof (long int) \ |
| 388 | ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int) \ | 393 | ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ |
| 389 | : _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long long int)) | 394 | long int, LONG_MIN, LONG_MAX) \ |
| 395 | : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ | ||
| 396 | long long int, LLONG_MIN, LLONG_MAX)) | ||
| 390 | # else | 397 | # else |
| 391 | # define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \ | 398 | # define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ |
| 392 | _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int) | 399 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ |
| 400 | long int, LONG_MIN, LONG_MAX)) | ||
| 393 | # endif | 401 | # endif |
| 394 | #endif | 402 | #endif |
| 395 | 403 | ||
| 396 | /* Return A <op> B, where the operation is given by OP and the result | 404 | /* Store the low-order bits of A <op> B into *R, where the operation |
| 397 | type is T. T is a signed integer type that is at least as wide as int. | 405 | is given by OP. Use the unsigned type UT for calculation to avoid |
| 398 | Do arithmetic using 'unsigned T' to avoid signed integer overflow. | 406 | overflow problems. *R's type is T, with extremal values TMIN and |
| 399 | Subtract TYPE_MINIMUM (T) before converting back to T, and add it | 407 | TMAX. T must be a signed integer type. */ |
| 400 | back afterwards, to avoid signed overflow during conversion. */ | 408 | #define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ |
| 401 | #define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, t) \ | 409 | (sizeof ((a) op (b)) < sizeof (t) \ |
| 402 | ((unsigned t) (a) op (unsigned t) (b) <= TYPE_MAXIMUM (t) \ | 410 | ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ |
| 403 | ? (t) ((unsigned t) (a) op (unsigned t) (b)) \ | 411 | : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax)) |
| 404 | : ((t) ((unsigned t) (a) op (unsigned t) (b) - TYPE_MINIMUM (t)) \ | 412 | #define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \ |
| 405 | + TYPE_MINIMUM (t))) | 413 | ((overflow (a, b) \ |
| 406 | 414 | || (_GL_INT_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \ | |
| 407 | /* Calls to the INT_<op>_<result> macros are like their INT_CONST_<op>_<result> | 415 | || (tmax) < ((a) op (b))) \ |
| 408 | counterparts, except they are faster with GCC 5 or later, and they | 416 | ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 1) \ |
| 409 | are not constant expressions due to limitations in the GNU C API. */ | 417 | : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 0)) |
| 410 | 418 | ||
| 411 | #define INT_ADD_OVERFLOW(a, b) \ | 419 | /* Return A <op> B, where the operation is given by OP. Use the |
| 412 | _GL_OP_OVERFLOW (a, b, INT_CONST_ADD_OVERFLOW, __builtin_add_overflow) | 420 | unsigned type UT for calculation to avoid overflow problems. |
| 413 | #define INT_SUBTRACT_OVERFLOW(a, b) \ | 421 | Convert the result to type T without overflow by subtracting TMIN |
| 414 | _GL_OP_OVERFLOW (a, b, INT_CONST_SUBTRACT_OVERFLOW, __builtin_sub_overflow) | 422 | from large values before converting, and adding it afterwards. |
| 415 | #define INT_MULTIPLY_OVERFLOW(a, b) \ | 423 | Compilers can optimize all the operations except OP. */ |
| 416 | _GL_OP_OVERFLOW (a, b, INT_CONST_MULTIPLY_OVERFLOW, __builtin_mul_overflow) | 424 | #define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t, tmin, tmax) \ |
| 417 | 425 | (((ut) (a) op (ut) (b)) <= (tmax) \ | |
| 418 | #define INT_ADD_WRAPV(a, b) \ | 426 | ? (t) ((ut) (a) op (ut) (b)) \ |
| 419 | _GL_OP_WRAPV (a, b, INT_CONST_ADD_WRAPV, __builtin_add_overflow) | 427 | : ((t) (((ut) (a) op (ut) (b)) - (tmin)) + (tmin))) |
| 420 | #define INT_SUBTRACT_WRAPV(a, b) \ | ||
| 421 | _GL_OP_WRAPV (a, b, INT_CONST_SUBTRACT_WRAPV, __builtin_sub_overflow) | ||
| 422 | #define INT_MULTIPLY_WRAPV(a, b) \ | ||
| 423 | _GL_OP_WRAPV (a, b, INT_CONST_MULTIPLY_WRAPV, __builtin_mul_overflow) | ||
| 424 | |||
| 425 | #if __GNUC__ < 5 | ||
| 426 | # define _GL_OP_OVERFLOW(a, b, portable, builtin) portable (a, b) | ||
| 427 | # define _GL_OP_WRAPV(a, b, portable, builtin) portable (a, b) | ||
| 428 | #else | ||
| 429 | # define _GL_OP_OVERFLOW(a, b, portable, builtin) \ | ||
| 430 | builtin (a, b, &(__typeof__ ((a) + (b))) {0}) | ||
| 431 | # define _GL_OP_WRAPV(a, b, portable, builtin) \ | ||
| 432 | _GL_OP_WRAPV_GENSYM(a, b, builtin, __gl_wrapv##__COUNTER__) | ||
| 433 | # define _GL_OP_WRAPV_GENSYM(a, b, builtin, r) \ | ||
| 434 | ({__typeof__ ((a) + (b)) r; builtin (a, b, &r); r; }) | ||
| 435 | #endif | ||
| 436 | 428 | ||
| 437 | #endif /* _GL_INTPROPS_H */ | 429 | #endif /* _GL_INTPROPS_H */ |
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) | |||
| 33 | int ns = a.tv_nsec + b.tv_nsec; | 33 | int ns = a.tv_nsec + b.tv_nsec; |
| 34 | int nsd = ns - TIMESPEC_RESOLUTION; | 34 | int nsd = ns - TIMESPEC_RESOLUTION; |
| 35 | int rns = ns; | 35 | int rns = ns; |
| 36 | time_t tmin = TYPE_MINIMUM (time_t); | ||
| 37 | time_t tmax = TYPE_MAXIMUM (time_t); | ||
| 36 | 38 | ||
| 37 | if (0 <= nsd) | 39 | if (0 <= nsd) |
| 38 | { | 40 | { |
| 39 | rns = nsd; | 41 | rns = nsd; |
| 40 | if (rs == TYPE_MAXIMUM (time_t)) | 42 | if (bs < tmax) |
| 41 | { | 43 | bs++; |
| 42 | if (0 <= bs) | 44 | else if (rs < 0) |
| 43 | goto high_overflow; | ||
| 44 | bs++; | ||
| 45 | } | ||
| 46 | else | ||
| 47 | rs++; | 45 | rs++; |
| 46 | else | ||
| 47 | goto high_overflow; | ||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | if (INT_ADD_OVERFLOW (rs, bs)) | 50 | /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned. |
| 51 | In theory time_t might be narrower than int, so plain | ||
| 52 | INT_ADD_OVERFLOW does not suffice. */ | ||
| 53 | if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax) | ||
| 54 | rs += bs; | ||
| 55 | else | ||
| 51 | { | 56 | { |
| 52 | if (rs < 0) | 57 | if (rs < 0) |
| 53 | { | 58 | { |
| 54 | rs = TYPE_MINIMUM (time_t); | 59 | rs = tmin; |
| 55 | rns = 0; | 60 | rns = 0; |
| 56 | } | 61 | } |
| 57 | else | 62 | else |
| 58 | { | 63 | { |
| 59 | high_overflow: | 64 | high_overflow: |
| 60 | rs = TYPE_MAXIMUM (time_t); | 65 | rs = tmax; |
| 61 | rns = TIMESPEC_RESOLUTION - 1; | 66 | rns = TIMESPEC_RESOLUTION - 1; |
| 62 | } | 67 | } |
| 63 | } | 68 | } |
| 64 | else | ||
| 65 | rs += bs; | ||
| 66 | 69 | ||
| 67 | return make_timespec (rs, rns); | 70 | return make_timespec (rs, rns); |
| 68 | } | 71 | } |
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c index c57437556d1..392ec1592a1 100644 --- a/lib/timespec-sub.c +++ b/lib/timespec-sub.c | |||
| @@ -33,36 +33,39 @@ timespec_sub (struct timespec a, struct timespec b) | |||
| 33 | time_t bs = b.tv_sec; | 33 | time_t bs = b.tv_sec; |
| 34 | int ns = a.tv_nsec - b.tv_nsec; | 34 | int ns = a.tv_nsec - b.tv_nsec; |
| 35 | int rns = ns; | 35 | int rns = ns; |
| 36 | time_t tmin = TYPE_MINIMUM (time_t); | ||
| 37 | time_t tmax = TYPE_MAXIMUM (time_t); | ||
| 36 | 38 | ||
| 37 | if (ns < 0) | 39 | if (ns < 0) |
| 38 | { | 40 | { |
| 39 | rns = ns + TIMESPEC_RESOLUTION; | 41 | rns = ns + TIMESPEC_RESOLUTION; |
| 40 | if (rs == TYPE_MINIMUM (time_t)) | 42 | if (bs < tmax) |
| 41 | { | 43 | bs++; |
| 42 | if (bs <= 0) | 44 | else if (- TYPE_SIGNED (time_t) < rs) |
| 43 | goto low_overflow; | ||
| 44 | bs--; | ||
| 45 | } | ||
| 46 | else | ||
| 47 | rs--; | 45 | rs--; |
| 46 | else | ||
| 47 | goto low_overflow; | ||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | if (INT_SUBTRACT_OVERFLOW (rs, bs)) | 50 | /* INT_SUBTRACT_WRAPV is not appropriate since time_t might be unsigned. |
| 51 | In theory time_t might be narrower than int, so plain | ||
| 52 | INT_SUBTRACT_OVERFLOW does not suffice. */ | ||
| 53 | if (! INT_SUBTRACT_OVERFLOW (rs, bs) && tmin <= rs - bs && rs - bs <= tmax) | ||
| 54 | rs -= bs; | ||
| 55 | else | ||
| 51 | { | 56 | { |
| 52 | if (rs < 0) | 57 | if (rs < 0) |
| 53 | { | 58 | { |
| 54 | low_overflow: | 59 | low_overflow: |
| 55 | rs = TYPE_MINIMUM (time_t); | 60 | rs = tmin; |
| 56 | rns = 0; | 61 | rns = 0; |
| 57 | } | 62 | } |
| 58 | else | 63 | else |
| 59 | { | 64 | { |
| 60 | rs = TYPE_MAXIMUM (time_t); | 65 | rs = tmax; |
| 61 | rns = TIMESPEC_RESOLUTION - 1; | 66 | rns = TIMESPEC_RESOLUTION - 1; |
| 62 | } | 67 | } |
| 63 | } | 68 | } |
| 64 | else | ||
| 65 | rs -= bs; | ||
| 66 | 69 | ||
| 67 | return make_timespec (rs, rns); | 70 | return make_timespec (rs, rns); |
| 68 | } | 71 | } |