[Openvpn-devel,v2] compat: Add strlcpy and strlcat

Message ID 20261016085833.27514-1-gert@greenie.muc.de
State New
Headers
Series [Openvpn-devel,v2] compat: Add strlcpy and strlcat |

Commit Message

Gert Doering Oct. 16, 2026, 8:58 a.m. UTC
  From: Frank Lichtenheld <frank@lichtenheld.com>

Avaibable on most systems (Linux since
glibc 2.38), but not all. We already
have strncpynt, but switching to the
standard strlcpy makes the code more
accessible for both humans and tools.

This commit only introduces the
possibility to use strlcpy in general
code (we already have one usage in
BSD-specific code). No users are
introduced, yet.

Change-Id: I906b3fad5d521e1e4b0f15aff763cf4d4d8bc35e
Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
Acked-by: Razvan Cojocaru <razvanc@mailbox.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1994
---

This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.

Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1994
This mail reflects revision 2 of this Change.

Acked-by according to Gerrit (reflected above):
Razvan Cojocaru <razvanc@mailbox.org>
  

Comments

Gert Doering Oct. 16, 2026, 11:36 a.m. UTC | #1
Reading the manpages for strlcpy() and strlcat() (and comparing to
strncat()) I agree that this is the direction to go.  I would not 
do this for 2.7, as it's the sort of "we clean up old stuff" thing
we do in master (-> 2.8).

Sanity checked via a GHA build run (all green, BBs as well).

Your patch has been applied to the master branch.

commit f659b6ecffccdca4469c2a20a819d7a29fc3c7c0 (master)
Author: Frank Lichtenheld
Date:   Fri Oct 16 10:58:27 2026 +0200

     compat: Add strlcpy and strlcat

     Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
     Acked-by: Razvan Cojocaru <razvanc@mailbox.org>
     Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1994
     Message-Id: <20261016085833.27514-1-gert@greenie.muc.de>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg39916.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering
  

Patch

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bac4dd4..b286ee2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -248,6 +248,7 @@ 
 
 check_symbol_exists(chsize io.h HAVE_CHSIZE)
 check_symbol_exists(getrlimit sys/resource.h HAVE_GETRLIMIT)
+check_symbol_exists(strlcpy string.h HAVE_STRLCPY)
 check_symbol_exists(strsep string.h HAVE_STRSEP)
 check_symbol_exists(strtok_r string.h HAVE_STRTOK_R)
 
@@ -431,6 +432,7 @@ 
     src/compat/compat-daemon.c
     src/compat/compat-dirname.c
     src/compat/compat-gettimeofday.c
+    src/compat/compat-strlcpy.c
     src/compat/compat-strsep.c
     src/compat/compat-strtok_r.c
     src/openvpn/argv.c
@@ -764,6 +766,7 @@ 
             src/openvpn/platform.c
             src/openvpn/win32-util.c
             src/compat/compat-gettimeofday.c
+            src/compat/compat-strlcpy.c
             src/compat/compat-strsep.c
             src/compat/compat-strtok_r.c
             )
diff --git a/config.h.cmake.in b/config.h.cmake.in
index 8c3088e..483de45 100644
--- a/config.h.cmake.in
+++ b/config.h.cmake.in
@@ -267,6 +267,9 @@ 
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
+/* Define to 1 if you have the `strlcpy' function. */
+#cmakedefine HAVE_STRLCPY
+
 /* Define to 1 if you have the `strsep' function. */
 #cmakedefine HAVE_STRSEP
 
diff --git a/configure.ac b/configure.ac
index 56109af..ad3f8f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -568,7 +568,7 @@ 
 	setgroups flock gettimeofday \
 	setsid chdir \
 	chsize ftruncate execve getpeereid basename dirname \
-	epoll_create strsep strtok_r \
+	epoll_create strlcpy strsep strtok_r \
 ])
 
 AC_CHECK_LIB(
diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am
index 22867b3..8b1d44a 100644
--- a/src/compat/Makefile.am
+++ b/src/compat/Makefile.am
@@ -20,5 +20,6 @@ 
 	compat-basename.c \
 	compat-gettimeofday.c \
 	compat-daemon.c \
+	compat-strlcpy.c \
 	compat-strsep.c \
-	compat-strtok_r.c
\ No newline at end of file
+	compat-strtok_r.c
diff --git a/src/compat/compat-strlcpy.c b/src/compat/compat-strlcpy.c
new file mode 100644
index 0000000..8c1e80a
--- /dev/null
+++ b/src/compat/compat-strlcpy.c
@@ -0,0 +1,52 @@ 
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_STRLCPY
+#include <string.h>
+
+size_t
+strlcpy(char *dest, const char *src, size_t maxlen)
+{
+    if (maxlen > 0)
+    {
+        strncpy(dest, src, maxlen - 1);
+        dest[maxlen - 1] = 0;
+    }
+    return strlen(src);
+}
+
+size_t
+strlcat(char *dest, const char *src, size_t maxlen)
+{
+    size_t dest_len = strnlen(dest, maxlen);
+    if (maxlen > dest_len)
+    {
+        strncat(dest, src, maxlen - dest_len - 1);
+    }
+    return dest_len + strlen(src);
+}
+
+#endif /* ifndef HAVE_STRLCPY */
diff --git a/src/compat/compat.h b/src/compat/compat.h
index 9e6f95c..4ee9141 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -56,6 +56,15 @@ 
 
 #endif
 
+#ifndef HAVE_STRLCPY
+size_t
+strlcpy(char *dest, const char *src, size_t maxlen);
+
+size_t
+strlcat(char *dest, const char *src, size_t maxlen);
+
+#endif
+
 #ifndef HAVE_STRSEP
 char *strsep(char **stringp, const char *delim);
 
diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am
index 5430ecb..38299f5 100644
--- a/tests/unit_tests/openvpn/Makefile.am
+++ b/tests/unit_tests/openvpn/Makefile.am
@@ -54,6 +54,7 @@ 
 argv_testdriver_SOURCES = test_argv.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/platform.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/win32-util.c \
@@ -64,6 +65,7 @@ 
 buffer_testdriver_SOURCES = test_buffer.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/win32-util.c \
 	$(top_srcdir)/src/openvpn/platform.c
 
@@ -74,6 +76,7 @@ 
 crypto_testdriver_SOURCES = test_crypto.c \
 	mock_msg.c mock_msg.h test_common.h \
 	siphash_openssl.c siphash_openssl.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/crypto.c \
 	$(top_srcdir)/src/openvpn/crypto_mbedtls.c \
@@ -94,6 +97,7 @@ 
 dhcp_testdriver_SOURCES = test_dhcp.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/platform.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/win32-util.c
@@ -106,6 +110,7 @@ 
 	mock_msg.c mock_msg.h test_common.h \
 	mock_management.c \
 	mock_ssl_dependencies.c mock_win32_execve.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/argv.c \
 	$(top_srcdir)/src/openvpn/base64.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -145,6 +150,7 @@ 
 packet_id_testdriver_SOURCES = test_packet_id.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/otime.c \
 	$(top_srcdir)/src/openvpn/packet_id.c \
@@ -158,6 +164,7 @@ 
 	@TEST_CFLAGS@
 pkt_testdriver_LDFLAGS = @TEST_LDFLAGS@
 pkt_testdriver_SOURCES = test_pkt.c mock_msg.c mock_msg.h mock_win32_execve.c test_common.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/argv.c \
 	$(top_srcdir)/src/openvpn/base64.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -190,6 +197,7 @@ 
 tls_crypt_testdriver_SOURCES = test_tls_crypt.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_win32_execve.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/argv.c \
 	$(top_srcdir)/src/openvpn/base64.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -212,6 +220,7 @@ 
 networking_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(top_srcdir)/src/openvpn \
 	$(OPTIONAL_CRYPTO_LIBS)
 networking_testdriver_SOURCES = test_networking.c mock_msg.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/networking_sitnl.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/crypto.c \
@@ -230,6 +239,7 @@ 
 options_parse_testdriver_SOURCES = test_options_parse.c \
 	mock_msg.c mock_msg.h test_common.h \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/options_parse.c \
 	$(top_srcdir)/src/openvpn/options_util.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -243,6 +253,7 @@ 
 	$(OPTIONAL_CRYPTO_LIBS)
 
 provider_testdriver_SOURCES = test_provider.c mock_msg.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/xkey_helper.c \
 	$(top_srcdir)/src/openvpn/xkey_provider.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -259,6 +270,7 @@ 
 	$(OPTIONAL_CRYPTO_LIBS) -lcrypt32 -lncrypt
 cryptoapi_testdriver_SOURCES = test_cryptoapi.c mock_msg.c \
 	pkey_test_utils.c cert_data.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/xkey_helper.c \
 	$(top_srcdir)/src/openvpn/xkey_provider.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
@@ -278,6 +290,7 @@ 
 pkcs11_testdriver_SOURCES = test_pkcs11.c \
 	mock_msg.c test_common.h \
 	pkey_test_utils.c cert_data.h mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/xkey_helper.c \
 	$(top_srcdir)/src/openvpn/xkey_provider.c \
 	$(top_srcdir)/src/openvpn/argv.c \
@@ -300,6 +313,7 @@ 
 
 auth_token_testdriver_SOURCES = test_auth_token.c \
 	mock_msg.c test_common.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/crypto.c \
 	$(top_srcdir)/src/openvpn/crypto_epoch.c \
@@ -320,6 +334,7 @@ 
 
 user_pass_testdriver_SOURCES = test_user_pass.c \
 	mock_msg.c test_common.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/console.c \
 	$(top_srcdir)/src/openvpn/env_set.c \
@@ -339,6 +354,7 @@ 
 
 ncp_testdriver_SOURCES = test_ncp.c \
 	mock_msg.c test_common.h \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/crypto.c \
 	$(top_srcdir)/src/openvpn/crypto_epoch.c \
@@ -362,6 +378,7 @@ 
 mbuf_testdriver_SOURCES = test_mbuf.c \
 	mock_msg.c test_common.h  \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/win32-util.c \
 	$(top_srcdir)/src/openvpn/platform.c \
@@ -377,6 +394,7 @@ 
 	test_schedule.c test_schedule.h \
 	mock_msg.c test_common.h  \
 	mock_get_random.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/options_util.c \
 	$(top_srcdir)/src/openvpn/ssl_util.c \
@@ -402,6 +420,7 @@ 
 	mock_msg.c \
 	mock_get_random.c \
 	mock_push_dependencies.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/platform.c \
 	$(top_srcdir)/src/openvpn/options_util.c \
@@ -419,6 +438,7 @@ 
 	mock_msg.c test_common.h  \
 	mock_get_random.c \
 	mock_management.c \
+	$(top_srcdir)/src/compat/compat-strlcpy.c \
 	$(top_srcdir)/src/openvpn/buffer.c \
 	$(top_srcdir)/src/openvpn/win32-util.c \
 	$(top_srcdir)/src/openvpn/platform.c \