From patchwork Wed Oct 8 10:29:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4481 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:7d42:b0:72f:f16c:e055 with SMTP id fr2csp829695mab; Wed, 8 Oct 2025 03:30:15 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCU0G7JqfsJl/AlKBUAS4QSIDvMqMD90i/D6Hu+zTjlUJrqon+/eIMVY+uYn4jZZ10dbVWOtsvnEg+o=@openvpn.net X-Google-Smtp-Source: AGHT+IEomenhA7cd5RX5fZmAOssQJyVttE9eJ56YKCA7uBNAQD5LaPZM6k3Lm3H/M4WRlDwqckBF X-Received: by 2002:a05:6870:701e:b0:395:825d:3b62 with SMTP id 586e51a60fabf-3c0fa86095amr1696319fac.45.1759919414891; Wed, 08 Oct 2025 03:30:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1759919414; cv=none; d=google.com; s=arc-20240605; b=Lp2e9jmutZC36XvCLt6c5lhGwiM84n/JksBOFfKI1HOT/uqB+L0BTdOkAKVJRSjJ8i BHd/10V2NYs8VjK8QqQRK6adLq3eVD4Z5QwwSmfQw9euF3D4c2pSuatTHCCvwwWVqd40 9FA9UUoEkBFJJ6yrrSHarcsVCs8hPZvfAfVwKcl07//aSKokeTOT7KPNshHkh3SgBah6 feZuK1e1Bmpzi6cIpsCjtAZ+ASpQYVVV3Uz+ZLCO45AcorbwSMxuZUNEKZZ8+Ikiy5Wf TApVCIhOktbxDz/IqlTvV0+tDr1zLqThfgwykUwDVvMXwr2MhnkUfzVSeD3zV0Y0Cy/v fz4w== 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=/uL38vwAU/nh1ADfD7VVDzAT91aCEexNGNreGv9+uas=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=iIdEydLPfJgYnwfshT8RLJtPOu0RMl/0Bazjf7VqrA7+iwYqyIA/K8fVnz345rC6Oe gUJdFEtbc3+F3I09ar/bEReaU5CaB/n5WsuzoxReMIFtsn4RcP1sAqAI7VZKN6r2xla7 rNhCMHCtGEhSMKfd/y9N/MyMxyHfZZFW8ZtCnivaC/tmdIxkuXv9ovo9s51z/yx0IDGa Xs7c/QLHaPQozklY+Y8Z3ZAARIPd19ICMv44f8O2Xoeg50kgdLcxkVTY7vkOvFZ40U82 +CrxScr6UaCPxvvDUjZTUUYFammKmNzMA97M2onJvShaKSCAF3mRNJXZ1Cze3Xr44Z4o gVcg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=AeTGcA2P; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="foXS//32"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="UfqB8i/W"; 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 586e51a60fabf-3be8957b116si1314786fac.80.2025.10.08.03.30.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 08 Oct 2025 03:30:14 -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=AeTGcA2P; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="foXS//32"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="UfqB8i/W"; 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=/uL38vwAU/nh1ADfD7VVDzAT91aCEexNGNreGv9+uas=; b=AeTGcA2PRiBe5wVFz9FQ5ekBA3 AbmVFWRYgD6JL2qeENGRXh70kGQ/Zfq9Qj5RwMBoE8GWXHUCOVuvC5CVt1LSgCLi7T7NHJ5H/DMpj N263CnsVFwmrD9teMwQFmhWz3ELVc1jxiExJsjCSOSydpME41nDcKL5KFK04Szp1y7jE=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1v6RQw-0002td-TS; Wed, 08 Oct 2025 10:30:10 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1v6RQu-0002tV-VM for openvpn-devel@lists.sourceforge.net; Wed, 08 Oct 2025 10:30:08 +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=fsNNoONhnhHE5CjmJJXl8T1W2JYrHdliB56VDStCkhU=; b=foXS//32qQq635VBSPFQM8quRP Olnq1neTV49ZOlLCxJqVbD8AJYUnhR/1WnZq0AuH5OyIkdNhJRfDDCI67aNJbwLEbO63wVV3BCMLw AFLWm8rBi8UoTmLYh7jtNNtYd2A0eBo996pJ2CZEqi18dd7lUHl0y00nvQDS+9aN1T6I=; 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=fsNNoONhnhHE5CjmJJXl8T1W2JYrHdliB56VDStCkhU=; b=UfqB8i/W2kyU109GLvCWclHwvy t+Nzk0P3cY3SGutf5jsOqmHPOm0+CWv+4uZIa4Iyt4mYn49y1Z2kbmfB2ZUtpUWbeiJ7DSoCAt2Vj XOK5teKE+FPawblcOoPNfoDhD/X4NhfCcMkfsHuPE/spKnRXgsiH48EP8jnvjaG/FCPk=; 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 1v6RQu-0005AF-1n for openvpn-devel@lists.sourceforge.net; Wed, 08 Oct 2025 10:30:08 +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 598AU1uF007747 for ; Wed, 8 Oct 2025 12:30:01 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.1/8.18.1/Submit) id 598AU1lX007731 for openvpn-devel@lists.sourceforge.net; Wed, 8 Oct 2025 12:30:01 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Wed, 8 Oct 2025 12:29:55 +0200 Message-ID: <20251008103001.7696-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 When parsing a "line" that is longer than the available line buffer, then buf_parse was eating up to 2 characters. It advanced past them but they were not part of the output. 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: 1v6RQu-0005AF-1n Subject: [Openvpn-devel] [PATCH v1] buffer: Fix buf_parse eating input 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?1845409260765249555?= X-GMAIL-MSGID: =?utf-8?q?1845409260765249555?= From: Frank Lichtenheld When parsing a "line" that is longer than the available line buffer, then buf_parse was eating up to 2 characters. It advanced past them but they were not part of the output. This can lead to unexpected results if buf_parse is used in a while loop on unrestricted input, like e.g. when reading configs (see in_src_get() used for check_inline_file_via_buf()). Change-Id: I3724660bf0f8336ee58c172acfb7c4f38e457393 Signed-off-by: Frank Lichtenheld Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1246 --- 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/+/1246 This mail reflects revision 1 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index c0b85b2..28de00f 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -832,19 +832,24 @@ do { - c = buf_read_u8(buf); + c = buf_peek_u8(buf); if (c < 0) { eol = true; + line[n] = 0; + break; } - if (c <= 0 || c == delim) + if (c == delim) { - c = 0; + buf_advance(buf, 1); + line[n] = 0; + break; } - if (n >= size) + if (n >= (size - 1)) { break; } + buf_advance(buf, 1); line[n++] = (char)c; } while (c); diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index 1405667..148cee0 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -771,7 +771,7 @@ } static inline int -buf_read_u8(struct buffer *buf) +buf_peek_u8(struct buffer *buf) { int ret; if (BLEN(buf) < 1) @@ -779,7 +779,17 @@ return -1; } ret = *BPTR(buf); - buf_advance(buf, 1); + return ret; +} + +static inline int +buf_read_u8(struct buffer *buf) +{ + int ret = buf_peek_u8(buf); + if (ret >= 0) + { + buf_advance(buf, 1); + } return ret; } diff --git a/tests/unit_tests/openvpn/test_buffer.c b/tests/unit_tests/openvpn/test_buffer.c index c86c19e..92c4c65 100644 --- a/tests/unit_tests/openvpn/test_buffer.c +++ b/tests/unit_tests/openvpn/test_buffer.c @@ -450,6 +450,56 @@ gc_free(&gc); } +/* for building long texts */ +#define A_TIMES_256 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO" + +void +test_buffer_parse(void **state) +{ + struct gc_arena gc = gc_new(); + struct buffer buf = alloc_buf_gc(1024, &gc); + char line[512]; + bool status; + const char test1[] = A_TIMES_256 "EOL\n" A_TIMES_256 "EOF"; + + /* line buffer bigger than actual line */ + assert_int_equal(buf_write(&buf, test1, sizeof(test1)), true); + status = buf_parse(&buf, '\n', line, sizeof(line)); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256 "EOL"); + status = buf_parse(&buf, '\n', line, sizeof(line)); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256 "EOF"); + + /* line buffer exactly same size as actual line + terminating \0 */ + buf_reset_len(&buf); + assert_int_equal(buf_write(&buf, test1, sizeof(test1)), true); + status = buf_parse(&buf, '\n', line, 260); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256 "EOL"); + status = buf_parse(&buf, '\n', line, 260); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256 "EOF"); + + /* line buffer smaller than actual line */ + buf_reset_len(&buf); + assert_int_equal(buf_write(&buf, test1, sizeof(test1)), true); + status = buf_parse(&buf, '\n', line, 257); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256); + status = buf_parse(&buf, '\n', line, 257); + assert_int_equal(status, true); + assert_string_equal(line, "EOL"); + status = buf_parse(&buf, '\n', line, 257); + assert_int_equal(status, true); + assert_string_equal(line, A_TIMES_256); + status = buf_parse(&buf, '\n', line, 257); + assert_int_equal(status, true); + assert_string_equal(line, "EOF"); + + gc_free(&gc); +} + int main(void) { @@ -478,7 +528,8 @@ cmocka_unit_test(test_character_class), cmocka_unit_test(test_character_string_mod_buf), cmocka_unit_test(test_snprintf), - cmocka_unit_test(test_buffer_chomp) + cmocka_unit_test(test_buffer_chomp), + cmocka_unit_test(test_buffer_parse) }; return cmocka_run_group_tests_name("buffer", tests, NULL, NULL);