From c742e92e7f247f7623c150d7613594e981a31094 Mon Sep 17 00:00:00 2001 From: Konrad Rieck Date: Mon, 27 Jul 2026 22:11:52 +0200 Subject: [PATCH 1/2] Fix memory leak in lis2dw_monitor_face settings array state->settings was malloc'd in lis2dw_monitor_face_setup() outside the guard that only runs on first allocation of the face's context. setup() is called again every time the watch wakes from deep sleep (movement.c's app_setup() re-runs watch_faces[i].setup() for every face on wake), so each wake cycle allocated a new settings array and abandoned the previous pointer with no matching free. Since NUM_SETTINGS is a compile-time constant, make settings a fixed-size array embedded directly in lis2dw_monitor_state_t instead of a separately malloc'd pointer, so it's allocated exactly once along with the rest of the state and never leaks. --- watch-faces/sensor/lis2dw_monitor_face.c | 4 ---- watch-faces/sensor/lis2dw_monitor_face.h | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/watch-faces/sensor/lis2dw_monitor_face.c b/watch-faces/sensor/lis2dw_monitor_face.c index 8afb7d3e..3934fa59 100644 --- a/watch-faces/sensor/lis2dw_monitor_face.c +++ b/watch-faces/sensor/lis2dw_monitor_face.c @@ -31,9 +31,6 @@ /* Display frequency */ #define DISPLAY_FREQUENCY 8 -/* Settings */ -#define NUM_SETTINGS 7 - static void _settings_title_display(lis2dw_monitor_state_t *state, char *buf1, char *buf2) { char buf[10]; @@ -541,7 +538,6 @@ void lis2dw_monitor_face_setup(uint8_t watch_face_index, void **context_ptr) /* Initialize settings */ uint8_t settings_page = 0; - state->settings = malloc(NUM_SETTINGS * sizeof(lis2dw_settings_t)); state->settings[settings_page].display = _settings_mode_display; state->settings[settings_page].advance = _settings_mode_advance; settings_page++; diff --git a/watch-faces/sensor/lis2dw_monitor_face.h b/watch-faces/sensor/lis2dw_monitor_face.h index 51a98ecf..7dc0da47 100644 --- a/watch-faces/sensor/lis2dw_monitor_face.h +++ b/watch-faces/sensor/lis2dw_monitor_face.h @@ -56,13 +56,16 @@ typedef struct { void (*advance)(void *); } lis2dw_settings_t; +/* Number of settings pages */ +#define NUM_SETTINGS 7 + typedef struct { uint8_t axis:2; /* Axis to display */ lis2dw_reading_t reading; /* Current reading */ lis2dw_monitor_page_t page; /* Displayed page */ lis2dw_device_state_t ds; /* Device state */ uint8_t settings_page:3; /* Subpage in settings */ - lis2dw_settings_t *settings; /* Settings config */ + lis2dw_settings_t settings[NUM_SETTINGS]; /* Settings config */ uint8_t show_title:6; /* Display face title */ } lis2dw_monitor_state_t; From bf25776a668c7d59a8176642d5c7cce3f5b9f549 Mon Sep 17 00:00:00 2001 From: Konrad Rieck Date: Mon, 27 Jul 2026 22:12:22 +0200 Subject: [PATCH 2/2] Fix wrong format specifier for axis label _monitor_display() used %C (wide character, expects wint_t) instead of %c (plain char/int) to print the X/Y/Z axis label. Every other single-character display in the codebase uses %c; on the embedded build, without wide-char support in the C library, %C is not a valid conversion for the char actually being passed. --- watch-faces/sensor/lis2dw_monitor_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-faces/sensor/lis2dw_monitor_face.c b/watch-faces/sensor/lis2dw_monitor_face.c index 3934fa59..7c7d8327 100644 --- a/watch-faces/sensor/lis2dw_monitor_face.c +++ b/watch-faces/sensor/lis2dw_monitor_face.c @@ -384,7 +384,7 @@ static void _monitor_display(lis2dw_monitor_state_t *state) { char buf[10]; - snprintf(buf, sizeof(buf), " %C ", "XYZ"[state->axis]); + snprintf(buf, sizeof(buf), " %c ", "XYZ"[state->axis]); watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, buf, buf); snprintf(buf, sizeof(buf), "%2d", state->axis + 1);