Fix day-increment overflow check in deadline_face settings

date_time.unit.day is a 5-bit bitfield (max 31). Incrementing 31
directly in the bitfield wrapped to 0 via truncation before the
day > days_in_month bounds check ever ran, so the overflow was
never caught. The result decoded as "day 0" of the current month,
i.e. the last day of the previous month, silently rolling the
displayed date backwards (e.g. Aug 31 -> Jul 31 -> Jun 30).

Compute the incremented day in a plain uint8_t local first, compare
it against the month length, and only then write the final value
into the bitfield.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSucp94GA31sshe5AjvSzQ
This commit is contained in:
Konrad Rieck
2026-07-27 20:40:21 +02:00
co-authored by Claude Sonnet 5
parent 8913758a24
commit 0b7ea662fe
+7 -6
View File
@@ -237,17 +237,18 @@ static void _increment_date(deadline_state_t *state, watch_date_time_t date_time
case 1: case 1:
date_time.unit.month = (date_time.unit.month % 12) + 1; date_time.unit.month = (date_time.unit.month % 12) + 1;
break; break;
case 2: case 2: {
date_time.unit.day = date_time.unit.day + 1;
/* Check for leap years */ /* Check for leap years */
int8_t days = days_in_month[date_time.unit.month - 1]; uint8_t days = days_in_month[date_time.unit.month - 1];
if (date_time.unit.month == 2 && _is_leap(date_time.unit.year)) if (date_time.unit.month == 2 && _is_leap(date_time.unit.year))
days++; days++;
if (date_time.unit.day > days) /* Compute next day outside the 5-bit bitfield so overflow past 31
date_time.unit.day = 1; * can be compared against `days` before it gets truncated. */
uint8_t day = date_time.unit.day + 1;
date_time.unit.day = (day > days) ? 1 : day;
break; break;
}
case 3: case 3:
date_time.unit.hour = (date_time.unit.hour + 1) % 24; date_time.unit.hour = (date_time.unit.hour + 1) % 24;
break; break;