diff --git a/Makefile b/Makefile index 4326556..8f6b0f3 100644 --- a/Makefile +++ b/Makefile @@ -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} diff --git a/src/audio_device.c b/src/audio_device.c index 200bf52..ebc5d6e 100644 --- a/src/audio_device.c +++ b/src/audio_device.c @@ -301,6 +301,16 @@ 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); @@ -308,13 +318,12 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t *device_idx 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); } @@ -425,10 +434,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 { diff --git a/src/autocomplete.c b/src/autocomplete.c index 2333fef..92175e2 100644 --- a/src/autocomplete.c +++ b/src/autocomplete.c @@ -38,20 +38,32 @@ #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. @@ -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. */ -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) { @@ -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. */ -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; @@ -161,7 +171,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 */ @@ -177,15 +194,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; @@ -365,7 +385,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); diff --git a/src/avatars.c b/src/avatars.c index 6e52786..d20f561 100644 --- a/src/avatars.c +++ b/src/avatars.c @@ -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); } diff --git a/src/chat.c b/src/chat.c index 00f1262..1f1f6b4 100644 --- a/src/chat.c +++ b/src/chat.c @@ -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); } @@ -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; } @@ -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'; } @@ -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; } } @@ -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); diff --git a/src/file_transfers.c b/src/file_transfers.c index 26a6dc8..82df435 100644 --- a/src/file_transfers.c +++ b/src/file_transfers.c @@ -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) diff --git a/src/friendlist.c b/src/friendlist.c index f5b680d..a7122ae 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -187,13 +187,21 @@ static int save_blocklist(char *path) return 0; } - char temp_path[strlen(path) + strlen(TEMP_BLOCKLIST_EXT) + 1]; - snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_BLOCKLIST_EXT); + size_t temp_buf_size = strlen(path) + strlen(TEMP_BLOCKLIST_EXT) + 1; + 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"); if (fp == NULL) { free(data); + free(temp_path); return -1; } @@ -201,6 +209,7 @@ static int save_blocklist(char *path) fprintf(stderr, "Failed to write blocklist data.\n"); fclose(fp); free(data); + free(temp_path); return -1; } @@ -208,9 +217,12 @@ static int save_blocklist(char *path) free(data); if (rename(temp_path, path) != 0) { + free(temp_path); return -1; } + free(temp_path); + return 0; } @@ -235,15 +247,22 @@ int load_blocklist(char *path) return -1; } - char data[len]; + char *data = malloc(len); + + if (data == NULL) { + fclose(fp); + return -1; + } if (fread(data, len, 1, fp) != 1) { fclose(fp); + free(data); return -1; } if (len % sizeof(BlockedFriend) != 0) { fclose(fp); + free(data); return -1; } @@ -251,9 +270,7 @@ int load_blocklist(char *path) Blocked.max_idx = num; realloc_blocklist(num); - int i; - - for (i = 0; i < num; ++i) { + for (int i = 0; i < num; ++i) { BlockedFriend tmp; memset(&tmp, 0, sizeof(BlockedFriend)); memset(&Blocked.list[i], 0, sizeof(BlockedFriend)); @@ -279,6 +296,8 @@ int load_blocklist(char *path) } fclose(fp); + free(data); + sort_blocklist_index(); return 0; diff --git a/src/global_commands.c b/src/global_commands.c index 265a7bd..13ab112 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -476,45 +476,79 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA nick[nick_len] = '\0'; 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); #ifdef QRPNG if (argc == 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'"); + free(dir); return; } else if (!strcmp(argv[1], "txt")) { #endif /* QRPNG */ - char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1]; - snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT); + size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1; + 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) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); + free(dir); + free(qr_path); return; } 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 } else if (!strcmp(argv[1], "png")) { - char qr_path[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); + size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT_PNG) + 1; + 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) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code."); + free(dir); + free(qr_path); return; } 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 { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]); + free(dir); return; } #endif /* QRPNG */ + + free(dir); } #endif /* QRCODE */ diff --git a/src/misc_tools.c b/src/misc_tools.c index 953e863..b0b8841 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -50,16 +50,20 @@ void clear_screen(void) void hst_to_net(uint8_t *num, uint16_t numbytes) { #ifndef WORDS_BIGENDIAN - uint32_t i; - uint8_t buff[numbytes]; + uint8_t *buff = malloc(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]; } memcpy(num, buff, numbytes); + + free(buff); #endif - return; } time_t get_unix_time(void) @@ -527,20 +531,31 @@ off_t file_size(const char *path) return st.st_size; } -/* compares the first size bytes of fp to signature. - Returns 0 if they are the same, 1 if they differ, and -1 on error. - - On success this function will seek back to the beginning of fp */ +/* 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. + */ 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) { + free(buf); return -1; } int ret = memcmp(signature, buf, size); + free(buf); + if (fseek(fp, 0L, SEEK_SET) == -1) { return -1; } @@ -603,3 +618,45 @@ bool is_ip6_address(const char *address) 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; +} diff --git a/src/misc_tools.h b/src/misc_tools.h index 551f62b..26620d3 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -169,10 +169,14 @@ File_Type file_type(const char *path); /* returns file size. If file doesn't exist returns 0. */ off_t file_size(const char *path); -/* compares the first size bytes of fp and signature. - Returns 0 if they are the same, 1 if they differ, and -1 on error. - - On success this function will seek back to the beginning of fp */ +/* 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. + */ int check_file_signature(const unsigned char *signature, size_t size, FILE *fp); /* sets window title in tab bar. */ @@ -190,4 +194,18 @@ bool is_ip4_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 */ diff --git a/src/qr_code.c b/src/qr_code.c index 102ece9..da9286e 100644 --- a/src/qr_code.c +++ b/src/qr_code.c @@ -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; 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); if (png_ptr == NULL) { fclose(fp); + free(row); QRcode_free(qr_obj); return -1; } @@ -152,12 +158,14 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile) if (info_ptr == NULL) { fclose(fp); + free(row); QRcode_free(qr_obj); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { fclose(fp); + free(row); QRcode_free(qr_obj); png_destroy_write_struct(&png_ptr, &info_ptr); return -1; @@ -206,10 +214,12 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile) png_write_row(png_ptr, row); } + free(row); + fclose(fp); + png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); QRcode_free(qr_obj); return 0; diff --git a/src/toxic.c b/src/toxic.c index 4b7c7d6..15d7f79 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -362,7 +362,13 @@ static void load_conferences(Tox *m) 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); for (size_t i = 0; i < num_chats; ++i) { @@ -402,6 +408,8 @@ static void load_conferences(Tox *m) continue; } } + + free(chatlist); } /* return length of password on success, 0 on failure */ @@ -567,12 +575,19 @@ int store_data(Tox *m, const char *path) return -1; } - char temp_path[strlen(path) + strlen(TEMP_PROFILE_EXT) + 1]; - snprintf(temp_path, sizeof(temp_path), "%s%s", path, TEMP_PROFILE_EXT); + size_t temp_buf_size = strlen(path) + strlen(TEMP_PROFILE_EXT) + 1; + 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"); if (fp == NULL) { + free(temp_path); return -1; } @@ -580,6 +595,7 @@ int store_data(Tox *m, const char *path) char *data = malloc(data_len * sizeof(char)); if (data == NULL) { + free(temp_path); fclose(fp); return -1; } @@ -592,6 +608,7 @@ int store_data(Tox *m, const char *path) if (enc_data == NULL) { fclose(fp); + free(temp_path); free(data); return -1; } @@ -603,6 +620,7 @@ int store_data(Tox *m, const char *path) if (err != TOX_ERR_ENCRYPTION_OK) { fprintf(stderr, "tox_pass_encrypt() failed with error %d\n", err); fclose(fp); + free(temp_path); free(data); free(enc_data); return -1; @@ -611,6 +629,7 @@ int store_data(Tox *m, const char *path) if (fwrite(enc_data, enc_len, 1, fp) != 1) { fprintf(stderr, "Failed to write profile data.\n"); fclose(fp); + free(temp_path); free(data); free(enc_data); return -1; @@ -621,6 +640,7 @@ int store_data(Tox *m, const char *path) if (fwrite(data, data_len, 1, fp) != 1) { fprintf(stderr, "Failed to write profile data.\n"); fclose(fp); + free(temp_path); free(data); return -1; } @@ -630,9 +650,12 @@ int store_data(Tox *m, const char *path) free(data); if (rename(temp_path, path) != 0) { + free(temp_path); return -1; } + free(temp_path); + return 0; } @@ -719,13 +742,22 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New if (len == 0) { fclose(fp); 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); + 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); + return NULL; } 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 */ if (arg_opts.encrypt_data && is_encrypted) { fclose(fp); + free(data); exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT); + return NULL; } 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; - 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) { 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) { fclose(fp); + free(plain); exit(0); } @@ -794,6 +835,8 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New if (m == NULL) { fclose(fp); + free(data); + free(plain); return NULL; } @@ -805,9 +848,14 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New pweval = 0; } else { fclose(fp); + free(data); + free(plain); exit_toxic_err("tox_pass_decrypt() failed", pwerr); + return NULL; } } + + free(plain); } else { /* data is not encrypted */ tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE); 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) { fclose(fp); + free(data); return NULL; } } fclose(fp); + free(data); } else { /* Data file does not/should not exist */ if (file_exists(data_path)) { exit_toxic_err("failed in load_tox", FATALERR_FILEOP); + return NULL; } 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) { 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" 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]; - snprintf(old_data_file, sizeof(old_data_file), "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_NAME); + size_t old_buf_size = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(OLD_DATA_NAME) + 1; + 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)) { + free(old_data_file); return 0; } if (file_exists(DATA_FILE)) { + free(old_data_file); return 0; } if (rename(old_data_file, DATA_FILE) != 0) { + free(old_data_file); return -1; } + free(old_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); if (!file_exists(old_data_blocklist)) { + free(old_data_blocklist); return 0; } if (file_exists(BLOCK_FILE)) { + free(old_data_blocklist); return 0; } if (rename(old_data_blocklist, BLOCK_FILE) != 0) { + free(old_data_blocklist); return -1; } + free(old_data_blocklist); + return 0; }