From fe6a7074eae8221cbf8178b358dacf66591fd135 Mon Sep 17 00:00:00 2001 From: jfreegman Date: Mon, 20 Nov 2017 07:02:56 -0500 Subject: [PATCH] Dynamically allocate audio calls structure This fixes a bug that caused a segfault when attempting to call a friend with a friend number above the MAX_CALLS limit --- src/audio_call.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- src/audio_call.h | 8 +++++--- src/friendlist.c | 8 ++++++++ src/video_call.c | 2 +- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/audio_call.c b/src/audio_call.c index 4009d42..abef6a6 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -133,8 +133,6 @@ ToxAV *init_audio(ToxWindow *self, Tox *tox) CallControl.video_frame_duration = 0; #endif /* VIDEO */ - memset(CallControl.calls, 0, sizeof(CallControl.calls)); - if ( !CallControl.av ) { CallControl.audio_errors |= ae_StartingCoreAudio; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV"); @@ -160,7 +158,7 @@ void terminate_audio() { int i; - for (i = 0; i < MAX_CALLS; ++i) + for (i = 0; i < CallControl.max_calls; ++i) stop_transmission(&CallControl.calls[i], i); if ( CallControl.av ) @@ -900,3 +898,47 @@ void stop_current_call(ToxWindow *self) CallControl.pending_call = false; } + +/** + * Reallocates the Calls list according to n. + */ +static void realloc_calls(uint32_t n) +{ + if (n <= 0) { + free(CallControl.calls); + CallControl.calls = NULL; + return; + } + + Call *temp = realloc(CallControl.calls, n * sizeof(Call)); + + if (temp == NULL) { + exit_toxic_err("failed in realloc_calls", FATALERR_MEMORY); + } + + CallControl.calls = temp; +} + +/** + * Inits the call structure for a given friend. Called when a friend is added to the friends list. + * Index must be equivalent to the friend's friendlist index. + */ +void init_friend_AV(uint32_t index) +{ + realloc_calls(CallControl.max_calls + 1); + memset(&CallControl.calls[CallControl.max_calls], 0, sizeof(Call)); + + if (index == CallControl.max_calls) { + ++CallControl.max_calls; + } +} + +/** + * Deletes the call structure for a given friend. Called when a friend is deleted from the friends list. + * Index must be equivalent to the friend's friendlist index. + */ +void del_friend_AV(uint32_t index) +{ + realloc_calls(index); + CallControl.max_calls = index; +} diff --git a/src/audio_call.h b/src/audio_call.h index 0431e4f..8ceb522 100644 --- a/src/audio_call.h +++ b/src/audio_call.h @@ -27,8 +27,6 @@ #include "audio_device.h" -#define MAX_CALLS 10 - typedef enum _AudioError { ae_None = 0, ae_StartingCaptureDevice = 1 << 0, @@ -65,7 +63,9 @@ struct CallControl { ToxAV *av; ToxWindow *prompt; - Call calls[MAX_CALLS]; + Call *calls; + uint32_t max_calls; + uint32_t call_state; bool pending_call; bool audio_enabled; @@ -89,5 +89,7 @@ void terminate_audio(); int start_transmission(ToxWindow *self, Call *call); int stop_transmission(Call *call, uint32_t friend_number); void stop_current_call(ToxWindow *self); +void init_friend_AV(uint32_t index); +void del_friend_AV(uint32_t index); #endif /* AUDIO_CALL_H */ diff --git a/src/friendlist.c b/src/friendlist.c index 0e05730..6ac2605 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -466,6 +466,10 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort) if (sort) sort_friendlist_index(); +#ifdef AUDIO + init_friend_AV(i); +#endif + return; } } @@ -605,6 +609,10 @@ static void delete_friend(Tox *m, uint32_t f_num) Friends.max_idx = i; realloc_friends(i); +#ifdef AUDIO + del_friend_AV(i); +#endif + /* make sure num_selected stays within Friends.num_friends range */ if (Friends.num_friends && Friends.num_selected == Friends.num_friends) --Friends.num_selected; diff --git a/src/video_call.c b/src/video_call.c index c04f943..10e4090 100644 --- a/src/video_call.c +++ b/src/video_call.c @@ -83,7 +83,7 @@ void terminate_video() { int i; - for (i = 0; i < MAX_CALLS; ++i) { + for (i = 0; i < CallControl.max_calls; ++i) { Call *this_call = &CallControl.calls[i]; stop_video_transmission(this_call, i);