Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[config] Fix handling of hidden modes setting
The make_hidden_modes_string() function claims to return const string,
but that is true only as an exception to the rule. Since the callers of
the function do not release dynamic memory, this leads to leakage. Also
if no mode is hidden, request to unhide something least to that mode
getting hidden and hiding something already hidden returns NULL which
is rather unintuitive.

Fix make_hidden_modes_string() and make all callers of it to release
dynamically reserved memory / deal with possible null return value.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Jul 7, 2016
1 parent ddc2942 commit 20abe60
Showing 1 changed file with 65 additions and 38 deletions.
103 changes: 65 additions & 38 deletions src/usb_moded-config.c
Expand Up @@ -416,75 +416,102 @@ set_config_result_t set_mode_setting(const char *mode)

/* Builds the string used for hidden modes, when hide set to one builds the
new string of hidden modes when adding one, otherwise it will remove one */
static const char * make_hidden_modes_string(const char *hidden, int hide)
static char * make_hidden_modes_string(const char *mode_name, int hide)
{
GString *modelist_str;
char *hidden_modes_list;
gchar **hidden_mode_split;
char *hidden_new = 0;
char *hidden_old = 0;
gchar **hidden_arr = 0;
GString *hidden_tmp = 0;
int i;


hidden_modes_list = get_hidden_modes();
if(hidden_modes_list)
{
hidden_mode_split = g_strsplit(hidden_modes_list, ",", 0);
}
else
/* Get current comma separated list of hidden modes */
hidden_old = get_hidden_modes();
if(!hidden_old)
{
/* no hidden modes yet. So just return the original string */
return hidden;
hidden_old = g_strdup("");
}

modelist_str = g_string_new(NULL);
hidden_arr = g_strsplit(hidden_old, ",", 0);

for(i = 0; hidden_mode_split[i] != NULL; i++)
hidden_tmp = g_string_new(NULL);

for(i = 0; hidden_arr[i] != NULL; i++)
{
if(strlen(hidden_mode_split[i]) == 0)
continue;
if(!strcmp(hidden_mode_split[i], hidden))
{
/* if hiding a mode that is already hidden do nothing */
if(hide)
return(NULL);
if(!hide)
continue;
}
if(strlen(modelist_str->str) != 0)
modelist_str = g_string_append(modelist_str, ",");
modelist_str = g_string_append(modelist_str, hidden_mode_split[i]);
if(strlen(hidden_arr[i]) == 0)
{
/* Skip any empty strings */
continue;
}

if(!strcmp(hidden_arr[i], mode_name))
{
/* When unhiding, just skip all matching entries */
if(!hide)
continue;

/* When hiding, keep the 1st match and ignore the rest */
hide = 0;
}

if(hidden_tmp->len > 0)
hidden_tmp = g_string_append(hidden_tmp, ",");
hidden_tmp = g_string_append(hidden_tmp, hidden_arr[i]);
}

if(hide)
{
if(strlen(modelist_str->str) != 0)
modelist_str = g_string_append(modelist_str, ",");
modelist_str = g_string_append(modelist_str, hidden);
/* Adding a hidden mode and no matching entry was found */
if(hidden_tmp->len > 0)
hidden_tmp = g_string_append(hidden_tmp, ",");
hidden_tmp = g_string_append(hidden_tmp, mode_name);
}

g_strfreev(hidden_mode_split);
return(g_string_free(modelist_str, FALSE));

hidden_new = g_string_free(hidden_tmp, FALSE), hidden_tmp = 0;

g_strfreev(hidden_arr), hidden_arr = 0;

g_free(hidden_old), hidden_old = 0;

return hidden_new;
}

set_config_result_t set_hide_mode_setting(const char *mode)
{
set_config_result_t ret;
set_config_result_t ret = SET_CONFIG_UNCHANGED;

char *hidden_modes = make_hidden_modes_string(mode, 1);

if( hidden_modes ) {
ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes);
}

ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, make_hidden_modes_string(mode, 1));
if(ret == SET_CONFIG_UPDATED) {
send_hidden_modes_signal();
send_supported_modes_signal();
}

g_free(hidden_modes);

return(ret);
}

set_config_result_t set_unhide_mode_setting(const char *mode)
{
set_config_result_t ret;
set_config_result_t ret = SET_CONFIG_UNCHANGED;

char *hidden_modes = make_hidden_modes_string(mode, 0);

if( hidden_modes ) {
ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes);
}

ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, make_hidden_modes_string(mode, 0));
if(ret == SET_CONFIG_UPDATED) {
send_hidden_modes_signal();
send_supported_modes_signal();
}

g_free(hidden_modes);

return(ret);
}

Expand Down

0 comments on commit 20abe60

Please sign in to comment.