Skip to content

Commit 194fffa

Browse files
mikellerSubsurface CI
authored andcommitted
field-cache: zero-initialise cache in shearwater and garmin parser create
dc_parser_allocate() uses malloc, leaving embedded struct members uninitialised. dc_field_cache_free() is now called from the destroy path of both parsers before the cache is ever populated; it dereferences strings[].value, which would be garbage pointers. Add memset(&parser->cache, 0, sizeof(parser->cache)) in shearwater_common_parser_create() and garmin_parser_create() immediately after dc_parser_allocate() succeeds, making all destroy and pre-reset free calls safe. Signed-off-by: Subsurface CI <ci@subsurface-divelog.org>
1 parent 6b3b483 commit 194fffa

4 files changed

Lines changed: 45 additions & 3 deletions

File tree

src/field-cache.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <stdio.h>
22
#include <stdarg.h>
3+
#include <stdlib.h>
34
#include <string.h>
45

56
#include "platform.h"
@@ -119,3 +120,16 @@ dc_field_get(dc_field_cache_t *cache, dc_field_type_t type, unsigned int flags,
119120

120121
return DC_STATUS_UNSUPPORTED;
121122
}
123+
124+
/*
125+
* Free all strdup'd string values in the cache. The desc pointers are
126+
* static allocations and must not be freed. Safe to call on a
127+
* zero-initialised cache (free(NULL) is a no-op).
128+
*/
129+
void dc_field_cache_free(dc_field_cache_t *cache)
130+
{
131+
for (int i = 0; i < MAXSTRINGS; i++) {
132+
free((void *) cache->strings[i].value);
133+
cache->strings[i].value = NULL;
134+
}
135+
}

src/field-cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dc_status_t dc_field_add_string(dc_field_cache_t *, const char *desc, const char
3939
dc_status_t dc_field_add_string_fmt(dc_field_cache_t *, const char *desc, const char *fmt, ...);
4040
dc_status_t dc_field_get_string(dc_field_cache_t *, unsigned idx, dc_field_string_t *value);
4141
dc_status_t dc_field_get(dc_field_cache_t *, dc_field_type_t, unsigned int, void *);
42+
void dc_field_cache_free(dc_field_cache_t *);
4243

4344
/*
4445
* Macro to make it easy to set DC_FIELD_xyz values.

src/garmin_parser.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ static dc_status_t garmin_parser_set_data (garmin_parser_t *garmin, const unsign
327327
static dc_status_t garmin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
328328
static dc_status_t garmin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
329329
static dc_status_t garmin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
330+
static dc_status_t garmin_parser_destroy (dc_parser_t *abstract);
330331

331332
static const dc_parser_vtable_t garmin_parser_vtable = {
332333
sizeof(garmin_parser_t),
@@ -337,7 +338,7 @@ static const dc_parser_vtable_t garmin_parser_vtable = {
337338
garmin_parser_get_datetime, /* datetime */
338339
garmin_parser_get_field, /* fields */
339340
garmin_parser_samples_foreach, /* samples_foreach */
340-
NULL /* destroy */
341+
garmin_parser_destroy /* destroy */
341342
};
342343

343344
dc_status_t
@@ -355,6 +356,8 @@ garmin_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned c
355356
return DC_STATUS_NOMEMORY;
356357
}
357358

359+
memset(&parser->cache, 0, sizeof(parser->cache));
360+
358361
garmin_parser_set_data(parser, data, size);
359362

360363
*out = (dc_parser_t *) parser;
@@ -1793,3 +1796,13 @@ garmin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callb
17931796
garmin->userdata = userdata;
17941797
return traverse_data(garmin);
17951798
}
1799+
1800+
static dc_status_t
1801+
garmin_parser_destroy (dc_parser_t *abstract)
1802+
{
1803+
garmin_parser_t *garmin = (garmin_parser_t *) abstract;
1804+
1805+
dc_field_cache_free(&garmin->cache);
1806+
1807+
return DC_STATUS_SUCCESS;
1808+
}

src/shearwater_predator_parser.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ struct dc_parser_sensor_calibration_t {
194194
static dc_status_t shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
195195
static dc_status_t shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
196196
static dc_status_t shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
197+
static dc_status_t shearwater_predator_parser_destroy (dc_parser_t *abstract);
197198

198199
static dc_status_t shearwater_predator_parser_cache (shearwater_predator_parser_t *parser);
199200

@@ -206,7 +207,7 @@ static const dc_parser_vtable_t shearwater_predator_parser_vtable = {
206207
shearwater_predator_parser_get_datetime, /* datetime */
207208
shearwater_predator_parser_get_field, /* fields */
208209
shearwater_predator_parser_samples_foreach, /* samples_foreach */
209-
NULL /* destroy */
210+
shearwater_predator_parser_destroy /* destroy */
210211
};
211212

212213
static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
@@ -218,7 +219,7 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
218219
shearwater_predator_parser_get_datetime, /* datetime */
219220
shearwater_predator_parser_get_field, /* fields */
220221
shearwater_predator_parser_samples_foreach, /* samples_foreach */
221-
NULL /* destroy */
222+
shearwater_predator_parser_destroy /* destroy */
222223
};
223224

224225

@@ -267,6 +268,8 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, const
267268
return DC_STATUS_NOMEMORY;
268269
}
269270

271+
memset(&parser->cache, 0, sizeof(parser->cache));
272+
270273
// Set the default values.
271274
parser->model = model;
272275
parser->petrel = petrel;
@@ -464,6 +467,16 @@ static void add_sensor_state(shearwater_predator_parser_t *parser, bool external
464467
}
465468
}
466469

470+
static dc_status_t
471+
shearwater_predator_parser_destroy (dc_parser_t *abstract)
472+
{
473+
shearwater_predator_parser_t *parser = (shearwater_predator_parser_t *) abstract;
474+
475+
dc_field_cache_free(&parser->cache);
476+
477+
return DC_STATUS_SUCCESS;
478+
}
479+
467480
static dc_status_t
468481
shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
469482
{
@@ -474,6 +487,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
474487
if (parser->cached) {
475488
return DC_STATUS_SUCCESS;
476489
}
490+
dc_field_cache_free(&parser->cache);
477491
memset(&parser->cache, 0, sizeof(parser->cache));
478492

479493
// Log versions before 6 weren't reliably stored in the data, but

0 commit comments

Comments
 (0)