ws: fix some string const errors

The `accept` parameter to `cockpit_web_server_parse_accept_list()` is
`const char *` and indeed doesn't modify its input, but it does make a
copy of it.  It then iterates over that copy and modifies it, but it
performs this iteration using the original `const` pointer.

It used to be that the compiler was a bit lenient about these `const`
correctness issues around strings but with the latest tasks container
upgrade and our use of -Werror in our unit tests run, this is now
failing.

Add a separate non-`const` local (`walk`) to avoid reusing the `const`
version to access a string which will be written to (since we put `\0`s
in here).  Also use a `const char *` when accessing `Language.value`
(which is also `const` because it might point to the `const` `defawlt`
parameter) to avoid a warning there.

Take the opportunity to clean up the entire function to move
declarations to their point of first use and add `g_autoptr` and
`g_autofree` throughout.

One very pedantic consideration after having spent too long writing Rust
code: `langs` ends up containing references to the sliced up string in
`copy`.  At the end of the function the variables get freed in reverse
order of their declaration, so we should want to make sure `langs` is
freed before `copy`.  The original code got this wrong but it's not
really an issue, of course, because there's no access between those two
points.  All the same: let's declare `copy` first so the frees happen in
the (pedantically) correct order.
This commit is contained in:
Allison Karlitskaya 2026-06-29 11:11:42 +02:00
parent 3b6be58156
commit 9b0b120649

View file

@ -469,41 +469,33 @@ gchar **
cockpit_web_server_parse_accept_list (const gchar *accept, cockpit_web_server_parse_accept_list (const gchar *accept,
const gchar *defawlt) const gchar *defawlt)
{ {
Language *lang; g_autofree gchar *copy = g_strdup (accept);
GPtrArray *langs; gchar *walk = copy;
GPtrArray *ret;
gchar *copy;
gchar *value;
gchar *next;
gchar *pos;
guint i;
langs = g_ptr_array_new_with_free_func (g_free); g_autoptr(GPtrArray) langs = g_ptr_array_new_with_free_func (g_free);
if (defawlt) if (defawlt)
{ {
lang = g_new0 (Language, 1); Language *lang = g_new0 (Language, 1);
lang->qvalue = 0.1; lang->qvalue = 0.1;
lang->value = defawlt; lang->value = defawlt;
g_ptr_array_add (langs, lang); g_ptr_array_add (langs, lang);
} }
/* First build up an array we can sort */ /* First build up an array we can sort */
accept = copy = g_strdup (accept); while (walk)
while (accept)
{ {
next = strchr (accept, ','); gchar *next = strchr (walk, ',');
if (next) if (next)
{ {
*next = '\0'; *next = '\0';
next++; next++;
} }
lang = g_new0 (Language, 1); Language *lang = g_new0 (Language, 1);
lang->qvalue = 1; lang->qvalue = 1;
pos = strchr (accept, ';'); gchar *pos = strchr (walk, ';');
if (pos) if (pos)
{ {
*pos = '\0'; *pos = '\0';
@ -515,43 +507,41 @@ cockpit_web_server_parse_accept_list (const gchar *accept,
} }
} }
lang->value = accept; lang->value = walk;
g_ptr_array_add (langs, lang); g_ptr_array_add (langs, lang);
accept = next; walk = next;
} }
g_ptr_array_sort (langs, sort_qvalue); g_ptr_array_sort (langs, sort_qvalue);
/* Now in the right order add all the prefs */ /* Now in the right order add all the prefs */
ret = g_ptr_array_new (); GPtrArray *ret = g_ptr_array_new ();
for (i = 0; i < langs->len; i++) for (guint i = 0; i < langs->len; i++)
{ {
lang = langs->pdata[i]; Language *lang = langs->pdata[i];
if (lang->qvalue > 0) if (lang->qvalue > 0)
{ {
value = g_strstrip (g_ascii_strdown (lang->value, -1)); gchar *value = g_strstrip (g_ascii_strdown (lang->value, -1));
g_ptr_array_add (ret, value); g_ptr_array_add (ret, value);
} }
} }
/* Add base languages after that */ /* Add base languages after that */
for (i = 0; i < langs->len; i++) for (guint i = 0; i < langs->len; i++)
{ {
lang = langs->pdata[i]; Language *lang = langs->pdata[i];
if (lang->qvalue > 0) if (lang->qvalue > 0)
{ {
pos = strchr (lang->value, '-'); const gchar *dash = strchr (lang->value, '-');
if (pos) if (dash)
{ {
value = g_strstrip (g_ascii_strdown (lang->value, pos - lang->value)); gchar *value = g_strstrip (g_ascii_strdown (lang->value, dash - lang->value));
g_ptr_array_add (ret, value); g_ptr_array_add (ret, value);
} }
} }
} }
g_free (copy);
g_ptr_array_add (ret, NULL); g_ptr_array_add (ret, NULL);
g_ptr_array_free (langs, TRUE);
return (gchar **)g_ptr_array_free (ret, FALSE); return (gchar **)g_ptr_array_free (ret, FALSE);
} }