From 86fc2b088592e94011df1b4b48179ae32c8db33f Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Mon, 7 Sep 2026 06:58:37 +1200 Subject: [PATCH] shearwater: fix userdata corruption in predator parser samples loop shearwater_predator_parser_samples_foreach serves two purposes: an internal calibration pre-pass called with callback=NULL and a dc_parser_sensor_calibration_t * as userdata, and normal sample enumeration called with a real callback and the caller's own userdata. The guard that restricted calibration writes to the pre-pass checked only that userdata was non-NULL, so during normal sample enumeration it cast the caller's userdata pointer to dc_parser_sensor_calibration_t * and wrote into it. For any CCR dive with internal (non-external) ppo2, this wrote the value 1 into the first byte of whatever struct the caller passed, e.g. the low byte of divecomputer::when in Subsurface (a small timestamp corruption) or a FILE * member in dctool (a crash). Fix: add !callback to the guard so the internal calibration writes only happen during the pre-pass (callback == NULL). Signed-off-by: Michael Keller --- src/shearwater_predator_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 10b2f13a..774fbd85 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -1224,7 +1224,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal if ((status & PPO2_EXTERNAL) == 0) { double calculated_ppo2 = data[offset + pnf + 6] / 100.0; - if (userdata) { + if (!callback && userdata) { struct dc_parser_sensor_calibration_t *out = (struct dc_parser_sensor_calibration_t *)userdata; out->external_ppo2_used = true;