From: Arne Schwabe Date: Wed, 8 Jul 2026 15:31:07 +0000 (+0200) Subject: Replace strtok with strtok_r X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=27df276eabdf87ad97ab88e8e84cc53d2bbc59c8;p=thirdparty%2Fopenvpn.git Replace strtok with strtok_r This does not change anything in our source code but makes compiling with newer Android NDKs (version 30 pre release) -Werror safe again as it has started throwing warning on this. The compat version is taken from current FreeBSD (commit dc36d6f9bb1) src/lib/libc/string/strtok.c and reformatted to our clang standard. Change-Id: I70560efd113308b7377424127eb2c1da4266371a Signed-off-by: Arne Schwabe Acked-by: Frank Lichtenheld Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1679 Message-Id: <20260708153107.60809-1-frank@lichtenheld.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg37538.html Signed-off-by: Gert Doering --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 23541a5db..7473f1545 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,6 +248,7 @@ endif() check_symbol_exists(chsize io.h HAVE_CHSIZE) check_symbol_exists(getrlimit sys/resource.h HAVE_GETRLIMIT) check_symbol_exists(strsep string.h HAVE_STRSEP) +check_symbol_exists(strtok_r string.h HAVE_STRTOK_R) # Some OS (e.g. FreeBSD) need some basic headers to allow # including network headers @@ -423,6 +424,7 @@ set(SOURCE_FILES src/compat/compat-dirname.c src/compat/compat-gettimeofday.c src/compat/compat-strsep.c + src/compat/compat-strtok_r.c src/openvpn/argv.c src/openvpn/argv.h src/openvpn/base64.c @@ -743,6 +745,8 @@ if (BUILD_TESTING) src/openvpn/platform.c src/openvpn/win32-util.c src/compat/compat-gettimeofday.c + src/compat/compat-strsep.c + src/compat/compat-strtok_r.c ) add_library_deps(${test_name}) diff --git a/configure.ac b/configure.ac index e19d65167..188f8fa42 100644 --- a/configure.ac +++ b/configure.ac @@ -568,7 +568,7 @@ AC_CHECK_FUNCS([ \ setgroups flock gettimeofday \ setsid chdir \ chsize ftruncate execve getpeereid basename dirname \ - epoll_create strsep \ + epoll_create strsep strtok_r \ ]) AC_CHECK_LIB( diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am index 69b29906f..22867b361 100644 --- a/src/compat/Makefile.am +++ b/src/compat/Makefile.am @@ -20,4 +20,5 @@ libcompat_la_SOURCES = \ compat-basename.c \ compat-gettimeofday.c \ compat-daemon.c \ - compat-strsep.c \ No newline at end of file + compat-strsep.c \ + compat-strtok_r.c \ No newline at end of file diff --git a/src/compat/compat-strtok_r.c b/src/compat/compat-strtok_r.c new file mode 100644 index 000000000..debcdd34b --- /dev/null +++ b/src/compat/compat-strtok_r.c @@ -0,0 +1,101 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1998 Softweyr LLC. All rights reserved. + * + * strtok_r, from Berkeley strtok + * Oct 13, 1998 by Wes Peters + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notices, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notices, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE + * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_STRTOK_R +#include + +char * +strtok_r(char *s, const char *delim, char **last) +{ + char *spanp, *tok; + int c, sc; + + if (s == NULL && (s = *last) == NULL) + { + return (NULL); + } + +/* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) + { + if (c == sc) + { + goto cont; + } + } + + if (c == 0) + { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) + { + c = *s++; + spanp = (char *)delim; + do + { + if ((sc = *spanp++) == c) + { + if (c == 0) + { + s = NULL; + } + else + { + s[-1] = '\0'; + } + *last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} +#endif \ No newline at end of file diff --git a/src/compat/compat.h b/src/compat/compat.h index 6532b8612..9e6f95c2f 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -61,4 +61,9 @@ char *strsep(char **stringp, const char *delim); #endif +#ifndef HAVE_STRTOK_R +char * +strtok_r(char *s, const char *delim, char **last); +#endif + #endif /* COMPAT_H */ diff --git a/src/openvpn/options_util.c b/src/openvpn/options_util.c index 47fe0bc25..d72ea25c7 100644 --- a/src/openvpn/options_util.c +++ b/src/openvpn/options_util.c @@ -48,7 +48,8 @@ parse_auth_failed_temp(struct options *o, const char *reason) message = strstr(reason, "]") + 1; /* null terminate the substring to only looks for flags between [ and ] */ *endofflags = '\x00'; - const char *token = strtok(m, "[,"); + char *lasts = NULL; + const char *token = strtok_r(m, "[,", &lasts); while (token) { if (!strncmp(token, "backoff ", strlen("backoff "))) @@ -81,7 +82,7 @@ parse_auth_failed_temp(struct options *o, const char *reason) { msg(D_PUSH_ERRORS, "WARNING: unknown AUTH_FAIL,TEMP flag: %s", token); } - token = strtok(NULL, "[,"); + token = strtok_r(NULL, "[,", &lasts); } } diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index 8a0f7d247..07caf082c 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -318,9 +318,10 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) /* Parse allowed ciphers, getting IDs */ int i = 0; + char *lasts = NULL; tmp_ciphers_orig = tmp_ciphers = string_alloc(ciphers, NULL); - token = strtok(tmp_ciphers, ":"); + token = strtok_r(tmp_ciphers, ":", &lasts); while (token) { ctx->allowed_ciphers[i] = mbedtls_ssl_get_ciphersuite_id(tls_translate_cipher_name(token)); @@ -328,7 +329,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) { i++; } - token = strtok(NULL, ":"); + token = strtok_r(NULL, ":", &lasts); } free(tmp_ciphers_orig); } diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c index 649665abc..baf5a9510 100644 --- a/src/openvpn/ssl_ncp.c +++ b/src/openvpn/ssl_ncp.c @@ -100,7 +100,8 @@ mutate_ncp_cipher_list(const char *list, struct gc_arena *gc) struct buffer new_list = alloc_buf(MAX_NCP_CIPHERS_LENGTH); char *const tmp_ciphers = string_alloc(list, NULL); - const char *token = strtok(tmp_ciphers, ":"); + char *lasts = NULL; + const char *token = strtok_r(tmp_ciphers, ":", &lasts); while (token) { /* @@ -174,7 +175,7 @@ mutate_ncp_cipher_list(const char *list, struct gc_arena *gc) buf_puts(&new_list, ovpn_cipher_name); } } - token = strtok(NULL, ":"); + token = strtok_r(NULL, ":", &lasts); } @@ -207,15 +208,16 @@ tls_item_in_cipher_list(const char *item, const char *list) { char *tmp_ciphers = string_alloc(list, NULL); char *tmp_ciphers_orig = tmp_ciphers; + char *lasts = NULL; - const char *token = strtok(tmp_ciphers, ":"); + const char *token = strtok_r(tmp_ciphers, ":", &lasts); while (token) { if (0 == strcmp(token, item)) { break; } - token = strtok(NULL, ":"); + token = strtok_r(NULL, ":", &lasts); } free(tmp_ciphers_orig); diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 9197adfba..162f68fba 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -868,7 +868,8 @@ check_auth_pending_method(const char *peer_info, const char *method) return false; } - const char *client_method = strtok(iv_sso, ","); + char *lasts = NULL; + const char *client_method = strtok_r(iv_sso, ",", &lasts); bool supported = false; while (client_method) @@ -878,7 +879,7 @@ check_auth_pending_method(const char *peer_info, const char *method) supported = true; break; } - client_method = strtok(NULL, ","); + client_method = strtok_r(NULL, ",", &lasts); } gc_free(&gc); diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 1128eb49e..d861ef9a3 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -107,6 +107,7 @@ ssl_testdriver_SOURCES = test_ssl.c \ $(top_srcdir)/src/openvpn/base64.c \ $(top_srcdir)/src/openvpn/buffer.c \ $(top_srcdir)/src/compat/compat-strsep.c \ + $(top_srcdir)/src/compat/compat-strtok_r.c \ $(top_srcdir)/src/openvpn/crypto.c \ $(top_srcdir)/src/openvpn/cryptoapi.c \ $(top_srcdir)/src/openvpn/crypto_epoch.c \ @@ -345,6 +346,7 @@ ncp_testdriver_SOURCES = test_ncp.c \ $(top_srcdir)/src/openvpn/platform.c \ $(top_srcdir)/src/openvpn/win32-util.c \ $(top_srcdir)/src/compat/compat-strsep.c \ + $(top_srcdir)/src/compat/compat-strtok_r.c \ $(top_srcdir)/src/openvpn/ssl_util.c mbuf_testdriver_CFLAGS = \