Re: Bug with iwd-3.11 - const char being modified

Marcel Holtmann
2026-02-10T09:43:31Z

Hi Rudi,

> Bug report (as below) for current iwd (including 3.11) - const char being modified.
>
> When compiling iwd with recent gcc and glibc-2.43 the --Wdiscarded-qualifiers
> warning occurs because with ISO C23, the function strrrchr that return
> pointers into their input arrays now have definitions as macros that
> return a pointer to a const-qualified type when the input argument is
> a pointer to a const-qualified type.
>
> ../client/known-networks.c: In function 'known_network_proxy_find_by_name':
> ../client/known-networks.c:296:29: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
> 296 | char *dot = strrchr(name, '.');
> | ^~~~~~~
>
> The fix would be to declare dot as const char as below, but this surfaces
> the error that name (which is const) is being modified. See >>>> below -
> this being an error.
>
> Regards
> Rudi
>
> --- a/client/known-networks.c
> +++ b/client/known-networks.c
> @@ -293,13 +293,13 @@
> network_args.type = NULL;
>
> if (network_args.type) {
> - char *dot = strrchr(name, '.');
> + const char *dot = strrchr(name, '.');
>
> if (!dot)
> /* This shouldn't ever be the case */
> return NULL;
>
>>>>> *dot = '\0';
> }
>
> network_args.name = name;

and this highlights a real issue.

I think the current code is trying to hard. This is untested, but it should be fixed along these lines.

diff --git a/client/known-networks.c b/client/known-networks.c
index 8634aca23e3b..0b24a863a8ef 100644
--- a/client/known-networks.c
+++ b/client/known-networks.c
@@ -243,15 +243,24 @@ static struct proxy_interface_type known_network_interface_type = {
static bool known_network_match(const void *a, const void *b)
{
const struct known_network *network = a;
- const struct network_args *args = b;
-
- if (strcmp(network->name, args->name))
- return false;
-
- if (args->type && strcmp(network->type, args->type))
- return false;
+ const char *name = b;
+ size_t name_len = strlen(name);
+
+ if (l_str_has_suffix(name, ".psk")) {
+ if (strcmp(network->type , "psk"))
+ return false;
+ name_len -= 4;
+ } else if (l_str_has_suffix(name, ".8021x")) {
+ if (strcmp(network->type , "8021x"))
+ return false;
+ name_len -= 6;
+ } else if (l_str_has_suffix(name, ".open")) {
+ if (strcmp(network->type , "open"))
+ return false;
+ name_len -= 5;
+ }
- return true;
+ return !strncmp(network->name, name, name_len);
}
static void check_errors_method_callback(struct l_dbus_message *message,
@@ -276,37 +285,14 @@ static enum cmd_status cmd_list(const char *entity, char **args, int argc)
static const struct proxy_interface *known_network_proxy_find_by_name(
const char *name)
{
- struct network_args network_args;
struct l_queue *match;
const struct proxy_interface *proxy;
if (!name)
return NULL;
- if (l_str_has_suffix(name, ".psk"))
- network_args.type = "psk";
- else if (l_str_has_suffix(name, ".8021x"))
- network_args.type = "8021x";
- else if (l_str_has_suffix(name, ".open"))
- network_args.type = "open";
- else
- network_args.type = NULL;
-
- if (network_args.type) {
- char *dot = strrchr(name, '.');
-
- if (!dot)
- /* This shouldn't ever be the case */
- return NULL;
-
- *dot = '\0';
- }
-
- network_args.name = name;
-
match = proxy_interface_find_all(known_network_interface_type.interface,
- known_network_match,
- &network_args);
+ known_network_match, name);
if (!match) {
display("No network with specified parameters was found\n");

And if you want to keep the network_args thing (which seems useless in view), then this could be a fix.

diff --git a/client/known-networks.c b/client/known-networks.c
index 8634aca23e3b..f906378602b1 100644
--- a/client/known-networks.c
+++ b/client/known-networks.c
@@ -279,35 +279,35 @@ static const struct proxy_interface *known_network_proxy_find_by_name(
struct network_args network_args;
struct l_queue *match;
const struct proxy_interface *proxy;
+ size_t name_len;
+ char *args_name;
if (!name)
return NULL;
- if (l_str_has_suffix(name, ".psk"))
+ name_len = strlen(name);
+
+ if (l_str_has_suffix(name, ".psk")) {
network_args.type = "psk";
- else if (l_str_has_suffix(name, ".8021x"))
+ name_len -= 4;
+ } else if (l_str_has_suffix(name, ".8021x")) {
network_args.type = "8021x";
- else if (l_str_has_suffix(name, ".open"))
+ name_len -= 6;
+ } else if (l_str_has_suffix(name, ".open")) {
network_args.type = "open";
- else
+ name_len -= 5;
+ } else
network_args.type = NULL;
- if (network_args.type) {
- char *dot = strrchr(name, '.');
-
- if (!dot)
- /* This shouldn't ever be the case */
- return NULL;
-
- *dot = '\0';
- }
-
- network_args.name = name;
+ args_name = l_strndup(name, name_len);
+ network_args.name = args_name;
match = proxy_interface_find_all(known_network_interface_type.interface,
known_network_match,
&network_args);
+ l_free(args_name);
+
if (!match) {
display("No network with specified parameters was found\n");
return NULL;

Regards

Marcel