Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup: Convert all variable length arrays to heap allocations #100

Merged
merged 3 commits into from
Nov 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CFG_DIR = $(BASE_DIR)/cfg
LIBS = toxcore ncursesw libconfig libcurl

CFLAGS ?= -g
CFLAGS += -std=c99 -pthread -Wall -Wpedantic -Wunused -fstack-protector-all
CFLAGS += -std=c99 -pthread -Wall -Wpedantic -Wunused -fstack-protector-all -Wvla
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += ${USER_CFLAGS}
Expand Down
26 changes: 21 additions & 5 deletions src/audio_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,20 +301,29 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t *device_idx
return de_FailedStart;
}

size_t zeros_size = frame_size * sizeof(uint16_t);
uint16_t *zeros = calloc(1, zeros_size);

if (zeros == NULL) {
free(device);
running[type][*device_idx] = NULL;
unlock;
return de_FailedStart;
}

device->ctx = alcCreateContext(device->dhndl, NULL);
alcMakeContextCurrent(device->ctx);

alGenBuffers(OPENAL_BUFS, device->buffers);
alGenSources((uint32_t)1, &device->source);
alSourcei(device->source, AL_LOOPING, AL_FALSE);

uint16_t zeros[frame_size];
memset(zeros, 0, frame_size * 2);

for (i = 0; i < OPENAL_BUFS; ++i) {
alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size * 2, sample_rate);
alBufferData(device->buffers[i], device->sound_mode, zeros, zeros_size, sample_rate);
}

free(zeros);

alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers);
alSourcePlay(device->source);
}
Expand Down Expand Up @@ -425,10 +434,17 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t *data, uint32_
alGetSourcei(device->source, AL_BUFFERS_QUEUED, &queued);

if (processed) {
ALuint bufids[processed];
ALuint *bufids = malloc(processed * sizeof(ALuint));

if (bufids == NULL) {
pthread_mutex_unlock(device->mutex);
return de_InternalError;
}

alSourceUnqueueBuffers(device->source, processed, bufids);
alDeleteBuffers(processed - 1, bufids + 1);
bufid = bufids[0];
free(bufids);
} else if (queued < 16) {
alGenBuffers(1, &bufid);
} else {
Expand Down
103 changes: 62 additions & 41 deletions src/autocomplete.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,42 +38,37 @@
#include "execute.h"
#include "configdir.h"

static void print_matches(ToxWindow *self, Tox *m, const void *list, size_t n_items, size_t size)
static void print_ac_matches(ToxWindow *self, Tox *m, char **list, size_t n_matches)
{
if (m) {
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
}

const char *L = (char *) list;
int i;

for (i = 0; i < n_items; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", &L[i * size]);
for (size_t i = 0; i < n_matches; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", list[i]);
}

line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, ""); /* formatting */
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
}

/* puts match in match buffer. if more than one match, add first n chars that are identical.
* e.g. if matches contains: [foo, foobar, foe] we put fo in match.
*
* Returns the length of the match.
*/
static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char (*matches)[MAX_STR_SIZE], int n)
static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, const char **matches, size_t n_items,
size_t max_size)
{
UNUSED_VAR(self);

if (n == 1) {
if (n_items == 1) {
return snprintf(match, match_sz, "%s", matches[0]);
}

int i;

for (i = 0; i < MAX_STR_SIZE; ++i) {
for (size_t i = 0; i < max_size; ++i) {
char ch1 = matches[0][i];
int j;

for (j = 0; j < n; ++j) {
for (size_t j = 0; j < n_items; ++j) {
char ch2 = matches[j][i];

if (ch1 != ch2 || !ch1) {
Expand All @@ -92,8 +87,7 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
* then fills line with the complete word. e.g. "Hello jo" would complete the line
* with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
*
* list is a pointer to the list of strings being compared, n_items is the number of items
* in the list, and size is the size of each item in the list.
* `list` is a pointer to `n_items` strings. Each string in the list must be <= MAX_STR_SIZE.
*
* dir_search should be true if the line being completed is a file path.
*
Expand All @@ -102,19 +96,18 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
*
* Note: This function should not be called directly. Use complete_line() and complete_path() instead.
*/
static int complete_line_helper(ToxWindow *self, const void *list, size_t n_items, size_t size, bool dir_search)
static int complete_line_helper(ToxWindow *self, const char **list, const size_t n_items, bool dir_search)
{
ChatContext *ctx = self->chatwin;

if (ctx->pos <= 0 || ctx->len <= 0 || ctx->pos > ctx->len) {
return -1;
}

if (ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE) {
if (ctx->len >= MAX_STR_SIZE) {
return -1;
}

const char *L = (const char *) list;
const char *endchrs = " ";
char ubuf[MAX_STR_SIZE] = {0};

Expand Down Expand Up @@ -161,31 +154,36 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item

int s_len = strlen(sub);
size_t n_matches = 0;
char matches[n_items][MAX_STR_SIZE];
int i = 0;

/* put all list matches in matches array */
for (i = 0; i < n_items; ++i) {
char str[MAX_CMDNAME_SIZE + 1];
snprintf(str, sizeof(str), "%s", &L[i * size]);
char **matches = (char **) malloc_ptr_array(n_items, MAX_STR_SIZE);

if (matches == NULL) {
free(sub);
return -1;
}

if (strncasecmp(str, sub, s_len) == 0) {
strcpy(matches[n_matches++], str);
/* put all list matches in matches array */
for (size_t i = 0; i < n_items; ++i) {
if (strncasecmp(list[i], sub, s_len) == 0) {
snprintf(matches[n_matches++], MAX_STR_SIZE, "%s", list[i]);
}
}

free(sub);

if (!n_matches) {
free_ptr_array((void **) matches);
return -1;
}

if (!dir_search && n_matches > 1) {
print_matches(self, NULL, matches, n_matches, MAX_STR_SIZE);
print_ac_matches(self, NULL, matches, n_matches);
}

char match[MAX_STR_SIZE];
size_t match_len = get_str_match(self, match, sizeof(match), matches, n_matches);
size_t match_len = get_str_match(self, match, sizeof(match), (const char **) matches, n_matches, MAX_STR_SIZE);

free_ptr_array((void **) matches);

if (match_len == 0) {
return 0;
Expand Down Expand Up @@ -261,14 +259,14 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
return diff;
}

int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size)
int complete_line(ToxWindow *self, const char **list, size_t n_items)
{
return complete_line_helper(self, list, n_items, size, false);
return complete_line_helper(self, list, n_items, false);
}

static int complete_path(ToxWindow *self, const void *list, size_t n_items, size_t size)
static int complete_path(ToxWindow *self, const char **list, const size_t n_items)
{
return complete_line_helper(self, list, n_items, size, true);
return complete_line_helper(self, list, n_items, true);
}

/* Transforms a tab complete starting with the shorthand "~" into the full home directory. */
Expand Down Expand Up @@ -300,6 +298,18 @@ static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const c
ctx->len = ctx->pos;
}

/*
* Return true if the first `p_len` chars in `s` are equal to `p` and `s` is a valid directory name.
*/
static bool is_partial_match(const char *s, const char *p, size_t p_len)
{
if (s == NULL || p == NULL) {
return false;
}

return strncmp(s, p, p_len) == 0 && strcmp(".", s) != 0 && strcmp("..", s) != 0;
}

/* Attempts to match /command "<incomplete-dir>" line to matching directories.
* If there is only one match the line is auto-completed.
*
Expand Down Expand Up @@ -338,35 +348,46 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)

snprintf(b_name, sizeof(b_name), "%s", &b_path[si + 1]);
b_path[si + 1] = '\0';
int b_name_len = strlen(b_name);
size_t b_name_len = strlen(b_name);
DIR *dp = opendir(b_path);

if (dp == NULL) {
return -1;
}

char dirnames[MAX_DIRS][NAME_MAX + 1];
char **dirnames = (char **) malloc_ptr_array(MAX_DIRS, NAME_MAX + 1);

if (dirnames == NULL) {
closedir(dp);
return -1;
}

struct dirent *entry;

int dircount = 0;

while ((entry = readdir(dp)) && dircount < MAX_DIRS) {
if (strncmp(entry->d_name, b_name, b_name_len) == 0
&& strcmp(".", entry->d_name) && strcmp("..", entry->d_name)) {
snprintf(dirnames[dircount], sizeof(dirnames[dircount]), "%s", entry->d_name);
if (is_partial_match(entry->d_name, b_name, b_name_len)) {
snprintf(dirnames[dircount], NAME_MAX + 1, "%s", entry->d_name);
++dircount;
}
}

closedir(dp);

if (dircount == 0) {
free_ptr_array((void **) dirnames);
return -1;
}

if (dircount > 1) {
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr);
print_matches(self, m, dirnames, dircount, NAME_MAX + 1);
qsort(dirnames, dircount, sizeof(char *), qsort_ptr_char_array_helper);
print_ac_matches(self, m, dirnames, dircount);
}

return complete_path(self, dirnames, dircount, NAME_MAX + 1);
int ret = complete_path(self, (const char **) dirnames, dircount);

free_ptr_array((void **) dirnames);

return ret;
}
9 changes: 6 additions & 3 deletions src/autocomplete.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@
* then fills line with the complete word. e.g. "Hello jo" would complete the line
* with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
*
* list is a pointer to the list of strings being compared, n_items is the number of items
* in the list, and size is the size of each item in the list.
* `list` is a pointer to `n_items` strings.
*
* dir_search should be true if the line being completed is a file path.
*
* Returns the difference between the old len and new len of line on success.
* Returns -1 on error.
*
* Note: This function should not be called directly. Use complete_line() and complete_path() instead.
*/
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size);
int complete_line(ToxWindow *self, const char **list, size_t n_items);

/* Attempts to match /command "<incomplete-dir>" line to matching directories.
* If there is only one match the line is auto-completed.
Expand Down
44 changes: 42 additions & 2 deletions src/avatars.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,37 @@ static struct Avatar {
off_t size;
} Avatar;

/* Compares the first size bytes of fp to signature.
*
* Returns 0 if they are the same
* Returns 1 if they differ
* Returns -1 on error.
*
* On success this function will seek back to the beginning of fp.
*/
static int check_file_signature(const unsigned char *signature, size_t size, FILE *fp)
{
char *buf = malloc(size);

if (buf == NULL) {
return -1;
}

if (fread(buf, size, 1, fp) != 1) {
free(buf);
return -1;
}

int ret = memcmp(signature, buf, size);

free(buf);

if (fseek(fp, 0L, SEEK_SET) == -1) {
return -1;
}

return ret == 0 ? 0 : 1;
}

static void avatar_clear(void)
{
Expand Down Expand Up @@ -196,17 +227,26 @@ void on_avatar_chunk_request(Tox *m, struct FileTransfer *ft, uint64_t position,
ft->position = position;
}

uint8_t send_data[length];
size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
uint8_t *send_data = malloc(length);

if (send_data == NULL) {
close_file_transfer(NULL, m, ft, TOX_FILE_CONTROL_CANCEL, NULL, silent);
return;
}

size_t send_length = fread(send_data, 1, length, ft->file);

if (send_length != length) {
close_file_transfer(NULL, m, ft, TOX_FILE_CONTROL_CANCEL, NULL, silent);
free(send_data);
return;
}

Tox_Err_File_Send_Chunk err;
tox_file_send_chunk(m, ft->friendnum, ft->filenum, position, send_data, send_length, &err);

free(send_data);

if (err != TOX_ERR_FILE_SEND_CHUNK_OK) {
fprintf(stderr, "tox_file_send_chunk failed in avatar callback (error %d)\n", err);
}
Expand Down
Loading