Skip to content

Commit

Permalink
minor: Add GCC Static analysis (closes #1372)
Browse files Browse the repository at this point in the history
  • Loading branch information
zuckschwerdt committed Oct 21, 2023
1 parent b455439 commit 96226b5
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 25 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
ADD_DEFINITIONS(-Wlarge-by-value-copy=8)
endif()

# Enable Static analysis on GCC10+
if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "10.0.0")
message(STATUS "Using GCC Static analysis")
add_definitions(-fanalyzer)
endif()

# Shut MSVC up about strdup and strtok
if(MSVC)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
Expand Down
7 changes: 6 additions & 1 deletion src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ R_API data_array_t *data_array(int num_values, data_type_t type, void const *val
return NULL;
}

// the static analyzer can't prove the allocs to be correct
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"

static data_t *vdata_make(data_t *first, const char *key, const char *pretty_key, va_list ap)
{
data_type_t type;
Expand Down Expand Up @@ -257,7 +261,6 @@ static data_t *vdata_make(data_t *first, const char *key, const char *pretty_key
type = va_arg(ap, data_type_t);
}
} while (key);
va_end(ap);
if (format) {
fprintf(stderr, "vdata_make() format type without data\n");
goto alloc_error;
Expand Down Expand Up @@ -344,6 +347,8 @@ R_API void data_free(data_t *data)
}
}

#pragma GCC diagnostic pop

/* data output */

R_API void data_output_print(data_output_t *output, data_t *data)
Expand Down
13 changes: 7 additions & 6 deletions src/decoder_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,11 @@ void decoder_log_bitbuffer(r_device *decoder, int level, char const *func, const
// note that decoder levels start at LOG_WARNING
level += 4;

char *row_codes[BITBUF_ROWS];
char *row_codes[BITBUF_ROWS] = {0};
char *row_bits[BITBUF_ROWS] = {0};

for (unsigned i = 0; i < bitbuffer->num_rows; i++) {
unsigned num_rows = bitbuffer->num_rows;
for (unsigned i = 0; i < num_rows; i++) {
row_codes[i] = bitrow_asprint_code(bitbuffer->bb[i], bitbuffer->bits_per_row[i]);

if (decoder->verbose_bits) {
Expand All @@ -153,20 +154,20 @@ void decoder_log_bitbuffer(r_device *decoder, int level, char const *func, const
"src", "", DATA_STRING, func,
"lvl", "", DATA_INT, level,
"msg", "", DATA_STRING, msg,
"num_rows", "", DATA_INT, bitbuffer->num_rows,
"codes", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_STRING, row_codes),
"num_rows", "", DATA_INT, num_rows,
"codes", "", DATA_ARRAY, data_array(num_rows, DATA_STRING, row_codes),
NULL);
/* clang-format on */

if (decoder->verbose_bits) {
data_append(data,
"bits", "", DATA_ARRAY, data_array(bitbuffer->num_rows, DATA_STRING, row_bits),
"bits", "", DATA_ARRAY, data_array(num_rows, DATA_STRING, row_bits),
NULL);
}

decoder_output_log(decoder, level, data);

for (unsigned i = 0; i < bitbuffer->num_rows; i++) {
for (unsigned i = 0; i < num_rows; i++) {
free(row_codes[i]);
free(row_bits[i]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,5 +1253,5 @@ struct data_output *data_output_http_create(struct mg_mgr *mgr, char const *host
exit(1);
}

return &http->output;
return (struct data_output *)http;
}
3 changes: 3 additions & 0 deletions src/optparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ char *asepcb(char **stringp, char delim, char stop)

int kwargs_match(char const *s, char const *key, char const **val)
{
if (!key || !*key) {
return 0; // no match
}
size_t len = strlen(key);
// check prefix match
if (strncmp(s, key, len)) {
Expand Down
8 changes: 4 additions & 4 deletions src/output_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ struct data_output *data_output_json_create(int log_level, FILE *file)
json->output.output_free = data_output_json_free;
json->file = file;

return &json->output;
return (struct data_output *)json;
}

/* Pretty Key-Value printer */
Expand Down Expand Up @@ -424,7 +424,7 @@ struct data_output *data_output_kv_create(int log_level, FILE *file)

kv->ring_bell = 0; // TODO: enable if requested...

return &kv->output;
return (struct data_output *)kv;
}

/* CSV printer */
Expand Down Expand Up @@ -469,7 +469,7 @@ static void R_API_CALLCONV print_csv_string(data_output_t *output, const char *s
UNUSED(format);
data_output_csv_t *csv = (data_output_csv_t *)output;

while (*str) {
while (str && *str) {
if (strncmp(str, csv->separator, strlen(csv->separator)) == 0)
fputc('\\', csv->file);
fputc(*str, csv->file);
Expand Down Expand Up @@ -638,5 +638,5 @@ struct data_output *data_output_csv_create(int log_level, FILE *file)
csv->output.output_free = data_output_csv_free;
csv->file = file;

return &csv->output;
return (struct data_output *)csv;
}
5 changes: 4 additions & 1 deletion src/output_influx.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ struct data_output *data_output_influx_create(struct mg_mgr *mgr, char *opts)
char *token = NULL;

// param/opts starts with URL
if (!opts) {
opts = "";
}
char *url = opts;
opts = strchr(opts, ',');
if (opts) {
Expand Down Expand Up @@ -515,5 +518,5 @@ struct data_output *data_output_influx_create(struct mg_mgr *mgr, char *opts)
influx->mgr = mgr;
influx_client_init(influx, url, token);

return &influx->output;
return (struct data_output *)influx;
}
2 changes: 1 addition & 1 deletion src/output_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,5 @@ struct data_output *data_output_log_create(int log_level, FILE *file)
log->output.output_free = data_output_log_free;
log->file = file;

return &log->output;
return (struct data_output *)log;
}
2 changes: 1 addition & 1 deletion src/output_mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,5 +599,5 @@ struct data_output *data_output_mqtt_create(struct mg_mgr *mgr, char *param, cha

mqtt->mqc = mqtt_client_init(mgr, &tls_opts, host, port, user, pass, client_id, retain, qos);

return &mqtt->output;
return (struct data_output *)mqtt;
}
20 changes: 16 additions & 4 deletions src/output_rtltcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,21 @@ static THREAD_RETURN THREAD_CALL accept_thread(void *arg)
rtltcp_server_t *srv = arg;

// Start listening for clients, waits for an incoming connection
listen(srv->sock, 1);
int listen_sock = srv->sock; // make it easy for the checker
int r = listen(listen_sock, 1);
if (r < 0) {
perror("ERROR on listen");
closesocket(listen_sock);
srv->sock = INVALID_SOCKET;
return 0;
}
// print_log(LOG_DEBUG, "rtl_tcp", "rtl_tcp listening...");

for (;;) {
// Accept actual connection from the client
struct sockaddr_storage addr = {0};
unsigned addr_len = sizeof(addr);
int sock = accept(srv->sock, (struct sockaddr *)&addr, &addr_len);
int sock = accept(listen_sock, (struct sockaddr *)&addr, &addr_len);

// TODO: ignore ECONNABORTED (Software caused connection abort)
if (sock < 0) {
Expand All @@ -274,6 +281,7 @@ static THREAD_RETURN THREAD_CALL accept_thread(void *arg)
int opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)) == -1) {
perror("setsockopt");
closesocket(sock);
continue;
}
#endif
Expand All @@ -285,6 +293,7 @@ static THREAD_RETURN THREAD_CALL accept_thread(void *arg)
host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
if (err != 0) {
print_logf(LOG_ERROR, __func__, "failed to convert address to string (code=%d)", err);
closesocket(sock);
continue;
}
print_logf(LOG_NOTICE, "rtl_tcp", "client connected from %s port %s", host, port);
Expand Down Expand Up @@ -388,7 +397,6 @@ static int rtltcp_server_start(rtltcp_server_t *srv, char const *host, char cons
for (res = res0; res; res = res->ai_next) {
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock >= 0) {
srv->sock = sock;
memset(&srv->addr, 0, sizeof(srv->addr));
memcpy(&srv->addr, res->ai_addr, res->ai_addrlen);
srv->addr_len = res->ai_addrlen;
Expand All @@ -403,9 +411,11 @@ static int rtltcp_server_start(rtltcp_server_t *srv, char const *host, char cons

if (bind(sock, (struct sockaddr *)&srv->addr, srv->addr_len) < 0) {
perror("error on binding");
closesocket(sock);
return -1;
}

srv->sock = sock;
srv->cfg = cfg;
srv->output = output;

Expand All @@ -416,6 +426,7 @@ static int rtltcp_server_start(rtltcp_server_t *srv, char const *host, char cons
address, sizeof(address), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
if (err != 0) {
print_logf(LOG_ERROR, __func__, "failed to convert address to string (code=%d)", err);
closesocket(sock);
return -1;
}
print_logf(LOG_CRITICAL, "rtl_tcp server", "Serving rtl_tcp on address %s %s", address, portstr);
Expand All @@ -436,6 +447,7 @@ static int rtltcp_server_start(rtltcp_server_t *srv, char const *host, char cons
#endif
if (r) {
fprintf(stderr, "%s: error in pthread_create, rc: %d\n", __func__, r);
closesocket(sock);
}

return r;
Expand Down Expand Up @@ -531,7 +543,7 @@ struct raw_output *raw_output_rtltcp_create(const char *host, const char *port,
exit(1);
}

return &rtltcp->output;
return (struct raw_output *)rtltcp;
}

#else
Expand Down
2 changes: 1 addition & 1 deletion src/output_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ struct data_output *data_output_trigger_create(FILE *file)
trigger->output.output_free = data_output_trigger_free;
trigger->file = file;

return &trigger->output;
return (struct data_output *)trigger;
}
2 changes: 1 addition & 1 deletion src/output_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,5 @@ struct data_output *data_output_syslog_create(int log_level, const char *host, c
syslog->hostname[_POSIX_HOST_NAME_MAX] = '\0';
datagram_client_open(&syslog->client, host, port);

return &syslog->output;
return (struct data_output *)syslog;
}
13 changes: 13 additions & 0 deletions src/pulse_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "pulse_data.h"
#include "rfraw.h"
#include "r_util.h"
#include "fatal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -74,6 +75,10 @@ static inline void chk_ret(int ret)

void pulse_data_print_vcd_header(FILE *file, uint32_t sample_rate)
{
if (!file) {
FATAL("Invalid stream in pulse_data_print_vcd_header()");
}

char time_str[LOCAL_TIME_BUFLEN];
char *timescale;
if (sample_rate <= 500000)
Expand Down Expand Up @@ -161,6 +166,10 @@ void pulse_data_load(FILE *file, pulse_data_t *data, uint32_t sample_rate)

void pulse_data_print_pulse_header(FILE *file)
{
if (!file) {
FATAL("Invalid stream in pulse_data_print_pulse_header()");
}

char time_str[LOCAL_TIME_BUFLEN];

chk_ret(fprintf(file, ";pulse data\n"));
Expand All @@ -172,6 +181,10 @@ void pulse_data_print_pulse_header(FILE *file)

void pulse_data_dump(FILE *file, pulse_data_t const *data)
{
if (!file) {
FATAL("Invalid stream in pulse_data_dump()");
}

char time_str[LOCAL_TIME_BUFLEN];

chk_ret(fprintf(file, ";received %s\n", format_time_str(time_str, NULL, 1, 0)));
Expand Down
6 changes: 6 additions & 0 deletions src/r_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ float inhg2hpa(float inhg)

bool str_endswith(char const *restrict str, char const *restrict suffix)
{
if (!suffix) {
return true;
}
if (!str) {
return false;
}
int str_len = strlen(str);
int suffix_len = strlen(suffix);

Expand Down
13 changes: 12 additions & 1 deletion src/sdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ static int rtltcp_open(sdr_dev_t **out_dev, char const *dev_query, int verbose)
ret = connect(sock, res->ai_addr, res->ai_addrlen);
if (ret == -1) {
perror("connect");
closesocket(sock);
sock = INVALID_SOCKET;
}
else
Expand Down Expand Up @@ -954,6 +955,10 @@ static int sdr_open_soapy(sdr_dev_t **out_dev, char const *dev_query, int verbos
return 0;
}

// the buffer sizes can't be proven to be correct
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-allocation-size"

static int soapysdr_read_loop(sdr_dev_t *dev, sdr_event_cb_t cb, void *ctx, uint32_t buf_num, uint32_t buf_len)
{
size_t buffer_size = (size_t)buf_num * buf_len;
Expand Down Expand Up @@ -1050,6 +1055,8 @@ static int soapysdr_read_loop(sdr_dev_t *dev, sdr_event_cb_t cb, void *ctx, uint
return 0;
}

#pragma GCC diagnostic pop

#endif

/* Public API */
Expand Down Expand Up @@ -1509,8 +1516,12 @@ int sdr_apply_settings(sdr_dev_t *dev, char const *sdr_settings, int verbose)
for (size_t i = 0; i < settings.size; ++i) {
const char *key = settings.keys[i];
const char *value = settings.vals[i];
if (verbose)
if (!key) {
continue;
}
if (verbose) {
print_logf(LOG_NOTICE, "SDR", "Setting %s to %s", key, value);
}
if (!strcmp(key, "antenna")) {
if (SoapySDRDevice_setAntenna(dev->soapy_dev, SOAPY_SDR_RX, 0, value) != 0) {
r = -1;
Expand Down
12 changes: 9 additions & 3 deletions src/write_sigrok.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,17 @@ void write_sigrok(char const *filename, unsigned samplerate, unsigned probes, un
argv[arg++] = "logic-1-1";
}

char *argv_dups[30] = {0}; // store only dups to help the checker match the free()
char **argv_analog = &argv[arg];
char str_buf[64];
for (unsigned i = probes + 1; i <= probes + analogs; ++i) {
snprintf(str_buf, sizeof(str_buf), "analog-1-%u-1", i);
char* dup = strdup(str_buf);
if (!dup) {
FATAL_STRDUP("write_sigrok()");
FATAL_STRDUP("write_sigrok()");
}
argv[arg++] = dup;
argv_dups[arg++] = dup;
}

int status = 0;
Expand All @@ -178,8 +180,9 @@ void write_sigrok(char const *filename, unsigned samplerate, unsigned probes, un
// child process because return value zero
execvp(argv[0], argv);
// execvp() returns only on error
for (int i = 0; i < arg; ++i)
for (int i = 0; i < arg; ++i) {
fprintf(stderr, "%s ", argv[i]);
}
fprintf(stderr, "\n");
perror("execvp");
exit(1);
Expand Down Expand Up @@ -211,8 +214,11 @@ void write_sigrok(char const *filename, unsigned samplerate, unsigned probes, un
if (unlink(argv_analog[i])) {
perror("unlinking Sigrok \"analog-1-N-1\" file");
}
free(argv_analog[i]);
}
for (int i = 0; i < arg; ++i) {
free(argv_dups[i]);
}

#endif // !_WIN32
}

Expand Down
Loading

0 comments on commit 96226b5

Please sign in to comment.