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