diff --git a/inet/inet_net.c b/inet/inet_net.c
index 50b526705d..13a818176d 100644
--- a/inet/inet_net.c
+++ b/inet/inet_net.c
@@ -69,6 +69,8 @@ again:
if (*cp == 'x' || *cp == 'X')
digit = 0, base = 16, cp++;
while ((c = *cp) != 0) {
+ if (val > 0xff)
+ return (INADDR_NONE);
if (isdigit(c)) {
if (base == 8 && (c == '8' || c == '9'))
return (INADDR_NONE);
diff --git a/nss/Makefile b/nss/Makefile
index 3ee51f309e..09ce94aae7 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -367,6 +367,7 @@ tests += tst-nss-files-hosts-multi
tests += tst-nss-files-hosts-getent
tests += tst-nss-files-alias-leak
tests += tst-nss-files-alias-truncated
+tests += tst-nss-files-network
# tst_fgetgrent currently only works with shared libraries
test-srcs := tst_fgetgrent
ifeq ($(run-built-tests),yes)
diff --git a/nss/nss_files/files-network.c b/nss/nss_files/files-network.c
index ca94372024..f08daaf55f 100644
--- a/nss/nss_files/files-network.c
+++ b/nss/nss_files/files-network.c
@@ -42,7 +42,8 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* 'inet_network' does not add zeroes at the end if the network number
- does not four byte values. We add them ourselves if necessary. */
+ does not contain four byte values. We shift result ourselves if
+ necessary. */
cp = strchr (addr, '.');
if (cp != NULL)
{
@@ -56,20 +57,11 @@ LINE_PARSER
++n;
}
}
- if (n < 4)
- {
- char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1);
- cp = stpcpy (newp, addr);
- do
- {
- *cp++ = '.';
- *cp++ = '0';
- }
- while (++n < 4);
- *cp = '\0';
- addr = newp;
- }
result->n_net = __inet_network (addr);
+ if (result->n_net == INADDR_NONE)
+ return 0;
+ if (n < 4)
+ result->n_net <<= 8 * (4 - n);
result->n_addrtype = AF_INET;
})
diff --git a/nss/tst-nss-files-network.c b/nss/tst-nss-files-network.c
new file mode 100644
index 0000000000..5aa0cd1db2
--- /dev/null
+++ b/nss/tst-nss-files-network.c
@@ -0,0 +1,96 @@
+/* Test long entries and truncated numbers in /etc/networks (bug 32573/32575).
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define STACK_LIM 1048576
+#define STRING_SIZE (2 * STACK_LIM)
+
+struct support_chroot *chroot_env;
+
+static void
+prepare (int argc, char **argv)
+{
+ int ret;
+ char *content;
+ char *entry = malloc (STRING_SIZE);
+ struct rlimit lim;
+ getrlimit (RLIMIT_STACK, &lim);
+ lim.rlim_cur = STACK_LIM;
+ setrlimit (RLIMIT_STACK, &lim);
+ if (entry == NULL)
+ {
+ puts ("malloc failed, cannot test");
+ exit (1);
+ }
+ memset (entry, 'A', STRING_SIZE);
+ entry[STRING_SIZE - 1] = 0;
+ ret = asprintf (&content, "%s\n%s\nnet3 %s\n",
+ "net1 x0000000000Ff.077", /* legal 255.63.0.0 */
+ "net2 xFF00000000.0.0.0", /* illegal */
+ entry /* illegal */);
+ if (ret == -1)
+ {
+ puts ("asprintf failed, cannot test");
+ exit (1);
+ }
+ free (entry);
+ chroot_env = support_chroot_create
+ ((struct support_chroot_configuration)
+ {
+ .networks = content
+ });
+
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ if (!support_can_chroot ())
+ return EXIT_UNSUPPORTED;
+
+ __nss_configure_lookup ("networks", "files");
+ xdlopen (LIBNSS_FILES_SO, RTLD_NOW);
+
+ xchroot (chroot_env->path_chroot);
+
+ check_netent ("net1", getnetbyname ("net1"),
+ "name: net1\n"
+ "net: 0xff3f0000\n");
+ check_netent ("net2", getnetbyname ("net2"), "error: HOST_NOT_FOUND\n");
+
+ support_chroot_free (chroot_env);
+ return 0;
+}
+
+#define PREPARE prepare
+#include
diff --git a/support/namespace.h b/support/namespace.h
index 456157a4e0..6b9b226f95 100644
--- a/support/namespace.h
+++ b/support/namespace.h
@@ -75,6 +75,7 @@ struct support_chroot_configuration
const char *hosts; /* /etc/hosts. */
const char *host_conf; /* /etc/host.conf. */
const char *aliases; /* /etc/aliases. */
+ const char *networks; /* /etc/networks. */
};
/* The result of the creation of a chroot. */
@@ -92,6 +93,7 @@ struct support_chroot
char *path_hosts; /* /etc/hosts. */
char *path_host_conf; /* /etc/host.conf. */
char *path_aliases; /* /etc/aliases. */
+ char *path_networks; /* /etc/networks. */
};
/* Create a chroot environment. The returned data should be freed
diff --git a/support/support_chroot.c b/support/support_chroot.c
index 2637dd1522..92c2a453aa 100644
--- a/support/support_chroot.c
+++ b/support/support_chroot.c
@@ -57,6 +57,7 @@ support_chroot_create (struct support_chroot_configuration conf)
write_file (path_etc, "hosts", conf.hosts, &chroot->path_hosts);
write_file (path_etc, "host.conf", conf.host_conf, &chroot->path_host_conf);
write_file (path_etc, "aliases", conf.aliases, &chroot->path_aliases);
+ write_file (path_etc, "networks", conf.networks, &chroot->path_networks);
free (path_etc);
@@ -79,5 +80,6 @@ support_chroot_free (struct support_chroot *chroot)
free (chroot->path_hosts);
free (chroot->path_host_conf);
free (chroot->path_aliases);
+ free (chroot->path_networks);
free (chroot);
}