From patchwork Wed Oct 8 10:10:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4480 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:7d42:b0:72f:f16c:e055 with SMTP id fr2csp820546mab; Wed, 8 Oct 2025 03:10:34 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUrtHQK/PqFArlF5tSMHnjAjfAebjDbQr/N9H43P7FtNw3KCzq3FeHIkwel2smyENpNLo8Nubu+htg=@openvpn.net X-Google-Smtp-Source: AGHT+IGXzjs66JHZLtVNUKM/fCajDAXSUgl4ESxJYaj4d1PGZ/R/+lEv6dg2zI5hVV3ChltbXthq X-Received: by 2002:a05:6808:1a27:b0:438:36af:9deb with SMTP id 5614622812f47-4417b927523mr1531629b6e.21.1759918234121; Wed, 08 Oct 2025 03:10:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1759918234; cv=none; d=google.com; s=arc-20240605; b=Q8R4YROBTmbRljXHliYhSreC/K7ycmqMt3Yua30/Zfv9NJZnns4I/wWTrKKU88EXFk jSLZgLB9DIJ9NSgW+al1yI/ibGbP7Jtl2Ak2YacWEBgEC8vymprtPwk+uCWEdxc5YZGW igNfGdS0VPQ6MMITaa0+be0gWx77HaI1/6A1iRx4TgZpckC3EHUq46LbBo+fF0gb/WWv pbTDuuR9pBKFoyZAJVTe5k7IlJYIYDG+FD3UGBWDhvklv4Xk19KD32P1Zy+Mnti/3dzE uJYr8d4n3+LAFNgLvFyMa1XvuTMS3xA02dApRWgKDLoOA4QcUCzAk4xvATueIFELA1SC uTjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=5aufqzud5yRHlJbNjEdx63nJLPtxgphO6ZpYDbhXhi8=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=SdpTo0Zi+XPfiUf3zd8X/RqRk6RlhRouGtqV7bfr+ChUFG2xF/lIWV7avqUUSF3aQB SfsqPnMT4+KLcWKrYAC3PO7z6tISnbItD8h5Brg6c3nfEcD6O685d89FUccMyZvoLZCU rl7L+5VZ5mFon2lymwTKx522Oi2dCRYf59faQvDdjVToEVnc1pnFl6qL9xCQICnVOa2q I6dfn6NLPmUcyW1uHxuLE1aiNLUku5V3YrM83FRMpzKZqCmoeg4AeCEXY2jNZLEKC5o3 tdKZXCWaBJK6GKOTW4Mp95uHt6vt96EU3VNLGrNaK5VgyTkP52inHt7VutskGlg8fHtI bmnQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=gpnP7JOW; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Z66XjNUM; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=TkmXWAqg; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5614622812f47-43fc19b536esi3586761b6e.413.2025.10.08.03.10.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 08 Oct 2025 03:10:34 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=gpnP7JOW; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Z66XjNUM; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=TkmXWAqg; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5aufqzud5yRHlJbNjEdx63nJLPtxgphO6ZpYDbhXhi8=; b=gpnP7JOWg8khHmZfuhTJQh0h+z HMucbAs93N0fNOEJffg+WX43riIpW7SOfG2XTi5bwOKhwKm8hQ64pkb69FuQn2+Gf8jCdcyIUqxS7 Dg/LhLZDKR65ckdhk2KGphNNTPJwFL7GzAZeZQ8WYEoCFGQjeAcc1zEHJyNKjdq6b6z4=; Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1v6R7u-0003z6-AM; Wed, 08 Oct 2025 10:10:30 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1v6R7s-0003yz-2a for openvpn-devel@lists.sourceforge.net; Wed, 08 Oct 2025 10:10:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=xL/TsCdXHqK5OOuKHf6FBMJwXHR4XwyyAABUlv/hcIk=; b=Z66XjNUM/ZhaRt6EPE88sY43XY jzh6En5kUXOXDxIudPjMv25xNhIVZKwoqC/csxfVHKaX4GW8E3Ax9qjiHvjJg0JUu9nxk8mly4NL0 8NuBXioje0AUOB7b1EIbCuRzo0Hz+L+kIzRqMqO8gDiEj2OJGTsM7e3b62y/00Gje52U=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=xL/TsCdXHqK5OOuKHf6FBMJwXHR4XwyyAABUlv/hcIk=; b=TkmXWAqgNeAwHBitwCJRIYrKZ+ Y0Fd8O5GftVWOfhgfiQ37bCjXh21/EgZK8W4VNorYSr/dlAZswz3qDYkeQp9YSya1iyrImBe6clS9 IjPHIBr0p4codUhK7fPoHdXQTuIkR3sTcMi8zVUMSvrU4Fc0eMJDh8u4rltLBofwqFjM=; Received: from [193.149.48.134] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1v6R7q-0003qd-Uv for openvpn-devel@lists.sourceforge.net; Wed, 08 Oct 2025 10:10:27 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 598AAFTd005720 for ; Wed, 8 Oct 2025 12:10:15 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.1/8.18.1/Submit) id 598AAF3s005719 for openvpn-devel@lists.sourceforge.net; Wed, 8 Oct 2025 12:10:15 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Wed, 8 Oct 2025 12:10:09 +0200 Message-ID: <20251008101014.5691-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.49.1 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Frank Lichtenheld For now contains one test case for parse_line. Change-Id: I95032d2539d994abf69fc17319ed1a429c3bb948 Signed-off-by: Frank Lichtenheld Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/open [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1v6R7q-0003qd-Uv Subject: [Openvpn-devel] [PATCH v3] test_options_parse: Start new UT for options_parse.c X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1845408022137927922?= X-GMAIL-MSGID: =?utf-8?q?1845408022137927922?= From: Frank Lichtenheld For now contains one test case for parse_line. Change-Id: I95032d2539d994abf69fc17319ed1a429c3bb948 Signed-off-by: Frank Lichtenheld Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1244 --- 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/+/1244 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/CMakeLists.txt b/CMakeLists.txt index aeef480..37bfc03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -685,6 +685,7 @@ # Clang-cl (which is also MSVC) is wrongly detected to support wrap if (NOT MSVC AND "${LD_SUPPORTS_WRAP}") list(APPEND unit_tests + "test_options_parse" "test_tls_crypt" ) endif () @@ -826,6 +827,20 @@ src/compat/compat-strsep.c ) + if (TARGET test_options_parse) + target_link_options(test_options_parse PRIVATE + -Wl,--wrap=add_option + -Wl,--wrap=remove_option + -Wl,--wrap=update_option + -Wl,--wrap=usage + ) + target_sources(test_options_parse PRIVATE + tests/unit_tests/openvpn/mock_get_random.c + src/openvpn/options_parse.c + src/openvpn/options_util.c + ) + endif () + target_sources(test_packet_id PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/otime.c diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index f7b1bc8..8e94665 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -9,6 +9,7 @@ user_pass_testdriver push_update_msg_testdriver provider_testdriver socket_testdriver if HAVE_LD_WRAP_SUPPORT +test_binaries += options_parse_testdriver if !WIN32 test_binaries += tls_crypt_testdriver endif @@ -190,6 +191,21 @@ $(top_srcdir)/src/openvpn/platform.c endif +options_parse_testdriver_CFLAGS = -I$(top_srcdir)/src/openvpn -I$(top_srcdir)/src/compat @TEST_CFLAGS@ +options_parse_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(top_srcdir)/src/openvpn \ + -Wl,--wrap=add_option \ + -Wl,--wrap=update_option \ + -Wl,--wrap=remove_option \ + -Wl,--wrap=usage +options_parse_testdriver_SOURCES = test_options_parse.c \ + mock_msg.c mock_msg.h test_common.h \ + mock_get_random.c \ + $(top_srcdir)/src/openvpn/options_parse.c \ + $(top_srcdir)/src/openvpn/options_util.c \ + $(top_srcdir)/src/openvpn/buffer.c \ + $(top_srcdir)/src/openvpn/win32-util.c \ + $(top_srcdir)/src/openvpn/platform.c + provider_testdriver_CFLAGS = \ -I$(top_srcdir)/include -I$(top_srcdir)/src/compat -I$(top_srcdir)/src/openvpn \ @TEST_CFLAGS@ $(OPTIONAL_CRYPTO_CFLAGS) diff --git a/tests/unit_tests/openvpn/test_options_parse.c b/tests/unit_tests/openvpn/test_options_parse.c new file mode 100644 index 0000000..9472c78 --- /dev/null +++ b/tests/unit_tests/openvpn/test_options_parse.c @@ -0,0 +1,196 @@ +/* + * 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) 2025 OpenVPN Inc + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "syshead.h" + +#include +#include +#include +#include +#include +#include + +#include "options.h" +#include "test_common.h" +#include "mock_msg.h" + +void +__wrap_add_option(struct options *options, char *p[], bool is_inline, const char *file, + int line, const int level, const msglvl_t msglevel, + const unsigned int permission_mask, unsigned int *option_types_found, + struct env_set *es) +{ +} + +void +__wrap_remove_option(struct context *c, struct options *options, char *p[], bool is_inline, + const char *file, int line, const msglvl_t msglevel, + const unsigned int permission_mask, unsigned int *option_types_found, + struct env_set *es) +{ +} + +void +__wrap_update_option(struct context *c, struct options *options, char *p[], bool is_inline, + const char *file, int line, const int level, const msglvl_t msglevel, + const unsigned int permission_mask, unsigned int *option_types_found, + struct env_set *es, unsigned int *update_options_found) +{ +} + +void +__wrap_usage(void) +{ +} + +/* for building long texts */ +#define A_TIMES_256 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO" + +static void +test_parse_line(void **state) +{ + char *p[MAX_PARMS + 1] = { 0 }; + struct gc_arena gc = gc_new(); + int res = 0; + +#define PARSE_LINE_TST(string) \ + do \ + { \ + CLEAR(p); \ + res = parse_line(string, p, SIZE(p) - 1, "test_options_parse", 1, M_INFO, &gc); \ + } while (0); + + /* basic example */ + PARSE_LINE_TST("some-opt firstparm second-parm"); + assert_int_equal(res, 3); + assert_string_equal(p[0], "some-opt"); + assert_string_equal(p[1], "firstparm"); + assert_string_equal(p[2], "second-parm"); + assert_null(p[res]); + + /* basic quoting, -- is not handled special */ + PARSE_LINE_TST("--some-opt 'first parm' \"second' 'parm\""); + assert_int_equal(res, 3); + assert_string_equal(p[0], "--some-opt"); + assert_string_equal(p[1], "first parm"); + assert_string_equal(p[2], "second' 'parm"); + assert_null(p[res]); + + /* escaped quotes */ + PARSE_LINE_TST("\"some opt\" 'first\" \"parm' \"second\\\" \\\"parm\""); + assert_int_equal(res, 3); + assert_string_equal(p[0], "some opt"); + assert_string_equal(p[1], "first\" \"parm"); + assert_string_equal(p[2], "second\" \"parm"); + assert_null(p[res]); + + /* missing closing quote */ + PARSE_LINE_TST("--some-opt 'first parm \"second parm\""); + assert_int_equal(res, 0); + + /* escaped backslash */ + PARSE_LINE_TST("some\\\\opt C:\\\\directory\\\\file"); + assert_int_equal(res, 2); + assert_string_equal(p[0], "some\\opt"); + assert_string_equal(p[1], "C:\\directory\\file"); + assert_null(p[res]); + + /* comment chars are not special inside parameter */ + PARSE_LINE_TST("some-opt firstparm; second#parm"); + assert_int_equal(res, 3); + assert_string_equal(p[0], "some-opt"); + assert_string_equal(p[1], "firstparm;"); + assert_string_equal(p[2], "second#parm"); + assert_null(p[res]); + + /* comment */ + PARSE_LINE_TST("some-opt firstparm # secondparm"); + assert_int_equal(res, 2); + assert_string_equal(p[0], "some-opt"); + assert_string_equal(p[1], "firstparm"); + assert_null(p[res]); + + /* parameter just long enough */ + PARSE_LINE_TST("opt " A_TIMES_256); + assert_int_equal(res, 2); + assert_string_equal(p[0], "opt"); + assert_string_equal(p[1], A_TIMES_256); + assert_null(p[res]); + + /* quoting doesn't count for parameter length */ + PARSE_LINE_TST("opt \"" A_TIMES_256 "\""); + assert_int_equal(res, 2); + assert_string_equal(p[0], "opt"); + assert_string_equal(p[1], A_TIMES_256); + assert_null(p[res]); + + /* very long line */ + PARSE_LINE_TST("opt " A_TIMES_256 " " A_TIMES_256 " " A_TIMES_256 " " A_TIMES_256); + assert_int_equal(res, 5); + assert_string_equal(p[0], "opt"); + assert_string_equal(p[1], A_TIMES_256); + assert_string_equal(p[2], A_TIMES_256); + assert_string_equal(p[3], A_TIMES_256); + assert_string_equal(p[4], A_TIMES_256); + assert_null(p[res]); + + /* parameter too long */ + PARSE_LINE_TST("opt " A_TIMES_256 "B"); + assert_int_equal(res, 0); + + /* max parameters */ + PARSE_LINE_TST("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"); + assert_int_equal(res, MAX_PARMS); + char num[3]; + for (int i = 0; i < MAX_PARMS; i++) + { + assert_true(snprintf(num, 3, "%d", i) < 3); + assert_string_equal(p[i], num); + } + assert_null(p[res]); + + /* too many parameters, overflow is ignored */ + PARSE_LINE_TST("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"); + assert_int_equal(res, MAX_PARMS); + for (int i = 0; i < MAX_PARMS; i++) + { + assert_true(snprintf(num, 3, "%d", i) < 3); + assert_string_equal(p[i], num); + } + assert_null(p[res]); + + gc_free(&gc); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_parse_line), + }; + + return cmocka_run_group_tests_name("options_parse", tests, NULL, NULL); +}