gkeyfilesettingsbackend: Handle long keys when converting paths

Previously, the code in `convert_path()` could not handle keys longer
than `G_MAXINT`, and would overflow if that was exceeded.

Convert the code to use `gsize` and `g_memdup2()` throughout, and
change from identifying the position of the final slash in the string
using a signed offset `i`, to using a pointer to the character (and
`strrchr()`). This allows the slash to be at any position in a
`G_MAXSIZE`-long string, without sacrificing a bit of the offset for
indicating whether a slash was found.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319
This commit is contained in:
Philip Withnall 2021-02-04 13:58:32 +00:00
parent 9acebef777
commit 7781a9cbd2

View File

@ -149,8 +149,8 @@ convert_path (GKeyfileSettingsBackend *kfsb,
gchar **group,
gchar **basename)
{
gint key_len = strlen (key);
gint i;
gsize key_len = strlen (key);
const gchar *last_slash;
if (key_len < kfsb->prefix_len ||
memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0)
@ -159,38 +159,36 @@ convert_path (GKeyfileSettingsBackend *kfsb,
key_len -= kfsb->prefix_len;
key += kfsb->prefix_len;
for (i = key_len; i >= 0; i--)
if (key[i] == '/')
break;
last_slash = strrchr (key, '/');
if (kfsb->root_group)
{
/* if a root_group was specified, make sure the user hasn't given
* a path that ghosts that group name
*/
if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0)
if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0)
return FALSE;
}
else
{
/* if no root_group was given, ensure that the user gave a path */
if (i == -1)
if (last_slash == NULL)
return FALSE;
}
if (group)
{
if (i >= 0)
if (last_slash != NULL)
{
*group = g_memdup (key, i + 1);
(*group)[i] = '\0';
*group = g_memdup2 (key, (last_slash - key) + 1);
(*group)[(last_slash - key)] = '\0';
}
else
*group = g_strdup (kfsb->root_group);
}
if (basename)
*basename = g_memdup (key + i + 1, key_len - i);
*basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
return TRUE;
}