diff --git a/include/fatal.h b/include/fatal.h new file mode 100644 index 000000000..bbfb3f9a3 --- /dev/null +++ b/include/fatal.h @@ -0,0 +1,38 @@ +/** @file + Fatal abort and warning macros for allocs. + + Copyright (C) 2019 Christian W. Zuckschwerdt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#ifndef INCLUDE_FATAL_H_ +#define INCLUDE_FATAL_H_ + +#define STR(x) #x +#define STRINGIFY(x) STR(x) +#define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__) +#define FATAL(what) do { fprintf(stderr, "FATAL: " what " from " FILE_LINE "\n"); exit(1); } while (0) +#define FATAL_MALLOC(what) FATAL("low memory? malloc() failed in " what) +#define FATAL_CALLOC(what) FATAL("low memory? calloc() failed in " what) +#define FATAL_REALLOC(what) FATAL("low memory? realloc() failed in " what) +#define FATAL_STRDUP(what) FATAL("low memory? strdup() failed in " what) +#define WARN(what) fprintf(stderr, "WARNING: " what " from " FILE_LINE "\n") +#define WARN_MALLOC(what) WARN("low memory? malloc() failed in " what) +#define WARN_CALLOC(what) WARN("low memory? calloc() failed in " what) +#define WARN_REALLOC(what) WARN("low memory? realloc() failed in " what) +#define WARN_STRDUP(what) WARN("low memory? strdup() failed in " what) + +/* + Use like this: + + char *buf = malloc(size); + if (!buf) + FATAL_MALLOC("my_func()"); + +*/ + +#endif /* INCLUDE_FATAL_H_ */ diff --git a/src/am_analyze.c b/src/am_analyze.c index 213530114..74aec0de8 100644 --- a/src/am_analyze.c +++ b/src/am_analyze.c @@ -15,6 +15,7 @@ #include "bitbuffer.h" #include "samp_grab.h" +#include "fatal.h" #include "am_analyze.h" @@ -25,7 +26,9 @@ am_analyze_t *am_analyze_create(void) { am_analyze_t *a; a = calloc(1, sizeof(am_analyze_t)); - return a; // NOTE: might silently return NULL on alloc failure. + if (!a) + WARN_CALLOC("am_analyze_create()"); + return a; // NOTE: returns NULL on alloc failure. } void am_analyze_free(am_analyze_t *a) diff --git a/src/confparse.c b/src/confparse.c index 535b07ae3..d4d037606 100644 --- a/src/confparse.c +++ b/src/confparse.c @@ -20,6 +20,7 @@ #include #include #include "confparse.h" +#include "fatal.h" #ifdef _WIN32 #include @@ -59,8 +60,9 @@ char *readconf(char const *path) return NULL; } - conf = (char *)malloc(file_size + 1); - if (conf == NULL) { + conf = malloc(file_size + 1); + if (!conf) { + WARN_MALLOC("readconf()"); fprintf(stderr, "Failed to allocate memory for \"%s\"\n", path); fclose(fp); return NULL; diff --git a/src/data.c b/src/data.c index 759170d4b..8b055be0f 100644 --- a/src/data.c +++ b/src/data.c @@ -52,6 +52,7 @@ #include "term_ctl.h" #include "abuf.h" +#include "fatal.h" #include "data.h" @@ -163,18 +164,24 @@ static bool import_values(void *dst, void *src, int num_values, data_type_t type data_array_t *data_array(int num_values, data_type_t type, void *values) { data_array_t *array = calloc(1, sizeof(data_array_t)); - if (array) { - int element_size = dmt[type].array_element_size; - array->values = calloc(num_values, element_size); - if (!array->values) - goto alloc_error; - if (!import_values(array->values, values, num_values, type)) - goto alloc_error; + if (!array) { + WARN_CALLOC("data_array()"); + return NULL; // NOTE: returns NULL on alloc failure. + } - array->num_values = num_values; - array->type = type; + int element_size = dmt[type].array_element_size; + array->values = calloc(num_values, element_size); + if (!array->values) { + WARN_CALLOC("data_array()"); + goto alloc_error; } - return array; // NOTE: might silently return NULL on alloc failure. + if (!import_values(array->values, values, num_values, type)) + goto alloc_error; + + array->num_values = num_values; + array->type = type; + + return array; alloc_error: if (array) @@ -198,8 +205,10 @@ static data_t *vdata_make(data_t *first, const char *key, const char *pretty_key switch (type) { case DATA_FORMAT: format = strdup(va_arg(ap, char *)); - if (!format) + if (!format) { + WARN_STRDUP("vdata_make()"); goto alloc_error; + } type = va_arg(ap, data_type_t); continue; break; @@ -211,16 +220,22 @@ static data_t *vdata_make(data_t *first, const char *key, const char *pretty_key break; case DATA_INT: value = malloc(sizeof(int)); - if (value) + if (!value) + WARN_MALLOC("vdata_make()"); + else // NOTE: skipped on alloc failure *(int *)value = va_arg(ap, int); break; case DATA_DOUBLE: value = malloc(sizeof(double)); - if (value) + if (!value) + WARN_MALLOC("vdata_make()"); + else // NOTE: skipped on alloc failure *(double *)value = va_arg(ap, double); break; case DATA_STRING: value = strdup(va_arg(ap, char *)); + if (!value) + WARN_STRDUP("vdata_make()"); break; case DATA_ARRAY: value = va_arg(ap, data_t *); @@ -234,17 +249,23 @@ static data_t *vdata_make(data_t *first, const char *key, const char *pretty_key goto alloc_error; current = calloc(1, sizeof(*current)); - if (!current) + if (!current) { + WARN_CALLOC("vdata_make()"); goto alloc_error; + } if (prev) prev->next = current; current->key = strdup(key); - if (!current->key) + if (!current->key) { + WARN_STRDUP("vdata_make()"); goto alloc_error; + } current->pretty_key = strdup(pretty_key ? pretty_key : key); - if (!current->pretty_key) + if (!current->pretty_key) { + WARN_STRDUP("vdata_make()"); goto alloc_error; + } current->type = type; current->format = format; current->value = value; @@ -484,8 +505,8 @@ struct data_output *data_output_json_create(FILE *file) { data_output_t *output = calloc(1, sizeof(data_output_t)); if (!output) { - fprintf(stderr, "calloc() failed"); - return NULL; + WARN_CALLOC("data_output_json_create()"); + return NULL; // NOTE: returns NULL on alloc failure. } output->print_data = print_json_data; @@ -670,8 +691,8 @@ struct data_output *data_output_kv_create(FILE *file) { data_output_kv_t *kv = calloc(1, sizeof(data_output_kv_t)); if (!kv) { - fprintf(stderr, "calloc() failed"); - return NULL; + WARN_CALLOC("data_output_kv_create()"); + return NULL; // NOTE: returns NULL on alloc failure. } kv->output.print_data = print_kv_data; @@ -766,8 +787,10 @@ static void data_output_csv_start(struct data_output *output, const char **field csv->separator = ","; allowed = calloc(num_fields, sizeof(const char *)); - if (!allowed) + if (!allowed) { + WARN_CALLOC("data_output_csv_start()"); goto alloc_error; + } memcpy(allowed, fields, sizeof(const char *) * num_fields); qsort(allowed, num_fields, sizeof(char *), compare_strings); @@ -789,12 +812,16 @@ static void data_output_csv_start(struct data_output *output, const char **field num_unique_fields = i; csv->fields = calloc(num_unique_fields + 1, sizeof(const char *)); - if (!csv->fields) + if (!csv->fields) { + WARN_CALLOC("data_output_csv_start()"); goto alloc_error; + } use_count = calloc(num_unique_fields, sizeof(*use_count)); - if (!use_count) + if (!use_count) { + WARN_CALLOC("data_output_csv_start()"); goto alloc_error; + } for (i = 0; i < num_fields; ++i) { const char **field = bsearch(&fields[i], allowed, num_unique_fields, sizeof(const char *), @@ -847,8 +874,8 @@ struct data_output *data_output_csv_create(FILE *file) { data_output_csv_t *csv = calloc(1, sizeof(data_output_csv_t)); if (!csv) { - fprintf(stderr, "calloc() failed"); - return NULL; + WARN_CALLOC("data_output_csv_create()"); + return NULL; // NOTE: returns NULL on alloc failure. } csv->output.print_data = print_csv_data; @@ -1102,8 +1129,8 @@ struct data_output *data_output_syslog_create(const char *host, const char *port { data_output_syslog_t *syslog = calloc(1, sizeof(data_output_syslog_t)); if (!syslog) { - fprintf(stderr, "calloc() failed"); - return NULL; + WARN_CALLOC("data_output_syslog_create()"); + return NULL; // NOTE: returns NULL on alloc failure. } #ifdef _WIN32 WSADATA wsa; diff --git a/src/decoder_util.c b/src/decoder_util.c index 51dde8faa..a74013d9d 100644 --- a/src/decoder_util.c +++ b/src/decoder_util.c @@ -14,16 +14,21 @@ #include "data.h" #include "util.h" #include "decoder_util.h" +#include "fatal.h" // create decoder functions r_device *create_device(r_device *dev_template) { r_device *r_dev = malloc(sizeof (*r_dev)); - if (r_dev && dev_template) + if (!r_dev) { + WARN_MALLOC("create_device()"); + return NULL; // NOTE: returns NULL on alloc failure. + } + if (dev_template) *r_dev = *dev_template; // copy - return r_dev; // NOTE: might silently return NULL on alloc failure. + return r_dev; } // variadic print functions @@ -121,13 +126,39 @@ void decoder_output_message(r_device *decoder, char const *msg) decoder_output_data(decoder, data); } -static char *bitrow_print_bits(bitrow_t const bitrow, unsigned bit_len) +static char *bitrow_asprint_code(bitrow_t const bitrow, unsigned bit_len) +{ + char *row_code; + char row_bytes[BITBUF_COLS * 2 + 1]; + + row_bytes[0] = '\0'; + // print byte-wide + for (unsigned col = 0; col < (unsigned)(bit_len + 7) / 8; ++col) { + sprintf(&row_bytes[2 * col], "%02x", bitrow[col]); + } + // remove last nibble if needed + row_bytes[2 * (bit_len + 3) / 8] = '\0'; + + // a simple bitrow representation + row_code = malloc(8 + bit_len / 4 + 1); // "{nnnn}..\0" + if (!row_code) { + WARN_MALLOC("decoder_output_bitbuffer()"); + return NULL; // NOTE: returns NULL on alloc failure. + } + sprintf(row_code, "{%d}%s", bit_len, row_bytes); + + return row_code; +} + +static char *bitrow_asprint_bits(bitrow_t const bitrow, unsigned bit_len) { char *row_bits, *p; p = row_bits = malloc(bit_len + bit_len / 4 + 1); // "1..\0" (1 space per nibble) - if (!row_bits) - return NULL; // NOTE: might silently return NULL on alloc failure. + if (!row_bits) { + WARN_MALLOC("bitrow_asprint_bits()"); + return NULL; // NOTE: returns NULL on alloc failure. + } // print bit-wide with a space every nibble for (unsigned i = 0; i < bit_len; ++i) { @@ -151,25 +182,13 @@ void decoder_output_bitbuffer(r_device *decoder, bitbuffer_t const *bitbuffer, c data_t *data; char *row_codes[BITBUF_ROWS]; char *row_bits[BITBUF_ROWS] = {0}; - char row_bytes[BITBUF_COLS * 2 + 1]; unsigned i; for (i = 0; i < bitbuffer->num_rows; i++) { - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (unsigned)(bitbuffer->bits_per_row[i] + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitbuffer->bb[i][col]); - } - // remove last nibble if needed - row_bytes[2 * (bitbuffer->bits_per_row[i] + 3) / 8] = '\0'; - - // a simpler representation for csv output - row_codes[i] = malloc(8 + BITBUF_COLS * 2 + 1); // "{nnn}..\0" - if (row_codes[i]) // NOTE: might silently skip on alloc failure. - sprintf(row_codes[i], "{%d}%s", bitbuffer->bits_per_row[i], row_bytes); + row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); if (decoder->verbose_bits) { - row_bits[i] = bitrow_print_bits(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); + row_bits[i] = bitrow_asprint_bits(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); } } @@ -216,9 +235,7 @@ void decoder_output_bitbuffer_array(r_device *decoder, bitbuffer_t const *bitbuf NULL); // a simpler representation for csv output - row_codes[i] = malloc(8 + BITBUF_COLS * 2 + 1); // "{nnn}..\0" - if (row_codes[i]) // NOTE: might silently skip on alloc failure. - sprintf(row_codes[i], "{%d}%s", bitbuffer->bits_per_row[i], row_bytes); + row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]); } data = data_make( @@ -239,20 +256,8 @@ void decoder_output_bitrow(r_device *decoder, bitrow_t const bitrow, unsigned bi data_t *data; char *row_code; char *row_bits = NULL; - char row_bytes[BITBUF_COLS * 2 + 1]; - - row_bytes[0] = '\0'; - // print byte-wide - for (unsigned col = 0; col < (bit_len + 7) / 8; ++col) { - sprintf(&row_bytes[2 * col], "%02x", bitrow[col]); - } - // remove last nibble if needed - row_bytes[2 * (bit_len + 3) / 8] = '\0'; - // a simpler representation for csv output - row_code = malloc(8 + BITBUF_COLS * 2 + 1); // "{nnn}..\0" - if (row_code) // NOTE: might silently skip on alloc failure. - sprintf(row_code, "{%d}%s", bit_len, row_bytes); + row_code = bitrow_asprint_code(bitrow, bit_len); data = data_make( "msg", "", DATA_STRING, msg, @@ -260,7 +265,7 @@ void decoder_output_bitrow(r_device *decoder, bitrow_t const bitrow, unsigned bi NULL); if (decoder->verbose_bits) { - row_bits = bitrow_print_bits(bitrow, bit_len); + row_bits = bitrow_asprint_bits(bitrow, bit_len); data_append(data, "bits", "", DATA_STRING, row_bits, NULL); diff --git a/src/devices/fineoffset.c b/src/devices/fineoffset.c index 5cfa878e4..47e154880 100644 --- a/src/devices/fineoffset.c +++ b/src/devices/fineoffset.c @@ -11,6 +11,7 @@ */ #include "decoder.h" +#include "fatal.h" #include r_device fineoffset_WH2; @@ -19,14 +20,14 @@ static r_device *fineoffset_WH2_create(char *arg) { r_device *r_dev = create_device(&fineoffset_WH2); if (!r_dev) { - fprintf(stderr, "create_device() failed"); + fprintf(stderr, "fineoffset_WH2_create() failed"); return NULL; // NOTE: returns NULL on alloc failure. } if (arg && !strcmp(arg, "no-wh5")) { int *quirk = malloc(sizeof (*quirk)); if (!quirk) { - fprintf(stderr, "malloc() failed"); + WARN_MALLOC("fineoffset_WH2_create()"); free(r_dev); return NULL; // NOTE: returns NULL on alloc failure. } diff --git a/src/devices/flex.c b/src/devices/flex.c index 84ce0d210..dd813e670 100644 --- a/src/devices/flex.c +++ b/src/devices/flex.c @@ -10,6 +10,7 @@ #include "decoder.h" #include "optparse.h" +#include "fatal.h" #include static inline int bit(const uint8_t *bytes, unsigned bit) @@ -263,8 +264,10 @@ static int flex_callback(r_device *decoder, bitbuffer_t *bitbuffer) render_getters(row_data[i], bitbuffer->bb[i], params); // a simpler representation for csv output - row_codes[i] = malloc(8 + BITBUF_COLS * 2 + 1); // "{nnn}..\0" - if (row_codes[i]) // NOTE: might silently skip on alloc failure. + row_codes[i] = malloc(8 + bitbuffer->bits_per_row[i] / 4 + 1); // "{nnnn}..\0" + if (!row_codes[i]) + WARN_MALLOC("flex_decode()"); + else // NOTE: skipped on alloc failure. sprintf(row_codes[i], "{%d}%s", bitbuffer->bits_per_row[i], row_bytes); } /* clang-format off */ @@ -427,7 +430,9 @@ const char *parse_map(const char *arg, struct flex_get *getter) const char *e = c; while (*e != ' ' && *e != ']') e++; val = malloc(e - c + 1); - if (val) { // NOTE: might silently skip on alloc failure. + if (!val) + WARN_MALLOC("parse_map()"); + else { // NOTE: skipped on alloc failure. memcpy(val, c, e - c); val[e - c] = '\0'; } @@ -458,8 +463,11 @@ static void parse_getter(const char *arg, struct flex_get *getter) getter->bit_count = parse_bits(arg, bitrow); getter->mask = extract_number(bitrow, 0, getter->bit_count); } - else + else { getter->name = strdup(arg); + if (!getter->name) + FATAL_STRDUP("parse_getter()"); + } arg = p; } if (!getter->name) { @@ -480,18 +488,23 @@ r_device *flex_create_device(char *spec) } struct flex_params *params = calloc(1, sizeof(*params)); - if (!params) - return NULL; // NOTE: might silently return NULL on alloc failure. + if (!params) { + WARN_CALLOC("flex_create_device()"); + return NULL; // NOTE: returns NULL on alloc failure. + } r_device *dev = calloc(1, sizeof(*dev)); if (!dev) { + WARN_CALLOC("flex_create_device()"); free(params); - return NULL; // NOTE: might silently return NULL on alloc failure. + return NULL; // NOTE: returns NULL on alloc failure. } dev->decode_ctx = params; char *c, *o; int get_count = 0; spec = strdup(spec); + if (!spec) + FATAL_STRDUP("flex_create_device()"); // locate optional args and terminate mandatory args char *args = strchr(spec, ','); if (args) { @@ -508,10 +521,13 @@ r_device *flex_create_device(char *spec) if (!strncasecmp(c, "name=", 5)) c += 5; params->name = strdup(c); + if (!params->name) + FATAL_STRDUP("flex_create_device()"); int name_size = strlen(c) + 27; dev->name = malloc(name_size); - if (dev->name) // NOTE: might silently skip on alloc failure. - snprintf(dev->name, name_size, "General purpose decoder '%s'", c); + if (!dev->name) + FATAL_MALLOC("flex_create_device()"); + snprintf(dev->name, name_size, "General purpose decoder '%s'", c); c = strtok(NULL, ":"); if (c != NULL) { diff --git a/src/list.c b/src/list.c index 6ab1d231d..037011127 100644 --- a/src/list.c +++ b/src/list.c @@ -10,6 +10,7 @@ */ #include "list.h" +#include "fatal.h" #include #include @@ -18,8 +19,7 @@ void list_ensure_size(list_t *list, size_t min_size) if (!list->elems || list->size < min_size) { list->elems = realloc(list->elems, min_size * sizeof(*list->elems)); if (!list->elems) { - fprintf(stderr, "realloc() failed"); - exit(1); // NOTE: abort on alloc failure. + FATAL_REALLOC("list_ensure_size()"); } list->size = min_size; diff --git a/src/output_mqtt.c b/src/output_mqtt.c index 4e36a423a..d5a4ab048 100644 --- a/src/output_mqtt.c +++ b/src/output_mqtt.c @@ -13,6 +13,7 @@ #include "output_mqtt.h" #include "optparse.h" #include "util.h" +#include "fatal.h" #include #include @@ -95,16 +96,13 @@ static void mqtt_client_event(struct mg_connection *nc, int ev, void *ev_data) static struct mg_mgr *mqtt_client_init(char const *host, char const *port, char const *user, char const *pass, char const *client_id, int retain) { struct mg_mgr *mgr = calloc(1, sizeof(*mgr)); - if (!mgr) { - fprintf(stderr, "calloc() failed in %s() %s:%d\n", __func__, __FILE__, __LINE__); - exit(1); - } + if (!mgr) + FATAL_CALLOC("mqtt_client_init()"); mqtt_client_t *ctx = calloc(1, sizeof(*ctx)); - if (!ctx) { - fprintf(stderr, "calloc() failed in %s() %s:%d\n", __func__, __FILE__, __LINE__); - exit(1); - } + if (!ctx) + FATAL_CALLOC("mqtt_client_init()"); + ctx->opts.user_name = user; ctx->opts.password = pass; ctx->publish_flags = MG_MQTT_QOS(0) | (retain ? MG_MQTT_RETAIN : 0); @@ -331,8 +329,8 @@ static void print_mqtt_data(data_output_t *output, data_t *data, char *format) size_t message_size = 20000; // state message need a large buffer char *message = malloc(message_size); if (!message) { - fprintf(stderr, "malloc() failed\n"); - return; // NOTE: skip on alloc failure. + WARN_MALLOC("print_mqtt_data()"); + return; // NOTE: skip output on alloc failure. } data_print_jsons(data, message, message_size); expand_topic(mqtt->topic, mqtt->states, data, mqtt->hostname); @@ -440,24 +438,30 @@ static void data_output_mqtt_free(data_output_t *output) static char *mqtt_topic_default(char const *topic, char const *base, char const *suffix) { - if (topic) - return strdup(topic); - - if (!base) - return strdup(suffix); + char const *p; + if (topic) { + p = topic; + } + else if (!base) { + p = suffix; + } + else { + char path[256]; + snprintf(path, sizeof(path), "%s/%s", base, suffix); + p = path; + } - char path[256]; - snprintf(path, sizeof(path), "%s/%s", base, suffix); - return strdup(path); + char *ret = strdup(p); + if (!ret) + WARN_STRDUP("mqtt_topic_default()"); + return ret; } struct data_output *data_output_mqtt_create(char const *host, char const *port, char *opts, char const *dev_hint) { data_output_mqtt_t *mqtt = calloc(1, sizeof(data_output_mqtt_t)); - if (!mqtt) { - fprintf(stderr, "calloc() failed in %s() %s:%d\n", __func__, __FILE__, __LINE__); - exit(1); - } + if (!mqtt) + FATAL_CALLOC("data_output_mqtt_create()"); gethostname(mqtt->hostname, sizeof(mqtt->hostname) - 1); mqtt->hostname[sizeof(mqtt->hostname) - 1] = '\0'; diff --git a/src/pulse_detect.c b/src/pulse_detect.c index 431f04456..10acd12e6 100644 --- a/src/pulse_detect.c +++ b/src/pulse_detect.c @@ -13,6 +13,7 @@ #include "pulse_demod.h" #include "util.h" #include "decoder.h" +#include "fatal.h" #include #include #include @@ -56,7 +57,6 @@ void pulse_data_dump_raw(uint8_t *buf, unsigned len, uint64_t buf_offset, pulse_ } } -__attribute__((always_inline)) static inline void chk_ret(int ret) { if (ret < 0) { @@ -364,7 +364,10 @@ struct pulse_detect { pulse_detect_t *pulse_detect_create() { - return calloc(1, sizeof(pulse_detect_t)); + pulse_detect_t *pulse_detect = calloc(1, sizeof(pulse_detect_t)); + if (!pulse_detect) + WARN_CALLOC("pulse_detect_create()"); + return pulse_detect; } void pulse_detect_free(pulse_detect_t *pulse_detect) diff --git a/src/r_api.c b/src/r_api.c index 4622c08aa..c16f032e5 100644 --- a/src/r_api.c +++ b/src/r_api.c @@ -27,6 +27,7 @@ #include "optparse.h" #include "output_mqtt.h" #include "compat_time.h" +#include "fatal.h" #ifdef _WIN32 #include @@ -81,10 +82,8 @@ void r_init_cfg(r_cfg_t *cfg) list_ensure_size(&cfg->output_handler, 16); cfg->demod = calloc(1, sizeof(*cfg->demod)); - if (!cfg->demod) { - fprintf(stderr, "Could not create demod!\n"); - exit(1); - } + if (!cfg->demod) + FATAL_CALLOC("r_init_cfg()"); cfg->demod->level_limit = DEFAULT_LEVEL_LIMIT; @@ -95,10 +94,8 @@ void r_init_cfg(r_cfg_t *cfg) r_cfg_t *r_create_cfg(void) { r_cfg_t *cfg = calloc(1, sizeof(*cfg)); - if (!cfg) { - fprintf(stderr, "Could not create cfg!\n"); - exit(1); - } + if (!cfg) + FATAL_CALLOC("r_create_cfg()"); r_init_cfg(cfg); @@ -167,10 +164,8 @@ void register_protocol(r_cfg_t *cfg, r_device *r_dev, char *arg) fprintf(stderr, "Protocol [%d] \"%s\" does not take arguments \"%s\"!\n", r_dev->protocol_num, r_dev->name, arg); } p = malloc(sizeof(*p)); - if (!p) { - fprintf(stderr, "Could not register protocol\n"); - exit(1); - } + if (!p) + FATAL_CALLOC("register_protocol()"); *p = *r_dev; // copy } @@ -485,12 +480,15 @@ void data_acquired_handler(r_device *r_dev, data_t *data) if ((d->type == DATA_STRING) && !strcmp(d->key, "battery")) { free(d->key); d->key = strdup("battery_ok"); + if (!d->key) + FATAL_STRDUP("data_acquired_handler()"); int ok = d->value && !strcmp(d->value, "OK"); free(d->value); d->type = DATA_INT; d->value = malloc(sizeof(int)); - if (d->value) // NOTE: might silently skip on alloc failure. - *(int *)d->value = ok; + if (!d->value) + FATAL_MALLOC("data_acquired_handler()"); + *(int *)d->value = ok; break; } } @@ -868,10 +866,8 @@ void add_null_output(r_cfg_t *cfg, char *param) void add_dumper(r_cfg_t *cfg, char const *spec, int overwrite) { file_info_t *dumper = calloc(1, sizeof(*dumper)); - if (!dumper) { - fprintf(stderr, "Could not add dumper\n"); - exit(1); - } + if (!dumper) + FATAL_CALLOC("add_dumper()"); list_push(&cfg->demod->dumper, dumper); parse_file_info(spec, dumper); diff --git a/src/r_util.c b/src/r_util.c index d59483186..06ce440bc 100644 --- a/src/r_util.c +++ b/src/r_util.c @@ -10,6 +10,7 @@ */ #include "r_util.h" +#include "fatal.h" #include #include #include @@ -169,9 +170,10 @@ char *str_replace(char *orig, char *rep, char *with) } tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); - - if (!result) - return NULL; + if (!result) { + WARN_MALLOC("str_replace()"); + return NULL; // NOTE: returns NULL on alloc failure. + } // first time through the loop, all the variables are set correctly // from here on, diff --git a/src/rtl_433.c b/src/rtl_433.c index b9a79b82a..572b26a86 100644 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -46,6 +46,7 @@ #include "confparse.h" #include "term_ctl.h" #include "compat_paths.h" +#include "fatal.h" #ifdef _WIN32 #include @@ -1211,12 +1212,11 @@ int main(int argc, char **argv) { // Special case for in files if (cfg.in_files.len) { unsigned char *test_mode_buf = malloc(DEFAULT_BUF_LENGTH * sizeof(unsigned char)); + if (!test_mode_buf) + FATAL_MALLOC("test_mode_buf"); float *test_mode_float_buf = malloc(DEFAULT_BUF_LENGTH / sizeof(int16_t) * sizeof(float)); - if (!test_mode_buf || !test_mode_float_buf) - { - fprintf(stderr, "Couldn't allocate read buffers!\n"); - exit(1); - } + if (!test_mode_float_buf) + FATAL_MALLOC("test_mode_float_buf"); if (cfg.duration > 0) { time(&cfg.stop_time); diff --git a/src/samp_grab.c b/src/samp_grab.c index 407d1269b..bece01f30 100644 --- a/src/samp_grab.c +++ b/src/samp_grab.c @@ -25,23 +25,25 @@ #endif #include "samp_grab.h" +#include "fatal.h" samp_grab_t *samp_grab_create(unsigned size) { samp_grab_t *g; g = calloc(1, sizeof(*g)); if (!g) { - return NULL; // NOTE: silently return NULL on alloc failure. + WARN_CALLOC("samp_grab_create()"); + return NULL; // NOTE: returns NULL on alloc failure. } - g->sg_buf = malloc(size); g->sg_size = size; - g->sg_counter = 1; + g->sg_buf = malloc(size); if (!g->sg_buf) { + WARN_MALLOC("samp_grab_create()"); free(g); - return NULL; // NOTE: silently return NULL on alloc failure. + return NULL; // NOTE: returns NULL on alloc failure. } return g; diff --git a/src/sdr.c b/src/sdr.c index a86e06214..9be21ea9e 100644 --- a/src/sdr.c +++ b/src/sdr.c @@ -19,6 +19,7 @@ #include "sdr.h" #include "r_util.h" #include "optparse.h" +#include "fatal.h" #ifdef RTLSDR #include "rtl-sdr.h" #include /* libusb_error_name(), libusb_strerror() */ @@ -152,8 +153,10 @@ static int rtltcp_open(sdr_dev_t **out_dev, int *sample_size, char *dev_query, i fprintf(stderr, "rtl_tcp connected to %s:%s (Tuner: %s)\n", host, port, tuner_name); sdr_dev_t *dev = calloc(1, sizeof(sdr_dev_t)); - if (!dev) - return -1; // NOTE: silently return on alloc failure. + if (!dev) { + WARN_CALLOC("rtltcp_open()"); + return -1; // NOTE: returns error on alloc failure. + } dev->rtl_tcp = sock; dev->sample_size = sizeof(uint8_t); // CU8 @@ -185,8 +188,10 @@ static int rtltcp_read_loop(sdr_dev_t *dev, sdr_read_cb_t cb, void *ctx, uint32_ if (dev->buffer_size != buf_len) { free(dev->buffer); dev->buffer = malloc(buf_len); - if (!dev->buffer) - return -1; // NOTE: silently return on alloc failure. + if (!dev->buffer) { + WARN_MALLOC("rtltcp_read_loop()"); + return -1; // NOTE: returns error on alloc failure. + } dev->buffer_size = buf_len; } uint8_t *buffer = dev->buffer; @@ -294,9 +299,10 @@ static int sdr_open_rtl(sdr_dev_t **out_dev, int *sample_size, char *dev_query, char vendor[256] = "n/a", product[256] = "n/a", serial[256] = "n/a"; int r = -1; sdr_dev_t *dev = calloc(1, sizeof(sdr_dev_t)); - if (!dev) - return -1; // NOTE: silently return on alloc failure. - + if (!dev) { + WARN_CALLOC("sdr_open_rtl()"); + return -1; // NOTE: returns error on alloc failure. + } for (uint32_t i = dev_query ? dev_index : 0; //cast quiets -Wsign-compare; if dev_index were < 0, would have returned -1 above i < (dev_query ? (unsigned)dev_index + 1 : device_count); @@ -605,8 +611,10 @@ static int sdr_open_soapy(sdr_dev_t **out_dev, int *sample_size, char *dev_query SoapySDR_setLogLevel(SOAPY_SDR_DEBUG); sdr_dev_t *dev = calloc(1, sizeof(sdr_dev_t)); - if (!dev) - return -1; // NOTE: silently return on alloc failure. + if (!dev) { + WARN_CALLOC("sdr_open_soapy()"); + return -1; // NOTE: returns error on alloc failure. + } dev->soapy_dev = SoapySDRDevice_makeStrArgs(dev_query); if (!dev->soapy_dev) { @@ -661,9 +669,10 @@ static int soapysdr_read_loop(sdr_dev_t *dev, sdr_read_cb_t cb, void *ctx, uint3 if (dev->buffer_size != buf_len) { free(dev->buffer); dev->buffer = malloc(buf_len); - if (!dev->buffer) - return -1; // NOTE: silently return on alloc failure. - + if (!dev->buffer) { + WARN_CALLOC("soapysdr_read_loop()"); + return -1; // NOTE: returns error on alloc failure. + } dev->buffer_size = buf_len; } int16_t *buffer = dev->buffer; diff --git a/tests/style-check.c b/tests/style-check.c index a7798495e..ac0da04c8 100644 --- a/tests/style-check.c +++ b/tests/style-check.c @@ -35,6 +35,7 @@ static int style_check(char *path) int long_errors = 0; int crlf_errors = 0; int tabs_errors = 0; + int memc_errors = 0; int leading_tabs = 0; int leading_spcs = 0; @@ -42,6 +43,8 @@ static int style_check(char *path) int use_stdout = 0; int use_printf = 0; + int need_cond = 0; + char str[MAX_LEN]; while (fgets(str, MAX_LEN, fp)) { int len = strlen(str); @@ -72,6 +75,17 @@ static int style_check(char *path) use_printf++; } } + if (need_cond && !strstr(str, "if (!")) { + // we had an alloc but no check on the following line + memc_errors++; + } + need_cond = 0; + if (strstr(str, "alloc(") && !strstr(str, "alloc()")) { + need_cond++; + } + if (strstr(str, "strdup(") && !strstr(str, "strdup()")) { + need_cond++; + } } if (leading_tabs && leading_spcs) { tabs_errors = leading_tabs > leading_spcs ? leading_spcs : leading_tabs; @@ -85,6 +99,8 @@ static int style_check(char *path) printf("File \"%s\" has %d CRLF errors.\n", path, crlf_errors); if (tabs_errors) printf("File \"%s\" has %d MIXED tab/spaces errors.\n", path, tabs_errors); + if (memc_errors) + printf("File \"%s\" has %d ALLOC check errors.\n", path, memc_errors); if (leading_tabs) printf("File \"%s\" has %d TAB indented lines.\n", path, leading_tabs); if (strict && use_stdout) @@ -92,7 +108,7 @@ static int style_check(char *path) if (strict && use_printf) printf("File \"%s\" has %d PRINTF lines.\n", path, use_printf); - return read_errors + long_errors + crlf_errors + tabs_errors + leading_tabs + (strict ? use_stdout + use_printf : 0); + return read_errors + long_errors + crlf_errors + tabs_errors + leading_tabs + (strict ? use_stdout + use_printf : 0) + memc_errors; } int main(int argc, char *argv[])