1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-22 22:43:01 +01:00

Convert all variable length arrays to heap allocations

VLA's are inherently unsafe so the safest option is to not use them
This commit is contained in:
jfreegman 2020-10-28 00:54:06 -04:00
parent ff1620c923
commit 2b43340c90
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
12 changed files with 355 additions and 69 deletions

View File

@ -6,7 +6,7 @@ CFG_DIR = $(BASE_DIR)/cfg
LIBS = toxcore ncursesw libconfig libcurl LIBS = toxcore ncursesw libconfig libcurl
CFLAGS ?= -g 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 += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"' CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += ${USER_CFLAGS} CFLAGS += ${USER_CFLAGS}

View File

@ -301,6 +301,16 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t *device_idx
return de_FailedStart; 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); device->ctx = alcCreateContext(device->dhndl, NULL);
alcMakeContextCurrent(device->ctx); alcMakeContextCurrent(device->ctx);
@ -308,13 +318,12 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t *device_idx
alGenSources((uint32_t)1, &device->source); alGenSources((uint32_t)1, &device->source);
alSourcei(device->source, AL_LOOPING, AL_FALSE); 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) { 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); alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers);
alSourcePlay(device->source); alSourcePlay(device->source);
} }
@ -425,10 +434,16 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t *data, uint32_
alGetSourcei(device->source, AL_BUFFERS_QUEUED, &queued); alGetSourcei(device->source, AL_BUFFERS_QUEUED, &queued);
if (processed) { if (processed) {
ALuint bufids[processed]; ALuint *bufids = malloc(processed * sizeof(ALuint));
if (bufids == NULL) {
return de_InternalError;
}
alSourceUnqueueBuffers(device->source, processed, bufids); alSourceUnqueueBuffers(device->source, processed, bufids);
alDeleteBuffers(processed - 1, bufids + 1); alDeleteBuffers(processed - 1, bufids + 1);
bufid = bufids[0]; bufid = bufids[0];
free(bufids);
} else if (queued < 16) { } else if (queued < 16) {
alGenBuffers(1, &bufid); alGenBuffers(1, &bufid);
} else { } else {

View File

@ -38,20 +38,32 @@
#include "execute.h" #include "execute.h"
#include "configdir.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);
}
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, "");
}
static void print_dir_matches(ToxWindow *self, Tox *m, const void *list, size_t n_items, size_t size)
{ {
if (m) { if (m) {
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE); execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
} }
const char *L = (char *)list; const char *L = (char *)list;
int i;
for (i = 0; i < n_items; ++i) { 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, "%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. /* puts match in match buffer. if more than one match, add first n chars that are identical.
@ -59,21 +71,19 @@ static void print_matches(ToxWindow *self, Tox *m, const void *list, size_t n_it
* *
* Returns the length of the 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); UNUSED_VAR(self);
if (n == 1) { if (n_items == 1) {
return snprintf(match, match_sz, "%s", matches[0]); return snprintf(match, match_sz, "%s", matches[0]);
} }
int i; for (size_t i = 0; i < max_size; ++i) {
for (i = 0; i < MAX_STR_SIZE; ++i) {
char ch1 = matches[0][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]; char ch2 = matches[j][i];
if (ch1 != ch2 || !ch1) { if (ch1 != ch2 || !ch1) {
@ -102,7 +112,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. * 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; ChatContext *ctx = self->chatwin;
@ -161,7 +171,14 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
int s_len = strlen(sub); int s_len = strlen(sub);
size_t n_matches = 0; 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; int i = 0;
/* put all list matches in matches array */ /* put all list matches in matches array */
@ -177,15 +194,18 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
free(sub); free(sub);
if (!n_matches) { if (!n_matches) {
free_ptr_array((void **) matches, n_items);
return -1; return -1;
} }
if (!dir_search && n_matches > 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]; 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) { if (match_len == 0) {
return 0; return 0;
@ -365,7 +385,7 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
if (dircount > 1) { if (dircount > 1) {
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr); 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); return complete_path(self, dirnames, dircount, NAME_MAX + 1);

View File

@ -196,17 +196,26 @@ void on_avatar_chunk_request(Tox *m, struct FileTransfer *ft, uint64_t position,
ft->position = position; ft->position = position;
} }
uint8_t send_data[length]; uint8_t *send_data = malloc(length);
size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
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) { if (send_length != length) {
close_file_transfer(NULL, m, ft, TOX_FILE_CONTROL_CANCEL, NULL, silent); close_file_transfer(NULL, m, ft, TOX_FILE_CONTROL_CANCEL, NULL, silent);
free(send_data);
return; return;
} }
Tox_Err_File_Send_Chunk err; Tox_Err_File_Send_Chunk err;
tox_file_send_chunk(m, ft->friendnum, ft->filenum, position, send_data, send_length, &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) { if (err != TOX_ERR_FILE_SEND_CHUNK_OK) {
fprintf(stderr, "tox_file_send_chunk failed in avatar callback (error %d)\n", err); fprintf(stderr, "tox_file_send_chunk failed in avatar callback (error %d)\n", err);
} }

View File

@ -422,18 +422,28 @@ static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum,
ft->position = position; ft->position = position;
} }
uint8_t send_data[length]; uint8_t *send_data = malloc(length);
size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
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) { if (send_length != length) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read fail.", ft->file_name); 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); close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
free(send_data);
return; return;
} }
Tox_Err_File_Send_Chunk err; Tox_Err_File_Send_Chunk err;
tox_file_send_chunk(m, ft->friendnum, ft->filenum, position, send_data, send_length, &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) { if (err != TOX_ERR_FILE_SEND_CHUNK_OK) {
fprintf(stderr, "tox_file_send_chunk failed in chat callback (error %d)\n", err); fprintf(stderr, "tox_file_send_chunk failed in chat callback (error %d)\n", err);
} }
@ -613,20 +623,29 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
bytes_convert_str(sizestr, sizeof(sizestr), file_size); 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); 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; size_t path_len = name_length;
/* use specified download path in config if possible */ /* use specified download path in config if possible */
if (!string_is_empty(user_settings->download_path)) { 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); path_len += strlen(user_settings->download_path);
} else { } 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); 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."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer faield: File path too long.");
free(file_path);
return; return;
} }
@ -642,7 +661,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
++count; ++count;
size_t d_len = strlen(d); 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; path_len -= d_len;
file_path[path_len] = '\0'; file_path[path_len] = '\0';
} }
@ -653,6 +672,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
if (count > 999) { if (count > 999) {
tox_file_control(m, friendnum, filenum, TOX_FILE_CONTROL_CANCEL, 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: invalid file path."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: invalid file path.");
free(file_path);
return; return;
} }
} }
@ -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); snprintf(ft->file_name, sizeof(ft->file_name), "%s", filename);
tox_file_get_file_id(m, friendnum, filenum, ft->file_id, NULL); tox_file_get_file_id(m, friendnum, filenum, ft->file_id, NULL);
free(file_path);
if (self->active_box != -1) { if (self->active_box != -1) {
box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS | user_settings->bell_on_filetrans, box_notify2(self, transfer_pending, NT_WNDALERT_0 | NT_NOFOCUS | user_settings->bell_on_filetrans,
self->active_box, "Incoming file: %s", filename); self->active_box, "Incoming file: %s", filename);

View File

@ -81,10 +81,18 @@ void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t l
strcat(prog_line, "-"); strcat(prog_line, "-");
} }
char full_line[strlen(pct_str) + NUM_PROG_MARKS + strlen(bps_str) + 7]; size_t line_buf_size = 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); 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); line_info_set(self, line_id, full_line);
free(full_line);
} }
static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft) static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)

View File

@ -187,13 +187,21 @@ static int save_blocklist(char *path)
return 0; return 0;
} }
char temp_path[strlen(path) + strlen(TEMP_BLOCKLIST_EXT) + 1]; size_t temp_buf_size = strlen(path) + strlen(TEMP_BLOCKLIST_EXT) + 1;
snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_BLOCKLIST_EXT); char *temp_path = malloc(temp_buf_size);
if (temp_path == NULL) {
free(data);
return -1;
}
snprintf(temp_path, temp_buf_size, "%s%s", path, TEMP_BLOCKLIST_EXT);
FILE *fp = fopen(temp_path, "wb"); FILE *fp = fopen(temp_path, "wb");
if (fp == NULL) { if (fp == NULL) {
free(data); free(data);
free(temp_path);
return -1; return -1;
} }
@ -201,6 +209,7 @@ static int save_blocklist(char *path)
fprintf(stderr, "Failed to write blocklist data.\n"); fprintf(stderr, "Failed to write blocklist data.\n");
fclose(fp); fclose(fp);
free(data); free(data);
free(temp_path);
return -1; return -1;
} }
@ -208,9 +217,12 @@ static int save_blocklist(char *path)
free(data); free(data);
if (rename(temp_path, path) != 0) { if (rename(temp_path, path) != 0) {
free(temp_path);
return -1; return -1;
} }
free(temp_path);
return 0; return 0;
} }
@ -235,15 +247,22 @@ int load_blocklist(char *path)
return -1; return -1;
} }
char data[len]; char *data = malloc(len);
if (data == NULL) {
fclose(fp);
return -1;
}
if (fread(data, len, 1, fp) != 1) { if (fread(data, len, 1, fp) != 1) {
fclose(fp); fclose(fp);
free(data);
return -1; return -1;
} }
if (len % sizeof(BlockedFriend) != 0) { if (len % sizeof(BlockedFriend) != 0) {
fclose(fp); fclose(fp);
free(data);
return -1; return -1;
} }
@ -251,9 +270,7 @@ int load_blocklist(char *path)
Blocked.max_idx = num; Blocked.max_idx = num;
realloc_blocklist(num); realloc_blocklist(num);
int i; for (int i = 0; i < num; ++i) {
for (i = 0; i < num; ++i) {
BlockedFriend tmp; BlockedFriend tmp;
memset(&tmp, 0, sizeof(BlockedFriend)); memset(&tmp, 0, sizeof(BlockedFriend));
memset(&Blocked.list[i], 0, sizeof(BlockedFriend)); memset(&Blocked.list[i], 0, sizeof(BlockedFriend));
@ -279,6 +296,8 @@ int load_blocklist(char *path)
} }
fclose(fp); fclose(fp);
free(data);
sort_blocklist_index(); sort_blocklist_index();
return 0; return 0;

View File

@ -476,45 +476,79 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
nick[nick_len] = '\0'; nick[nick_len] = '\0';
size_t data_file_len = strlen(DATA_FILE); size_t data_file_len = strlen(DATA_FILE);
char dir[data_file_len + 1]; char *dir = malloc(data_file_len + 1);
if (dir == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory.");
return;
}
size_t dir_len = get_base_dir(DATA_FILE, data_file_len, dir); size_t dir_len = get_base_dir(DATA_FILE, data_file_len, dir);
#ifdef QRPNG #ifdef QRPNG
if (argc == 0) { if (argc == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'");
free(dir);
return; return;
} else if (!strcmp(argv[1], "txt")) { } else if (!strcmp(argv[1], "txt")) {
#endif /* QRPNG */ #endif /* QRPNG */
char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1]; size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1;
snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT); char *qr_path = malloc(qr_path_buf_size);
if (qr_path == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
free(dir);
return;
}
snprintf(qr_path, qr_path_buf_size, "%s%s%s", dir, nick, QRCODE_FILENAME_EXT);
if (ID_to_QRcode_txt(id_string, qr_path) == -1) { if (ID_to_QRcode_txt(id_string, qr_path) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
free(dir);
free(qr_path);
return; return;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
free(qr_path);
#ifdef QRPNG #ifdef QRPNG
} else if (!strcmp(argv[1], "png")) { } else if (!strcmp(argv[1], "png")) {
char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT_PNG) + 1]; size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT_PNG) + 1;
snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT_PNG); char *qr_path = malloc(qr_path_buf_size);
if (qr_path == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
free(dir);
return;
}
snprintf(qr_path, qr_path_buf_size, "%s%s%s", dir, nick, QRCODE_FILENAME_EXT_PNG);
if (ID_to_QRcode_png(id_string, qr_path) == -1) { if (ID_to_QRcode_png(id_string, qr_path) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
free(dir);
free(qr_path);
return; return;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
free(qr_path);
} else { } else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]);
free(dir);
return; return;
} }
#endif /* QRPNG */ #endif /* QRPNG */
free(dir);
} }
#endif /* QRCODE */ #endif /* QRCODE */

View File

@ -50,16 +50,20 @@ void clear_screen(void)
void hst_to_net(uint8_t *num, uint16_t numbytes) void hst_to_net(uint8_t *num, uint16_t numbytes)
{ {
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
uint32_t i; uint8_t *buff = malloc(numbytes);
uint8_t buff[numbytes];
for (i = 0; i < numbytes; ++i) { if (buff == NULL) {
return;
}
for (uint32_t i = 0; i < numbytes; ++i) {
buff[i] = num[numbytes - i - 1]; buff[i] = num[numbytes - i - 1];
} }
memcpy(num, buff, numbytes); memcpy(num, buff, numbytes);
free(buff);
#endif #endif
return;
} }
time_t get_unix_time(void) time_t get_unix_time(void)
@ -527,20 +531,31 @@ off_t file_size(const char *path)
return st.st_size; return st.st_size;
} }
/* compares the first size bytes of fp to signature. /* Compares the first size bytes of fp to signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error. *
* Returns 0 if they are the same
On success this function will seek back to the beginning of fp */ * Returns 1 if they differ
* Returns -1 on error.
*
* On success this function will seek back to the beginning of fp.
*/
int check_file_signature(const unsigned char *signature, size_t size, FILE *fp) int check_file_signature(const unsigned char *signature, size_t size, FILE *fp)
{ {
char buf[size]; char *buf = malloc(size);
if (buf == NULL) {
return -1;
}
if (fread(buf, size, 1, fp) != 1) { if (fread(buf, size, 1, fp) != 1) {
free(buf);
return -1; return -1;
} }
int ret = memcmp(signature, buf, size); int ret = memcmp(signature, buf, size);
free(buf);
if (fseek(fp, 0L, SEEK_SET) == -1) { if (fseek(fp, 0L, SEEK_SET) == -1) {
return -1; return -1;
} }
@ -603,3 +618,45 @@ bool is_ip6_address(const char *address)
return num_colons > 1 && num_colons < 8; return num_colons > 1 && num_colons < 8;
} }
/*
* Frees `length` members of pointer array `arr` and frees `arr`.
*/
void free_ptr_array(void **arr, size_t length)
{
if (arr == NULL) {
return;
}
for (size_t i = 0; i < length; ++i) {
free(arr[i]);
}
free(arr);
}
/*
* Returns a new array of `length` pointers of size `ptr_size`. Each pointer is allocated `bytes` bytes.
* Returns NULL on failure.
*
* The caller is responsible for freeing the array with `free_ptr_array`.
*/
void **malloc_ptr_array(size_t length, size_t bytes, size_t ptr_size)
{
void **arr = malloc(length * ptr_size);
if (arr == NULL) {
return NULL;
}
for (size_t i = 0; i < length; ++i) {
arr[i] = malloc(bytes);
if (arr[i] == NULL) {
free_ptr_array(arr, i);
return NULL;
}
}
return arr;
}

View File

@ -169,10 +169,14 @@ File_Type file_type(const char *path);
/* returns file size. If file doesn't exist returns 0. */ /* returns file size. If file doesn't exist returns 0. */
off_t file_size(const char *path); off_t file_size(const char *path);
/* compares the first size bytes of fp and signature. /* Compares the first size bytes of fp to signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error. *
* Returns 0 if they are the same
On success this function will seek back to the beginning of fp */ * Returns 1 if they differ
* Returns -1 on error.
*
* On success this function will seek back to the beginning of fp.
*/
int check_file_signature(const unsigned char *signature, size_t size, FILE *fp); int check_file_signature(const unsigned char *signature, size_t size, FILE *fp);
/* sets window title in tab bar. */ /* sets window title in tab bar. */
@ -190,4 +194,18 @@ bool is_ip4_address(const char *address);
*/ */
bool is_ip6_address(const char *address); bool is_ip6_address(const char *address);
/*
* Frees `length` members of pointer array `arr` and frees `arr`.
*/
void free_ptr_array(void **arr, size_t length);
/*
* Returns a new array of `length` pointers of size `ptr_size`. Each pointer is allocated `bytes` bytes.
* Returns NULL on failure.
*
* The caller is responsible for freeing the array with `free_ptr_array`.
*/
void **malloc_ptr_array(size_t length, size_t bytes, size_t ptr_size);
#endif /* MISC_TOOLS_H */ #endif /* MISC_TOOLS_H */

View File

@ -138,12 +138,18 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile)
real_width = (qr_obj->width + BORDER_LEN * 2) * SQUARE_SIZE; real_width = (qr_obj->width + BORDER_LEN * 2) * SQUARE_SIZE;
size_t row_size = real_width * 4; size_t row_size = real_width * 4;
unsigned char row[row_size]; unsigned char *row = malloc(row_size);
if (row == NULL) {
fclose(fp);
return -1;
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) { if (png_ptr == NULL) {
fclose(fp); fclose(fp);
free(row);
QRcode_free(qr_obj); QRcode_free(qr_obj);
return -1; return -1;
} }
@ -152,12 +158,14 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile)
if (info_ptr == NULL) { if (info_ptr == NULL) {
fclose(fp); fclose(fp);
free(row);
QRcode_free(qr_obj); QRcode_free(qr_obj);
return -1; return -1;
} }
if (setjmp(png_jmpbuf(png_ptr))) { if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp); fclose(fp);
free(row);
QRcode_free(qr_obj); QRcode_free(qr_obj);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
return -1; return -1;
@ -206,10 +214,12 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile)
png_write_row(png_ptr, row); png_write_row(png_ptr, row);
} }
free(row);
fclose(fp);
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
QRcode_free(qr_obj); QRcode_free(qr_obj);
return 0; return 0;

View File

@ -362,7 +362,13 @@ static void load_conferences(Tox *m)
return; return;
} }
uint32_t chatlist[num_chats]; uint32_t *chatlist = malloc(num_chats * sizeof(uint32_t));
if (chatlist == NULL) {
fprintf(stderr, "malloc() failed in load_conferences()\n");
return;
}
tox_conference_get_chatlist(m, chatlist); tox_conference_get_chatlist(m, chatlist);
for (size_t i = 0; i < num_chats; ++i) { for (size_t i = 0; i < num_chats; ++i) {
@ -402,6 +408,8 @@ static void load_conferences(Tox *m)
continue; continue;
} }
} }
free(chatlist);
} }
/* return length of password on success, 0 on failure */ /* return length of password on success, 0 on failure */
@ -567,12 +575,19 @@ int store_data(Tox *m, const char *path)
return -1; return -1;
} }
char temp_path[strlen(path) + strlen(TEMP_PROFILE_EXT) + 1]; size_t temp_buf_size = strlen(path) + strlen(TEMP_PROFILE_EXT) + 1;
snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_PROFILE_EXT); char *temp_path = malloc(temp_buf_size);
if (temp_path == NULL) {
return -1;
}
snprintf(temp_path, temp_buf_size, "%s%s", path, TEMP_PROFILE_EXT);
FILE *fp = fopen(temp_path, "wb"); FILE *fp = fopen(temp_path, "wb");
if (fp == NULL) { if (fp == NULL) {
free(temp_path);
return -1; return -1;
} }
@ -580,6 +595,7 @@ int store_data(Tox *m, const char *path)
char *data = malloc(data_len * sizeof(char)); char *data = malloc(data_len * sizeof(char));
if (data == NULL) { if (data == NULL) {
free(temp_path);
fclose(fp); fclose(fp);
return -1; return -1;
} }
@ -592,6 +608,7 @@ int store_data(Tox *m, const char *path)
if (enc_data == NULL) { if (enc_data == NULL) {
fclose(fp); fclose(fp);
free(temp_path);
free(data); free(data);
return -1; return -1;
} }
@ -603,6 +620,7 @@ int store_data(Tox *m, const char *path)
if (err != TOX_ERR_ENCRYPTION_OK) { if (err != TOX_ERR_ENCRYPTION_OK) {
fprintf(stderr, "tox_pass_encrypt() failed with error %d\n", err); fprintf(stderr, "tox_pass_encrypt() failed with error %d\n", err);
fclose(fp); fclose(fp);
free(temp_path);
free(data); free(data);
free(enc_data); free(enc_data);
return -1; return -1;
@ -611,6 +629,7 @@ int store_data(Tox *m, const char *path)
if (fwrite(enc_data, enc_len, 1, fp) != 1) { if (fwrite(enc_data, enc_len, 1, fp) != 1) {
fprintf(stderr, "Failed to write profile data.\n"); fprintf(stderr, "Failed to write profile data.\n");
fclose(fp); fclose(fp);
free(temp_path);
free(data); free(data);
free(enc_data); free(enc_data);
return -1; return -1;
@ -621,6 +640,7 @@ int store_data(Tox *m, const char *path)
if (fwrite(data, data_len, 1, fp) != 1) { if (fwrite(data, data_len, 1, fp) != 1) {
fprintf(stderr, "Failed to write profile data.\n"); fprintf(stderr, "Failed to write profile data.\n");
fclose(fp); fclose(fp);
free(temp_path);
free(data); free(data);
return -1; return -1;
} }
@ -630,9 +650,12 @@ int store_data(Tox *m, const char *path)
free(data); free(data);
if (rename(temp_path, path) != 0) { if (rename(temp_path, path) != 0) {
free(temp_path);
return -1; return -1;
} }
free(temp_path);
return 0; return 0;
} }
@ -719,13 +742,22 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
if (len == 0) { if (len == 0) {
fclose(fp); fclose(fp);
exit_toxic_err("failed in load_tox", FATALERR_FILEOP); exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
return NULL;
} }
char data[len]; char *data = malloc(len);
if (fread(data, sizeof(data), 1, fp) != 1) { if (data == NULL) {
fclose(fp); fclose(fp);
exit_toxic_err("failed in load_tox", FATALERR_MEMORY);
return NULL;
}
if (fread(data, len, 1, fp) != 1) {
fclose(fp);
free(data);
exit_toxic_err("failed in load_tox", FATALERR_FILEOP); exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
return NULL;
} }
bool is_encrypted = tox_is_data_encrypted((uint8_t *) data); bool is_encrypted = tox_is_data_encrypted((uint8_t *) data);
@ -733,7 +765,9 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
/* attempt to encrypt an already encrypted data file */ /* attempt to encrypt an already encrypted data file */
if (arg_opts.encrypt_data && is_encrypted) { if (arg_opts.encrypt_data && is_encrypted) {
fclose(fp); fclose(fp);
free(data);
exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT); exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT);
return NULL;
} }
if (arg_opts.unencrypt_data && is_encrypted) { if (arg_opts.unencrypt_data && is_encrypted) {
@ -756,7 +790,13 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
} }
size_t plain_len = len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; size_t plain_len = len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
char plain[plain_len]; char *plain = malloc(plain_len); // must be freed after tox_new()
if (plain == NULL) {
fclose(fp);
exit_toxic_err("failed in load_tox", FATALERR_MEMORY);
return NULL;
}
while (true) { while (true) {
fflush(stdout); // Flush before prompts so the user sees the question/message fflush(stdout); // Flush before prompts so the user sees the question/message
@ -771,6 +811,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
if (strcasecmp(user_password.pass, "q") == 0) { if (strcasecmp(user_password.pass, "q") == 0) {
fclose(fp); fclose(fp);
free(plain);
exit(0); exit(0);
} }
@ -794,6 +835,8 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
if (m == NULL) { if (m == NULL) {
fclose(fp); fclose(fp);
free(data);
free(plain);
return NULL; return NULL;
} }
@ -805,9 +848,14 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
pweval = 0; pweval = 0;
} else { } else {
fclose(fp); fclose(fp);
free(data);
free(plain);
exit_toxic_err("tox_pass_decrypt() failed", pwerr); exit_toxic_err("tox_pass_decrypt() failed", pwerr);
return NULL;
} }
} }
free(plain);
} else { /* data is not encrypted */ } else { /* data is not encrypted */
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(tox_opts, (uint8_t *) data, len); tox_options_set_savedata_data(tox_opts, (uint8_t *) data, len);
@ -816,14 +864,17 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
if (m == NULL) { if (m == NULL) {
fclose(fp); fclose(fp);
free(data);
return NULL; return NULL;
} }
} }
fclose(fp); fclose(fp);
free(data);
} else { /* Data file does not/should not exist */ } else { /* Data file does not/should not exist */
if (file_exists(data_path)) { if (file_exists(data_path)) {
exit_toxic_err("failed in load_tox", FATALERR_FILEOP); exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
return NULL;
} }
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_NONE); tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_NONE);
@ -836,6 +887,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
if (store_data(m, data_path) == -1) { if (store_data(m, data_path) == -1) {
exit_toxic_err("failed in load_tox", FATALERR_FILEOP); exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
return NULL;
} }
} }
@ -1207,38 +1259,60 @@ static void parse_args(int argc, char *argv[])
#define OLD_DATA_BLOCKLIST_NAME "data-blocklist" #define OLD_DATA_BLOCKLIST_NAME "data-blocklist"
static int rename_old_profile(const char *user_config_dir) static int rename_old_profile(const char *user_config_dir)
{ {
char old_data_file[strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(OLD_DATA_NAME) + 1]; size_t old_buf_size = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(OLD_DATA_NAME) + 1;
snprintf(old_data_file, sizeof(old_data_file), "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_NAME); char *old_data_file = malloc(old_buf_size);
if (old_data_file == NULL) {
return -1;
}
snprintf(old_data_file, old_buf_size, "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_NAME);
if (!file_exists(old_data_file)) { if (!file_exists(old_data_file)) {
free(old_data_file);
return 0; return 0;
} }
if (file_exists(DATA_FILE)) { if (file_exists(DATA_FILE)) {
free(old_data_file);
return 0; return 0;
} }
if (rename(old_data_file, DATA_FILE) != 0) { if (rename(old_data_file, DATA_FILE) != 0) {
free(old_data_file);
return -1; return -1;
} }
free(old_data_file);
queue_init_message("Data file has been moved to %s", DATA_FILE); queue_init_message("Data file has been moved to %s", DATA_FILE);
char old_data_blocklist[strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(OLD_DATA_BLOCKLIST_NAME) + 1]; size_t old_block_buf_size = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(OLD_DATA_BLOCKLIST_NAME) + 1;
char *old_data_blocklist = malloc(old_block_buf_size);
if (old_data_blocklist == NULL) {
return -1;
}
snprintf(old_data_blocklist, sizeof(old_data_blocklist), "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_BLOCKLIST_NAME); snprintf(old_data_blocklist, sizeof(old_data_blocklist), "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_BLOCKLIST_NAME);
if (!file_exists(old_data_blocklist)) { if (!file_exists(old_data_blocklist)) {
free(old_data_blocklist);
return 0; return 0;
} }
if (file_exists(BLOCK_FILE)) { if (file_exists(BLOCK_FILE)) {
free(old_data_blocklist);
return 0; return 0;
} }
if (rename(old_data_blocklist, BLOCK_FILE) != 0) { if (rename(old_data_blocklist, BLOCK_FILE) != 0) {
free(old_data_blocklist);
return -1; return -1;
} }
free(old_data_blocklist);
return 0; return 0;
} }