extmod/utime_mphal: Make ticks_add check for overflow of delta.
Work done in collaboration with @jimmo. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
89b3207376
commit
815920c87f
|
@ -95,6 +95,19 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
|
||||||
// we assume that first argument come from ticks_xx so is small int
|
// we assume that first argument come from ticks_xx so is small int
|
||||||
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
|
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
|
||||||
mp_uint_t delta = mp_obj_get_int(delta_in);
|
mp_uint_t delta = mp_obj_get_int(delta_in);
|
||||||
|
|
||||||
|
// Check that delta does not overflow the range that ticks_diff can handle.
|
||||||
|
// This ensures the following:
|
||||||
|
// - ticks_diff(ticks_add(T, delta), T) == delta
|
||||||
|
// - ticks_diff(T, ticks_add(T, delta)) == -delta
|
||||||
|
// The latter requires excluding delta=-TICKS_PERIOD/2.
|
||||||
|
//
|
||||||
|
// This unsigned comparison is equivalent to a signed comparison of:
|
||||||
|
// delta <= TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2
|
||||||
|
if (delta + MICROPY_PY_UTIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_UTIME_TICKS_PERIOD - 1) {
|
||||||
|
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow"));
|
||||||
|
}
|
||||||
|
|
||||||
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
|
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
try:
|
||||||
|
from utime import ticks_diff, ticks_add
|
||||||
|
except ImportError:
|
||||||
|
print("SKIP")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
# Maximum value returned from ticks_add, ticks_ms, etc.
|
||||||
|
TICKS_MAX = ticks_add(0, -1)
|
||||||
|
# Maximum value returned from ticks_diff.
|
||||||
|
TICKS_INTERVAL_MAX = TICKS_MAX // 2
|
||||||
|
|
||||||
|
# Invariants:
|
||||||
|
# - ticks_diff(ticks_add(T, delta), T) == delta
|
||||||
|
# - ticks_diff(T, ticks_add(T, delta)) == -delta
|
||||||
|
|
||||||
|
# Check actual values of ticks_add.
|
||||||
|
print(ticks_add(20, 12))
|
||||||
|
print(ticks_add(20, -12))
|
||||||
|
|
||||||
|
# Check invariant.
|
||||||
|
print(ticks_diff(ticks_add(100, 123), 100))
|
||||||
|
print(ticks_diff(ticks_add(100, -123), 100))
|
||||||
|
print(ticks_diff(100, ticks_add(100, 123)))
|
||||||
|
print(ticks_diff(100, ticks_add(100, -123)))
|
||||||
|
|
||||||
|
# Check limits.
|
||||||
|
for T in (0, 10, TICKS_MAX):
|
||||||
|
for delta in (
|
||||||
|
-TICKS_INTERVAL_MAX - 1,
|
||||||
|
-TICKS_INTERVAL_MAX,
|
||||||
|
0,
|
||||||
|
TICKS_INTERVAL_MAX,
|
||||||
|
TICKS_INTERVAL_MAX + 1,
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
print(ticks_diff(ticks_add(T, delta), T) == delta)
|
||||||
|
except OverflowError:
|
||||||
|
print("OverflowError")
|
||||||
|
try:
|
||||||
|
print(ticks_diff(T, ticks_add(T, delta)) == -delta)
|
||||||
|
except OverflowError:
|
||||||
|
print("OverflowError")
|
|
@ -0,0 +1,36 @@
|
||||||
|
32
|
||||||
|
8
|
||||||
|
123
|
||||||
|
-123
|
||||||
|
-123
|
||||||
|
123
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
True
|
||||||
|
OverflowError
|
||||||
|
OverflowError
|
Loading…
Reference in New Issue