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:
Damien George 2022-10-14 15:49:52 +11:00
parent 89b3207376
commit 815920c87f
3 changed files with 91 additions and 0 deletions

View File

@ -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
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_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));
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);

42
tests/extmod/ticks_add.py Normal file
View File

@ -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")

View File

@ -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