Skip to content

Commit

Permalink
Convert all variable length arrays to heap allocations
Browse files Browse the repository at this point in the history
VLA's are inherently unsafe so the safest option is to not use them
  • Loading branch information
JFreegman committed Oct 28, 2020
1 parent 4d96d6a commit d97782d
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 69 deletions.
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=gnu99 -pthread -Wall -Wpedantic -Wunused -fstack-protector-all
CFLAGS += -std=gnu99 -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
25 changes: 20 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 @@ -424,10 +433,16 @@ 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) {
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
53 changes: 36 additions & 17 deletions src/autocomplete.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,42 +38,51 @@
#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 (size_t i = 0; i < n_matches; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", list[i]);
}

for (i = 0; i < n_items; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
}

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

const char *L = (char *)list;

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

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, 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 Down Expand Up @@ -102,7 +111,7 @@ 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 void *list, const size_t n_items, size_t size, bool dir_search)
{
ChatContext *ctx = self->chatwin;

Expand Down Expand Up @@ -161,7 +170,14 @@ 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];

char **matches = (char **)malloc_ptr_array(n_items, MAX_STR_SIZE, sizeof(char *));

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

int i = 0;

/* put all list matches in matches array */
Expand All @@ -177,15 +193,18 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
free(sub);

if (!n_matches) {
free_ptr_array((void **) matches, n_items);
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), matches, n_matches, MAX_STR_SIZE);

free_ptr_array((void **) matches, n_items);

if (match_len == 0) {
return 0;
Expand Down Expand Up @@ -365,7 +384,7 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)

if (dircount > 1) {
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr);
print_matches(self, m, dirnames, dircount, NAME_MAX + 1);
print_dir_matches(self, m, dirnames, dircount, NAME_MAX + 1);
}

return complete_path(self, dirnames, dircount, NAME_MAX + 1);
Expand Down
13 changes: 11 additions & 2 deletions src/avatars.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,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
36 changes: 29 additions & 7 deletions src/chat.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,18 +422,28 @@ static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum,
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) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Out of memory.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}

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

if (send_length != length) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read fail.", ft->file_name);
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
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 chat callback (error %d)\n", err);
}
Expand Down Expand Up @@ -613,20 +623,29 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
bytes_convert_str(sizestr, sizeof(sizestr), file_size);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", filename, sizestr);

char file_path[PATH_MAX + name_length + 1];
size_t file_path_buf_size = PATH_MAX + name_length + 1;
char *file_path = malloc(file_path_buf_size);

if (file_path == NULL) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Out of memory.");
return;
}

size_t path_len = name_length;

/* use specified download path in config if possible */
if (!string_is_empty(user_settings->download_path)) {
snprintf(file_path, sizeof(file_path), "%s%s", user_settings->download_path, filename);
snprintf(file_path, file_path_buf_size, "%s%s", user_settings->download_path, filename);
path_len += strlen(user_settings->download_path);
} else {
snprintf(file_path, sizeof(file_path), "%s", filename);
snprintf(file_path, file_path_buf_size, "%s", filename);
}

if (path_len >= sizeof(file_path) || path_len >= sizeof(ft->file_path) || name_length >= sizeof(ft->file_name)) {
if (path_len >= file_path_buf_size || path_len >= sizeof(ft->file_path) || name_length >= sizeof(ft->file_name)) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer faield: File path too long.");
free(file_path);
return;
}

Expand All @@ -642,7 +661,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
++count;
size_t d_len = strlen(d);

if (path_len + d_len >= sizeof(file_path)) {
if (path_len + d_len >= file_path_buf_size) {
path_len -= d_len;
file_path[path_len] = '\0';
}
Expand All @@ -653,6 +672,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
if (count > 999) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: invalid file path.");
free(file_path);
return;
}
}
Expand All @@ -664,6 +684,8 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
tox_file_get_file_id(m, friendnum, filenum, ft->file_id, NULL);

free(file_path);

if (self->active_box != -1) {
box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS | user_settings->bell_on_filetrans,
self->active_box, "Incoming file: %s", filename);
Expand Down
12 changes: 10 additions & 2 deletions src/file_transfers.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,18 @@ void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t l
strcat(prog_line, "-");
}

char full_line[strlen(pct_str) + NUM_PROG_MARKS + strlen(bps_str) + 7];
snprintf(full_line, sizeof(full_line), "%s [%s] %s/s", pct_str, prog_line, bps_str);
size_t line_buf_size = strlen(pct_str) + NUM_PROG_MARKS + strlen(bps_str) + 7;
char *full_line = malloc(line_buf_size);

if (full_line == NULL) {
return;
}

snprintf(full_line, line_buf_size, "%s [%s] %s/s", pct_str, prog_line, bps_str);

line_info_set(self, line_id, full_line);

free(full_line);
}

static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)
Expand Down
Loading

0 comments on commit d97782d

Please sign in to comment.