Fix flex device memory leak by replacing dynamic allocation with static (closes #3350)

This commit is contained in:
Dan Dwyer
2026-07-01 15:20:47 -07:00
committed by Christian W. Zuckschwerdt
parent 4318f9503f
commit dd28f8ac8d

View File

@@ -65,9 +65,12 @@ static unsigned long extract_number(uint8_t *data, unsigned bit_offset, unsigned
return val; return val;
} }
#define FLEX_GET_STR_LEN 32
#define FLEX_DEV_NAME_LEN 64
struct flex_map { struct flex_map {
unsigned key; unsigned key;
const char *val; char val[FLEX_GET_STR_LEN];
}; };
#define GETTER_MAP_SLOTS 16 #define GETTER_MAP_SLOTS 16
@@ -76,15 +79,16 @@ struct flex_get {
unsigned bit_offset; unsigned bit_offset;
unsigned bit_count; unsigned bit_count;
unsigned long mask; unsigned long mask;
const char *name; char name[FLEX_GET_STR_LEN];
struct flex_map map[GETTER_MAP_SLOTS]; struct flex_map map[GETTER_MAP_SLOTS];
const char *format; char format[FLEX_GET_STR_LEN];
}; };
#define GETTER_SLOTS 12 #define GETTER_SLOTS 12
struct flex_params { struct flex_params {
char *name; char name[FLEX_GET_STR_LEN];
char dev_name[FLEX_DEV_NAME_LEN];
unsigned min_rows; unsigned min_rows;
unsigned max_rows; unsigned max_rows;
unsigned min_bits; unsigned min_bits;
@@ -131,13 +135,13 @@ static void render_getters(data_t *data, uint8_t *bits, struct flex_params *para
else else
val = extract_number(bits, getter->bit_offset, getter->bit_count); val = extract_number(bits, getter->bit_offset, getter->bit_count);
int m; int m;
for (m = 0; getter->map[m].val; m++) { for (m = 0; getter->map[m].val[0]; m++) {
if (getter->map[m].key == val) { if (getter->map[m].key == val) {
data_str(data, getter->name, "", NULL, getter->map[m].val); data_str(data, getter->name, "", NULL, getter->map[m].val);
break; break;
} }
} }
if (!getter->map[m].val) { if (!getter->map[m].val[0]) {
data_int(data, getter->name, "", getter->format, val); data_int(data, getter->name, "", getter->format, val);
} }
} }
@@ -572,7 +576,6 @@ static const char *parse_map(const char *arg, struct flex_get *getter)
while (*c) { while (*c) {
unsigned long key; unsigned long key;
char *val;
while (*c == ' ') c++; while (*c == ' ') c++;
if (*c == ']') return c + 1; if (*c == ']') return c + 1;
@@ -587,18 +590,15 @@ static const char *parse_map(const char *arg, struct flex_get *getter)
// then parse a string // then parse a string
const char *e = c; const char *e = c;
while (*e && *e != ' ' && *e != ']') e++; while (*e && *e != ' ' && *e != ']') e++;
val = malloc(e - c + 1); size_t map_len = (size_t)(e - c);
if (!val) strncpy(getter->map[i].val, c, FLEX_GET_STR_LEN - 1);
WARN_MALLOC("parse_map()"); getter->map[i].val[FLEX_GET_STR_LEN - 1] = '\0';
else { // NOTE: skipped on alloc failure. if (map_len >= FLEX_GET_STR_LEN)
memcpy(val, c, e - c); fprintf(stderr, "Warning: flex map value truncated at %d chars.\n", FLEX_GET_STR_LEN - 1);
val[e - c] = '\0';
}
c = e; c = e;
// store result // store result
getter->map[i].key = key; getter->map[i].key = key;
getter->map[i].val = val;
i++; i++;
} }
return c; return c;
@@ -622,18 +622,20 @@ static void parse_getter(const char *arg, struct flex_get *getter)
getter->mask = extract_number(bitrow, 0, getter->bit_count); getter->mask = extract_number(bitrow, 0, getter->bit_count);
} }
else if (*arg == '%') { else if (*arg == '%') {
getter->format = strdup(arg); strncpy(getter->format, arg, FLEX_GET_STR_LEN - 1);
if (!getter->format) getter->format[FLEX_GET_STR_LEN - 1] = '\0';
FATAL_STRDUP("parse_getter()"); if (strlen(arg) >= FLEX_GET_STR_LEN)
fprintf(stderr, "Warning: flex format truncated at %d chars.\n", FLEX_GET_STR_LEN - 1);
} }
else { else {
getter->name = strdup(arg); strncpy(getter->name, arg, FLEX_GET_STR_LEN - 1);
if (!getter->name) getter->name[FLEX_GET_STR_LEN - 1] = '\0';
FATAL_STRDUP("parse_getter()"); if (strlen(arg) >= FLEX_GET_STR_LEN)
fprintf(stderr, "Warning: flex getter name truncated at %d chars.\n", FLEX_GET_STR_LEN - 1);
} }
arg = p; arg = p;
} }
if (!getter->name) { if (!getter->name[0]) {
fprintf(stderr, "Bad flex spec, \"get\" missing name!\n"); fprintf(stderr, "Bad flex spec, \"get\" missing name!\n");
usage(); usage();
} }
@@ -689,15 +691,14 @@ static r_device *flex_create_device(char const *spec)
if (!key || !*key) if (!key || !*key)
continue; continue;
else if (!strcasecmp(key, "n") || !strcasecmp(key, "name")) { else if (!strcasecmp(key, "n") || !strcasecmp(key, "name")) {
params->name = strdup(val); strncpy(params->name, val, FLEX_GET_STR_LEN - 1);
if (!params->name) params->name[FLEX_GET_STR_LEN - 1] = '\0';
FATAL_STRDUP("flex_create_device()"); if (strlen(val) >= FLEX_GET_STR_LEN)
int name_size = strlen(val) + 27; fprintf(stderr, "Warning: flex name truncated at %d chars.\n", FLEX_GET_STR_LEN - 1);
char* flex_name = malloc(name_size); snprintf(params->dev_name, FLEX_DEV_NAME_LEN, "General purpose decoder '%s'", val);
if (!flex_name) if (snprintf(NULL, 0, "General purpose decoder '%s'", val) - 1 >= FLEX_DEV_NAME_LEN)
FATAL_MALLOC("flex_create_device()"); fprintf(stderr, "Warning: flex device name truncated at %d chars.\n", FLEX_DEV_NAME_LEN - 1);
snprintf(flex_name, name_size, "General purpose decoder '%s'", val); dev->name = params->dev_name;
dev->name = flex_name;
} }
else if (!strcasecmp(key, "m") || !strcasecmp(key, "modulation")) else if (!strcasecmp(key, "m") || !strcasecmp(key, "modulation"))
@@ -797,7 +798,7 @@ static r_device *flex_create_device(char const *spec)
} }
params->fields[i++] = "len"; params->fields[i++] = "len";
params->fields[i++] = "data"; params->fields[i++] = "data";
for (int g = 0; g < GETTER_SLOTS && params->getter[g].name; ++g) { for (int g = 0; g < GETTER_SLOTS && params->getter[g].name[0]; ++g) {
params->fields[i++] = params->getter[g].name; params->fields[i++] = params->getter[g].name;
} }
dev->fields = params->fields; dev->fields = params->fields;
@@ -805,7 +806,7 @@ static r_device *flex_create_device(char const *spec)
// sanity checks // sanity checks
if (!params->name || !*params->name) { if (!params->name[0]) {
fprintf(stderr, "Bad flex spec, missing name!\n"); fprintf(stderr, "Bad flex spec, missing name!\n");
usage(); usage();
} }