From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0F54B364045; Sun, 15 Mar 2026 21:16:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609417; cv=pass; b=QAsOznxMTIQDYICnDq0awVYODxPyFCYb5TzDaC2Kvos+LGRI6VuC5DqKmot3SJUjbbVHPBwevz6eU8ASTz4S8qoe+6t+vaD5ZFYhhKZ1hk5luGOtTYuvf+43G2FxrNIKD8TRRWK1CSqZyqEyCEUKMidOQeelSeRWKXa+HxHQ7sU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609417; c=relaxed/simple; bh=TvoodWqX4Zt9qaZn8/cmtP96TLJg6Fl3uNkMx+/OM/s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UoFdGsAjCDb9LkYZC43baPw67dzfdg0ldIcKyqRdFnGsT94QnAnncTaCf5gTS+1PPn80QmLKXMb5xTW74ZM/K5iIl7winYIphohxvDn9QwmX4bAUkEGatDeG5O4q8cwWd8kYSw8oaZMvF4mxvkOXckqdoDssvaO7X/OevKJ8W50= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=h5xlBtQc; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="h5xlBtQc" ARC-Seal: i=1; a=rsa-sha256; t=1773609406; cv=none; d=zohomail.eu; s=zohoarc; b=DsZldlkd/UBh6TfV+VHX+s1TRPO0SZ5H9vFvhicpZPMvqIHMzSjAJQgn5WK69hdvDeNEF1lJdU3h5GQQu0kQ6OqEJpCCjilCf+rFHJR0p9BaW9cyRWfVr6TfNKx943V0DMwsL4hKXhIj1L8EMi/TrKRRxk6kiN2ONeu/OrcK/wQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609406; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=IKJGSUF4neu8mf6CKhF1x8j3j8JrAeeYnr9Wq9xiqSo=; b=QQZWrMfSMLFooplGjSEPcl+GZLbulxSVmKiS9WmXmurk5wLhPqzyuwHSnjCThN6X0aIgP8jhimS1i0WdFwNfT45ZwJLbzUV9lqxClW5GVcAQ0HEBQzqLLyB0g+zFJiXoeYHimkxpbKUBC84l8NMTXODm8z/ZSdC6BQCdfnNr0oA= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609405; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=IKJGSUF4neu8mf6CKhF1x8j3j8JrAeeYnr9Wq9xiqSo=; b=h5xlBtQck2j9haXSZCGvm6+VQwVZ/OY5Ig96qg17//X6BcGh1Xcnc6Bce+/bNmZJ kNUQdxuGrN90FiutGh+ezPFjhqWGfrtgBxnJag2DI+vbpfOY45CS3BUrKwjeH9ieQgK gncmHn3fPK0UMxdN6B6qXCX8ezLp7iUIGgv4VfZ8= Received: by mx.zoho.eu with SMTPS id 177360940411717.37568035027789; Sun, 15 Mar 2026 22:16:44 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 1/8] lib/glob: normalize inverted character class ranges Date: Sun, 15 Mar 2026 21:16:30 +0000 Message-Id: <20260315211641.408318-3-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" When a character class range has its endpoints reversed (e.g., [z-a]), the comparison a <=3D c && c <=3D b can never be true, so the range silently matches nothing. A pattern like "file[9-0]" intended to match any digit would fail to match anything, with no indication that the range is backwards. Swap the endpoints when a > b so that inverted ranges behave the same as their forward equivalents: [z-a] matches the same characters as [a-z], and [9-0] matches the same as [0-9]. This is consistent with how GNU fnmatch and other glob implementations handle reversed ranges. Signed-off-by: Josh Law --- lib/glob.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/glob.c b/lib/glob.c index 7aca76c25bcb..cb45a9a47f28 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -94,7 +94,13 @@ bool __pure glob_match(char const *pat, char const *str) goto literal; =20 class +=3D 2; - /* Any special action if a > b? */ + /* Normalize inverted ranges like [z-a] */ + if (a > b) { + unsigned char tmp =3D a; + + a =3D b; + b =3D tmp; + } } if (a <=3D c && c <=3D b) match =3D true; --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7197D35F609; Sun, 15 Mar 2026 21:16:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609417; cv=pass; b=slcKa+qIhEIHcojBpwga1yYDixTHV0KaKcN+jMHYEv8P/R1V46dBPwYEPNqPUiBGWfe1nKkfeJ1dOKx9j5Ak7GzDe+OFveIiiuPDcUwXR2A1xX10aDzFyB+zlwYCQsSwJDTqhGS4UBKH3bKmzKewHTtuOMzfklGM6vP4GkuKgKo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609417; c=relaxed/simple; bh=polKK+TVvNhEByk+/eHx32xRBSbjq2Xd9H4Z2XJ6PcI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=c80ap1XJLpygK7CabsMH+25CPbxzVf5se6oWXpWFQg/wxRebIisUel0p6GJ29QdCtCHY34Ivek85SAWT5O89Kk/vNJ8xVC72o8AIJ9KDw+RNNEegeiEcUkKwcd2IpbtRNvF2HM5fkyCT1/As09mwFC/8dS6MpZ+iZU7fiPxxhaE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=j9dFPYux; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="j9dFPYux" ARC-Seal: i=1; a=rsa-sha256; t=1773609405; cv=none; d=zohomail.eu; s=zohoarc; b=cUIjjtIrQcO2JmeN9BBx/quSy3R6LtkZo+Dcg3kjeafDzlJ02dBgXNmFI37IqQJyaPaWVnmL9Tznlc8/jV9bjUD78lyW3yKbQJ9qV7nMqfS8FWrhpggjJFyMe9jpJjfzsZ0cbWEH+xDMo3qwzb0C6gUqmcnWOwWPpN5a48Wnnfo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609405; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=wV6NoXecECb7bqi4ET6OkCEvhdV779F9FKJzjGTMHkA=; b=C5k3AHBsejh8P5eVTe5Vj3DIRis3Y0J66UJgoKK1EZPq3OljCxZQoZYDQzHhPudjPalbSLQyhT9JxmQL0XX2Dq0Cz1oLHPMGrmnS6CohnHdR0s5C5FuYnOote256w7l6PhHImYLpauKHofarOR94fMD+kakTWGWmnxikTb5UiCE= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609405; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=wV6NoXecECb7bqi4ET6OkCEvhdV779F9FKJzjGTMHkA=; b=j9dFPYux48g7UdwSJeLTCwi8wRChVHduati3WqZ41bzzBqrwiJ6wV/PShtYf5TBr g3rljnrIIQCpyUx2TC8hqljWWgGNpusGgqZU3JN936fXRn603zE6TcKKs+LqJKOxSJH RUEtkFVvRwDzNTX5hGwHCUn9yl9nl6ET6sjeQsQ4= Received: by mx.zoho.eu with SMTPS id 1773609403462239.15358876651385; Sun, 15 Mar 2026 22:16:43 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v2 1/5] lib/glob: add case-insensitive glob_match_nocase() Date: Sun, 15 Mar 2026 21:16:29 +0000 Message-Id: <20260315211641.408318-2-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add a case-insensitive variant of glob_match() for callers that need to match patterns regardless of case. The immediate motivation is the ATA device quirk denylist in drivers/ata/libata-core.c, which uses glob_match() to match drive model and firmware revision strings. ATA IDENTIFY DEVICE data is space-padded ASCII and the specification does not mandate a particular case, so a denylist entry could miss a drive that reports its model string in unexpected casing. Switching the denylist to glob_match_nocase() (in a follow-up ATA patch) would make it robust against such variation. Refactor the matching logic into a static __glob_match() helper that takes a bool nocase parameter, and implement both glob_match() and glob_match_nocase() as thin wrappers. When nocase is true, literal characters and character class endpoints are folded through tolower() before comparison. Signed-off-by: Josh Law --- include/linux/glob.h | 1 + lib/glob.c | 75 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/include/linux/glob.h b/include/linux/glob.h index 861327b33e41..36527ae89730 100644 --- a/include/linux/glob.h +++ b/include/linux/glob.h @@ -6,5 +6,6 @@ #include /* For __pure */ =20 bool __pure glob_match(char const *pat, char const *str); +bool __pure glob_match_nocase(char const *pat, char const *str); =20 #endif /* _LINUX_GLOB_H */ diff --git a/lib/glob.c b/lib/glob.c index c5508be0d215..172b8ba3cd8e 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) +#include #include #include #include @@ -11,8 +12,8 @@ MODULE_DESCRIPTION("glob(7) matching"); MODULE_LICENSE("Dual MIT/GPL"); =20 -/** - * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) +/* + * __glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) * @pat: Shell-style pattern to match, e.g. "*.[ch]". * @str: String to match. The pattern must match the entire string. * @@ -20,7 +21,7 @@ MODULE_LICENSE("Dual MIT/GPL"); * succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str,= 0). * * Pattern metacharacters are ?, *, [ and \. - * (And, inside character classes, !, - and ].) + * (And, inside character classes, !, ^ - and ].) * * This is a small and simple implementation intended for device denylists * where a string is matched against a number of patterns. Thus, it @@ -39,7 +40,7 @@ MODULE_LICENSE("Dual MIT/GPL"); * * An opening bracket without a matching close is matched literally. */ -bool __pure glob_match(char const *pat, char const *str) +static bool __pure __glob_match(char const *pat, char const *str, bool noc= ase) { /* * Backtrack to previous * on mismatch and retry starting one @@ -58,6 +59,11 @@ bool __pure glob_match(char const *pat, char const *str) unsigned char c =3D *str++; unsigned char d =3D *pat++; =20 + if (nocase) { + c =3D tolower(c); + d =3D tolower(d); + } + switch (d) { case '?': /* Wildcard: anything but nul */ if (c =3D=3D '\0') @@ -94,13 +100,17 @@ bool __pure glob_match(char const *pat, char const *st= r) goto literal; =20 class +=3D 2; - /* Normalize inverted ranges like [z-a] */ - if (a > b) { - unsigned char tmp =3D a; + } + if (nocase) { + a =3D tolower(a); + b =3D tolower(b); + } + /* Normalize inverted ranges like [z-a] */ + if (a > b) { + unsigned char tmp =3D a; =20 - a =3D b; - b =3D tmp; - } + a =3D b; + b =3D tmp; } if (a <=3D c && c <=3D b) match =3D true; @@ -112,8 +122,11 @@ bool __pure glob_match(char const *pat, char const *st= r) } break; case '\\': - if (*pat !=3D '\0') + if (*pat !=3D '\0') { d =3D *pat++; + if (nocase) + d =3D tolower(d); + } fallthrough; default: /* Literal character */ literal: @@ -132,4 +145,44 @@ bool __pure glob_match(char const *pat, char const *st= r) } } } + +/** + * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) + * @pat: Shell-style pattern to match, e.g. "*.[ch]". + * @str: String to match. The pattern must match the entire string. + * + * Perform shell-style glob matching, returning true (1) if the match + * succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str,= 0). + * + * Pattern metacharacters are ?, *, [ and \. + * (And, inside character classes, !, ^ - and ].) + * + * This is small and simple and non-recursive, with run-time at most + * quadratic: strlen(@str)*strlen(@pat). It does not preprocess the + * patterns. An opening bracket without a matching close is matched + * literally. + * + * Return: true if @str matches @pat, false otherwise. + */ +bool __pure glob_match(char const *pat, char const *str) +{ + return __glob_match(pat, str, false); +} EXPORT_SYMBOL(glob_match); + +/** + * glob_match_nocase - Case-insensitive shell-style pattern matching + * @pat: Shell-style pattern to match. + * @str: String to match. The pattern must match the entire string. + * + * Identical to glob_match(), but performs case-insensitive comparisons + * for literal characters and character class contents using tolower(). + * Metacharacters (?, *, [, ]) are not affected by case folding. + * + * Return: true if @str matches @pat (case-insensitive), false otherwise. + */ +bool __pure glob_match_nocase(char const *pat, char const *str) +{ + return __glob_match(pat, str, true); +} +EXPORT_SYMBOL(glob_match_nocase); --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3AA95373BEB; Sun, 15 Mar 2026 21:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609418; cv=pass; b=Wkt0b0adkfxyu928NHNmAh5FWSMYX4mdqu2EsLWHPuPLexA2dFKxqA8dH2H2fz1g2SqdDmRStWN5EjelXi/x1hIb+us0Q5w6VuriqSmoc6sDVSPstV6389PPBDOuVT6PsRXq+Hw/Iijeo8uEGpH96h8/kh4JNqg5DQrOeo2yHZA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609418; c=relaxed/simple; bh=NK8NcdJxCO2LV2WJNqfKBaNOOeGuUndAUUlIXnyHtxA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=H3nW32DntJ/09nfm/X9xZ6nlF7XDTFEnhhVVMIVhJpWvX1/IysAVhvr/JPZEkt5XHi+NapjrEQLMXpTTRPJiuiv2x/zuLh1NAF834p/mqVaGBFIKk3j/yHOsikdJIRWTvydpJXoZV3rMps9u7czoilbwIVJibIVKQjqLqr7u6wo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=DQbuRLv9; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="DQbuRLv9" ARC-Seal: i=1; a=rsa-sha256; t=1773609407; cv=none; d=zohomail.eu; s=zohoarc; b=MQr5XGHJXKJkbYEZIeuTv/NsJcK89hPd7BCNpq94AXLqojHIQSpBNZxclUBvtv5do+OUo7RidLrzfzzhRk5vTUmgxYehVrTuBfYOL2G+y5Y5D6/4qyIrPGAz3bjugbMfrju4vdYfy6SO2eRF1FT6wXhzyQpsvQAqKFCupFlr+iE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609407; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZH0GCSbT5tKftFXXPeA2gjcQUx1mgWMeocoKefb8MuM=; b=gbkh8yxNkntj84QwT4Hz3Gx2EvbZzyRFi1rcXT1AbOtbQU1lKN4AV4AgJY3NeYUCFc7LcwsanVmiHsYlK4jTKq3jG/8/hcZc9w/YCsC33k/XCsYBX7xFJkGRvOZElTzI8Jd/LjveOHtnV5TzNJlRB0bLS1NnAGB3dfMb7sX7OrU= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609407; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=ZH0GCSbT5tKftFXXPeA2gjcQUx1mgWMeocoKefb8MuM=; b=DQbuRLv9JvoJc7Q8K+e9f2Yvkwc6bxeSA98uSjeUwyOgKPmeacZqsyURquQQbmmG ckwZxyBiyS+XxFNya2+O14HhGA/PDkwcjNbWDOE0ikrGxQ9fLYDKn8RIBfcGwVrO/rz CXCfKh47gIOWY74ZiS2zOIvrn+LpFvNwsBvLGcQI= Received: by mx.zoho.eu with SMTPS id 1773609404755626.5514401154636; Sun, 15 Mar 2026 22:16:44 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v2 2/5] lib/glob: add glob_validate() for pattern syntax checking Date: Sun, 15 Mar 2026 21:16:31 +0000 Message-Id: <20260315211641.408318-4-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add glob_validate() which checks whether a glob pattern is syntactically well-formed before matching. It detects: - Unclosed character classes: a '[' with no matching ']' - Trailing backslash: a '\' at end of pattern with nothing to escape glob_match() already handles these gracefully (unclosed brackets are matched literally, a trailing backslash matches itself), but callers that accept patterns from userspace may want to reject malformed input upfront with a clear error rather than silently falling back to literal matching. For example, the kunit executor accepts a filter_glob module parameter to select which tests to run. A user who types "snd_*.[codec_test" (forgetting the closing bracket) would currently see the '[' matched literally instead of starting a character class, producing silently wrong filter results. With glob_validate(), the executor can reject the pattern early and report -EINVAL, as done in the following patch. Signed-off-by: Josh Law --- include/linux/glob.h | 1 + lib/glob.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/linux/glob.h b/include/linux/glob.h index 36527ae89730..deceaa2e4a74 100644 --- a/include/linux/glob.h +++ b/include/linux/glob.h @@ -7,5 +7,6 @@ =20 bool __pure glob_match(char const *pat, char const *str); bool __pure glob_match_nocase(char const *pat, char const *str); +bool __pure glob_validate(char const *pat); =20 #endif /* _LINUX_GLOB_H */ diff --git a/lib/glob.c b/lib/glob.c index 172b8ba3cd8e..8ee539d19cc4 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -186,3 +186,46 @@ bool __pure glob_match_nocase(char const *pat, char co= nst *str) return __glob_match(pat, str, true); } EXPORT_SYMBOL(glob_match_nocase); + +/** + * glob_validate - Check whether a glob pattern is well-formed + * @pat: Shell-style pattern to validate. + * + * Return: true if @pat is a syntactically valid glob pattern, false + * if it contains malformed constructs. The following are considered + * invalid: + * + * - An opening '[' with no matching ']' (unclosed character class). + * - A trailing '\' with no character following it. + * + * Note that glob_match() handles these gracefully (an unclosed bracket + * is matched literally, a trailing backslash matches itself), but + * callers that accept patterns from user input may wish to reject + * malformed patterns early with a clear error. + */ +bool __pure glob_validate(char const *pat) +{ + while (*pat) { + switch (*pat++) { + case '\\': + if (*pat =3D=3D '\0') + return false; + pat++; + break; + case '[': + if (*pat =3D=3D '!' || *pat =3D=3D '^') + pat++; + /* ] as first character is literal, not end of class */ + if (*pat =3D=3D ']') + pat++; + while (*pat && *pat !=3D ']') + pat++; + if (*pat =3D=3D '\0') + return false; + pat++; /* skip ']' */ + break; + } + } + return true; +} +EXPORT_SYMBOL(glob_validate); --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B862D37CD3E; Sun, 15 Mar 2026 21:16:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609420; cv=pass; b=dkIk7eU7iuIGuvViGuR7WOzhtkXd2ypzbfvQr57qA8iU6yHZxKvFJqFPMg+9O8k56n8wT+sb0EVNxonI3Uf53mtw8xvgYQkCw0Ebz3C14WJvBqSZ/snYsqJ9ri37FA+coiNu5O4Qllwsb1gTjZ5xBdKzNiChPS4mOzhfqc6dpxs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609420; c=relaxed/simple; bh=ynosWAVdTZjwHIldBKnJyOHFf6YCnzrYK/oMhyqjJmI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sM1O+I3Y8MkqpcnetIemRbQ9fPRofuPwSD9ZGslwoRW+kfVbuONsXtLEU+0z6MJqTqHe3ch3pQ9HVYS8TPJkazwf/nzBTG3kWUuhrUJCgqcBH5NnRoMNZ2bQmteAJlRVED6pm9xcNiQUcpzy3Q476lJ+IoYJN/+Ht/rhl9PFwIs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=brJk9q0q; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="brJk9q0q" ARC-Seal: i=1; a=rsa-sha256; t=1773609407; cv=none; d=zohomail.eu; s=zohoarc; b=chiN4gIxo0hfVrKKVuDiCdQ5EaQ98yniXABHBmWoKRF/geDAPZSvCtS9l0YQGxe3FQPPaB7SVwYEt2CRyiwohHZ8v7v8d297EXKwFhjsn7KUECY/+BbfRIlUv+2QUDM+9LTQIfJUHI0Pk5i1TA0uGOaRTpH7DDj0iljC/F7usSg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609407; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=ueSZI5AfyJ2dJY/ym+gJvwLv50twR0Whfk1qSI94zoM=; b=CB7XBeJSUKXvy8PO9ODREv9Ep/eVIfz29TsL4a1RC4v7m88qIz4u28R5xfNTed5MD591vzohULzXSSBsWbnNRq938BpZhaICQ8+ZfFANUo1ERqxZcf5G4cyE+IbE0cyljGyQ7WUbsmSwTfdCLTEFmcE0TcSovOkzX7E9m7heMBc= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609407; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=ueSZI5AfyJ2dJY/ym+gJvwLv50twR0Whfk1qSI94zoM=; b=brJk9q0q3rN7RoE9kXMqyM/aQ4U8jQjXupnFvNXTdpgVLXqH4g1mnuOUAyHyi2Tk vKwQeRh+fTu4/1dBkLedUPtgh37bdQhXrJGqL4vzwoFMiOYDLIm8bUDvpUZOVzU44gC t4oF1YLoo0W5ODPZKrRdsLNGJAnVXbdzVG0i4WT0= Received: by mx.zoho.eu with SMTPS id 1773609405416218.4258200308409; Sun, 15 Mar 2026 22:16:45 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 2/8] lib/glob: treat trailing backslash as literal character Date: Sun, 15 Mar 2026 21:16:32 +0000 Message-Id: <20260315211641.408318-5-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" A pattern ending with a lone backslash (e.g., "path\\") reads the NUL terminator as the escaped character, making the backslash effectively match end-of-string rather than a literal '\' character. This means glob_match("path\\", "path\\") would fail since the pattern consumes the NUL early, while glob_match("path\\", "path") would unexpectedly succeed. Guard the escape so that a trailing backslash keeps d =3D '\\' and falls through to literal matching, which is the intuitive behavior: a trailing backslash matches a literal backslash character. Signed-off-by: Josh Law --- lib/glob.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/glob.c b/lib/glob.c index cb45a9a47f28..df7f00619b1b 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -112,7 +112,8 @@ bool __pure glob_match(char const *pat, char const *str) } break; case '\\': - d =3D *pat++; + if (*pat !=3D '\0') + d =3D *pat++; fallthrough; default: /* Literal character */ literal: --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F0E8374730; Sun, 15 Mar 2026 21:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609418; cv=pass; b=LiZvnsnx+8jfSLZeMeVU7Gdit/RT85Xyd04aMb2WF49VadADFG6geOvOM6fxW1GLTgySu0O6jn8YWiOOZynHNgfzjyZFDRtK2SY0id6LdiYsqjWLRGA4T3g0nQW92aA11hoRSsTGkTj5HNUvGrhNhA5T9faKKDQU9icri27X8uM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609418; c=relaxed/simple; bh=XgWFRb8ONcA2GQ/HdeRNANjgs9ScGEr/4d+esA/Kb7c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nGxmulUTmCQfWRrFGFTw8P/W8pwEPfPsOtAVRgmUl7QGF37209Ivkgd+wO/hEQb7+o9wT7N/Oq0iPGgnCmQKv2FPsQkA1SG0PZc0tw29qW7V4nJdDCSdbk28VKSVU7/HiyZh0lqUl/QdzmBOXkNnwEXWtu/dMjI5yyHG96VRg6Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=kPN6H4LK; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="kPN6H4LK" ARC-Seal: i=1; a=rsa-sha256; t=1773609408; cv=none; d=zohomail.eu; s=zohoarc; b=lNef373UeMm0iTQWWKrHcct/tu4eWkXuoq1YrcJmXNoowTPVX2utToTSG8VUJkKlkcYKdZj/OzMgxEcGpAELDDMWTPMZsd5BTe3nZsbVTXJpDpFz4C9+hgs4mmaEGCSwtq9Enh5vJEVsVMo4U90yFsTijguR1idtLkyHpmaV8OE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609408; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=6MFsWg559qWHVDZpDzdEbMHixOdjZsqRsUni07ha0iI=; b=OLFDFzqsVZLxXpDriXqvNhsuu2C8Eu7+XopA5yfh6K5DQ2u2PsNcAdYOrQssr4ys03B12MpC4TsVkIVsAZu21YV0AM6CAqbbOA4B6I5H2qkrdbGpfT5mthKtYhax+z11umJL2Be7/uQS2bFFsTIel5jQszzYpFrtPxRC1ZLf3o8= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609407; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=6MFsWg559qWHVDZpDzdEbMHixOdjZsqRsUni07ha0iI=; b=kPN6H4LKvc7zWCP/shk0uVhACzcOMqOsocQa6iSygoiYD9kKeOdYHvGj4RniL4F3 PfCOzo13yrDkItGYdRcjUmt+xC5fd9M8RK5pT5gWFuqtsKZ0WiQGWMV/TdL7Q9Twf6M Z85fwPYHHEjgbXoNiskqR93fOBNLf9FH4S9mq7/w= Received: by mx.zoho.eu with SMTPS id 1773609406065337.3837088591996; Sun, 15 Mar 2026 22:16:46 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 3/8] lib/glob: accept [^...] as character class negation syntax Date: Sun, 15 Mar 2026 21:16:33 +0000 Message-Id: <20260315211641.408318-6-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" glob(7) specifies [!...] for negated character classes, but many users are more familiar with the regex-style [^...] syntax. Tools like git, rsync, and bash all accept both forms, and the difference is a common source of confusion when writing glob patterns. Accept '^' as an alias for '!' at the start of a character class so that both [!a-z] and [^a-z] work as expected. Signed-off-by: Josh Law --- lib/glob.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/glob.c b/lib/glob.c index df7f00619b1b..c5508be0d215 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -33,9 +33,9 @@ MODULE_LICENSE("Dual MIT/GPL"); * Like !fnmatch(@pat, @str, 0) and unlike the shell, this does NOT * treat / or leading . specially; it isn't actually used for pathnames. * - * Note that according to glob(7) (and unlike bash), character classes - * are complemented by a leading !; this does not support the regex-style - * [^a-z] syntax. + * Note that according to glob(7), character classes are complemented by + * a leading !. The regex-style [^a-z] syntax is also accepted as an + * alias. * * An opening bracket without a matching close is matched literally. */ @@ -72,7 +72,7 @@ bool __pure glob_match(char const *pat, char const *str) case '[': { /* Character class */ if (c =3D=3D '\0') /* No possible match */ return false; - bool match =3D false, inverted =3D (*pat =3D=3D '!'); + bool match =3D false, inverted =3D (*pat =3D=3D '!' || *pat =3D=3D '^'); char const *class =3D inverted ? pat + 1 : pat; unsigned char a =3D *class++; =20 --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B15A737C90C; Sun, 15 Mar 2026 21:16:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609419; cv=pass; b=fud8CWiQql+jDTuTt2Mf4eJE2reR55y0I/SrtmIAkm7vqRVobLkg8A9keAavCDoFqUevQS2/wOKmasVghx3jNklhw8Iap8d+6R7TjYD6Kfk/5aeC1DTP/lCrdL0AaO+masnV7qinsz2Dh/DNgLoc/i/QOJUyeTZvKGTgNYQ0vBY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609419; c=relaxed/simple; bh=DqDIHMd4MJlmLaUnm4FNNfD7TmiR4u66qXh4CXNuOwo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kiPKzfy8BvTlyoqFk8ToWq05gwHf/EgpVnXSoGAfmvQ+BIeR2Jz6BsajP+ARXVpqlggG78zf3uV7UxoeO+QndNY54R0FfbDcXtXM0+kCIXTvBTeRSZ3q9HXRAL8TRgB0iOu42N/oF1KIal0VoSSIbWVcRjs+S7kRItCu9Rj6MVo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=mRKvtOrA; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="mRKvtOrA" ARC-Seal: i=1; a=rsa-sha256; t=1773609408; cv=none; d=zohomail.eu; s=zohoarc; b=lf8gOwNzs/6s9S6FOheTFv/NAmKKwLAz3V9pKOOY7EAxHq4xxqxCniJ/4R5yqoJNZOWapw8RYiasrkAeOsV9/KqA7iNEUZWg9Z+VF7M38cT4hk8lWAwJKP1OzaVM7XVviM3NpUcsJBxxazkqplreQE4ZtXbdWjziv+e0tAa1Lio= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609408; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=f220kEhJ66X+jXJtp71OpS8vD3cCaDjeBL3VruhruPw=; b=Bz3+lbamzurYIo0APAIpnPx5Ic4ylNBr4tzRArbiN9d2XBLcZS0ufWfAesgLZIpQvjEABnoP06hNkdpo2jL0AvS4hUuXWsS/9IVZ2g4aVtz27Q0zJKWTvKq0YylB7bb9Tso+BrmF/NE75D6gFuweppZvsNCEhTrSMYUTyWSQaFA= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609408; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=f220kEhJ66X+jXJtp71OpS8vD3cCaDjeBL3VruhruPw=; b=mRKvtOrAR5+aynrUnR0JQNyO6z4mZUboVkpZRCIF01b1w6zUSkjIlQyaBmWTVjM3 FPdvSGYpbpdjUJrazlbOOYhTHZnI7G2tv1KNp4bAVNojnePyQglOXQPRcnKVc7HeOXd 2mcNbpA87xdghBxSgnGlM1Dwetv5Vk6KEicVD6n4= Received: by mx.zoho.eu with SMTPS id 1773609406740167.70234176599104; Sun, 15 Mar 2026 22:16:46 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v2 3/5] lib/tests: add glob test cases for escapes, edge cases, and new features Date: Sun, 15 Mar 2026 21:16:34 +0000 Message-Id: <20260315211641.408318-7-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" The glob kunit test suite had no coverage for backslash escape sequences, and was missing edge cases around wildcards with empty strings, inverted ranges, unclosed brackets, and consecutive wildcards. Add test cases covering: - Backslash escapes: \*, \?, \[, \\, non-metachar after backslash, and trailing backslash matching a literal '\' character. - Wildcards matching special characters in the string (*, [, \, ?). - Wildcards with empty strings: * matches empty, ** matches empty, ? does not match empty. - Inverted (backwards) ranges: [z-a] and [9-0] now match thanks to endpoint normalization. - Single-character ranges: [a-a] matches 'a'. - Caret negation: [^a] and [^a-z] as alias for [!...]. - Unclosed bracket: [ treated as literal. - Consecutive wildcards: ***a, *?*, *?*?* patterns. Signed-off-by: Josh Law --- lib/tests/glob_kunit.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c index 362b1eda8e5b..9b53060e7c8e 100644 --- a/lib/tests/glob_kunit.c +++ b/lib/tests/glob_kunit.c @@ -80,6 +80,53 @@ static const struct glob_test_case glob_test_cases[] =3D= { { .pat =3D "*bc", .str =3D "bc", .expected =3D true }, { .pat =3D "*bc", .str =3D "bbc", .expected =3D true }, { .pat =3D "*bc", .str =3D "bcbc", .expected =3D true }, + /* Backslash escape sequences */ + { .pat =3D "\\*", .str =3D "*", .expected =3D true }, + { .pat =3D "\\*", .str =3D "a", .expected =3D false }, + { .pat =3D "\\?", .str =3D "?", .expected =3D true }, + { .pat =3D "\\?", .str =3D "a", .expected =3D false }, + { .pat =3D "\\[", .str =3D "[", .expected =3D true }, + { .pat =3D "\\[", .str =3D "a", .expected =3D false }, + { .pat =3D "a\\bc", .str =3D "abc", .expected =3D true }, + { .pat =3D "\\\\", .str =3D "\\", .expected =3D true }, + { .pat =3D "\\\\", .str =3D "a", .expected =3D false }, + /* Trailing backslash (matches literal backslash) */ + { .pat =3D "a\\", .str =3D "a\\", .expected =3D true }, + { .pat =3D "a\\", .str =3D "a", .expected =3D false }, + /* Wildcards matching special characters in string */ + { .pat =3D "?", .str =3D "*", .expected =3D true }, + { .pat =3D "?", .str =3D "[", .expected =3D true }, + { .pat =3D "?", .str =3D "\\", .expected =3D true }, + { .pat =3D "?", .str =3D "?", .expected =3D true }, + /* Wildcards with empty strings */ + { .pat =3D "*", .str =3D "", .expected =3D true }, + { .pat =3D "*", .str =3D "a", .expected =3D true }, + { .pat =3D "**", .str =3D "", .expected =3D true }, + { .pat =3D "**", .str =3D "abc", .expected =3D true }, + { .pat =3D "?", .str =3D "", .expected =3D false }, + /* Inverted (backwards) ranges */ + { .pat =3D "[z-a]", .str =3D "m", .expected =3D true }, + { .pat =3D "[z-a]", .str =3D "z", .expected =3D true }, + { .pat =3D "[z-a]", .str =3D "a", .expected =3D true }, + { .pat =3D "[9-0]", .str =3D "5", .expected =3D true }, + { .pat =3D "[9-0]", .str =3D "a", .expected =3D false }, + /* Single-character range */ + { .pat =3D "[a-a]", .str =3D "a", .expected =3D true }, + { .pat =3D "[a-a]", .str =3D "b", .expected =3D false }, + /* Caret negation syntax */ + { .pat =3D "[^a]", .str =3D "b", .expected =3D true }, + { .pat =3D "[^a]", .str =3D "a", .expected =3D false }, + { .pat =3D "[^a-z]", .str =3D "0", .expected =3D true }, + { .pat =3D "[^a-z]", .str =3D "m", .expected =3D false }, + /* Unclosed bracket (treated as literal) */ + { .pat =3D "[", .str =3D "[", .expected =3D true }, + { .pat =3D "[", .str =3D "a", .expected =3D false }, + { .pat =3D "[abc", .str =3D "[abc", .expected =3D true }, + /* Consecutive wildcards */ + { .pat =3D "***a", .str =3D "a", .expected =3D true }, + { .pat =3D "*?*", .str =3D "a", .expected =3D true }, + { .pat =3D "*?*?*", .str =3D "ab", .expected =3D true }, + { .pat =3D "*?*?*", .str =3D "a", .expected =3D false }, /* Multiple asterisks (complex backtracking) */ { .pat =3D "*ac*", .str =3D "abacadaeafag", .expected =3D true }, { .pat =3D "*ac*ae*ag*", .str =3D "abacadaeafag", .expected =3D true }, --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44ADF37C913; Sun, 15 Mar 2026 21:17:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609426; cv=pass; b=E4Og7vm5ZJo3cJ/nNlNjd5W40Ra8nGsSLcdXUSp+pm5H5PusPI6JdJITllSgBm143Jxe8krTJAwPGOG4tqqNL6g3nbzrf1fCfFhW2TXnQEEwTuN9IdK3trswYWH1l1hlGtOCBsJLTkryzsIhhImKM2wQzHg2F+GALvGd9qXRpRk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609426; c=relaxed/simple; bh=MrFEroHwYorqSWGBoY5ocHzyEC+JzAla+WphZ3zVa6Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=M4bCVU61sLYO0A3LJVM3lQWO+o9vjnuUS8xyh9I/WHmx9zuZc0Ekm0i2dW1D7JD296wDOyNpx9gU0nQ7spLWim/9jbisXcFNoSY8YDkjrsuloyBmIgB77A0Dwtv2ZpLXbB9rLDZ8JPRB4y2WRlXomJED6bPD7oTUpBJ9sJb3YCw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=HZTg+LP+; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="HZTg+LP+" ARC-Seal: i=1; a=rsa-sha256; t=1773609409; cv=none; d=zohomail.eu; s=zohoarc; b=jzE9RKYreXfyZgmscpA1JrQkgUlTIbPKzqdOmg15ebAeV9eEU2cGRWUHL0PRN5+7Q6NQCa0gTTzQAWQZmVS9QtPtFQZ/9FkcVViP0yXvaEPZXjzmDmuF17f3qh6J/HjmEe+SEEALzoSFma3cNLsxBjpViSeF5tMxF6xE6pQtINM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609409; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=/JtZCIPsgGracX5Mx/4hRAMi9BpwqYEGpkwpzrg8Moo=; b=IuxZRZoLdHFL7wqG0/0MhtWw5wRA45JYzUVoZ7NgUuDLcuz1l5cWLFjieP1zgYNr3AZhamJj4QpJ2JrlxEgoEW5noUTto34W8Qy9IDiHkbLtDQXJVdIw7EPVCNlL1xUQEAdmeCCApRH11p78+1c4Pk1frMOOjZa8JyMZlU0KVRo= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609409; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=/JtZCIPsgGracX5Mx/4hRAMi9BpwqYEGpkwpzrg8Moo=; b=HZTg+LP+2SkjNBe3fBD31ccvGwn+hJFbifX1ofVVvcdFfOH0boML6UoPEqFRmgBR Sxwtf/kj6Dqcu4c3VhcfarVZi94FNrBrdogDY0q9UWIIPudOv0bbuiehgr/vrrhz9Sx gKNyiIgCi4CGzdxfhh0aXMDJsWFKPDAW48i10fAw= Received: by mx.zoho.eu with SMTPS id 1773609408132790.0034136864398; Sun, 15 Mar 2026 22:16:48 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v2 4/5] lib/tests: add kunit tests for glob_match_nocase() and glob_validate() Date: Sun, 15 Mar 2026 21:16:36 +0000 Message-Id: <20260315211641.408318-9-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add parameterized test cases for the new glob API functions: glob_match_nocase() tests verify case-insensitive matching for literal characters, wildcards, character class ranges, and backslash escapes -- e.g., pattern "a*c" matches string "ABC", and range [A-Z] matches lowercase 'm'. glob_validate() tests verify detection of malformed patterns: well-formed patterns (character classes, escapes, wildcards) return true, while unclosed brackets ("[abc") and trailing backslashes ("abc\") return false. Signed-off-by: Josh Law --- lib/tests/glob_kunit.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c index 9b53060e7c8e..711cb44d1fc8 100644 --- a/lib/tests/glob_kunit.c +++ b/lib/tests/glob_kunit.c @@ -157,8 +157,85 @@ static void glob_test_match(struct kunit *test) params->pat, params->str, params->expected); } =20 +/* Case-insensitive matching tests */ +static const struct glob_test_case glob_nocase_test_cases[] =3D { + { .pat =3D "abc", .str =3D "ABC", .expected =3D true }, + { .pat =3D "ABC", .str =3D "abc", .expected =3D true }, + { .pat =3D "aBc", .str =3D "AbC", .expected =3D true }, + { .pat =3D "a*c", .str =3D "ABC", .expected =3D true }, + { .pat =3D "A?C", .str =3D "abc", .expected =3D true }, + { .pat =3D "[A-Z]", .str =3D "m", .expected =3D true }, + { .pat =3D "[a-z]", .str =3D "M", .expected =3D true }, + { .pat =3D "abc", .str =3D "abd", .expected =3D false }, + { .pat =3D "ABC", .str =3D "ABD", .expected =3D false }, + { .pat =3D "a*z", .str =3D "ABZ", .expected =3D true }, + { .pat =3D "\\A", .str =3D "a", .expected =3D true }, +}; + +KUNIT_ARRAY_PARAM(glob_nocase, glob_nocase_test_cases, glob_case_to_desc); + +static void glob_test_match_nocase(struct kunit *test) +{ + const struct glob_test_case *params =3D test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, + glob_match_nocase(params->pat, params->str), + params->expected, + "nocase Pattern: \"%s\", String: \"%s\", Expected: %d", + params->pat, params->str, params->expected); +} + +/* Pattern validation tests */ +struct glob_validate_case { + const char *pat; + bool expected; +}; + +static const struct glob_validate_case glob_validate_test_cases[] =3D { + { .pat =3D "abc", .expected =3D true }, + { .pat =3D "*", .expected =3D true }, + { .pat =3D "?", .expected =3D true }, + { .pat =3D "[abc]", .expected =3D true }, + { .pat =3D "[!abc]", .expected =3D true }, + { .pat =3D "[^abc]", .expected =3D true }, + { .pat =3D "[a-z]", .expected =3D true }, + { .pat =3D "[]abc]", .expected =3D true }, + { .pat =3D "\\*", .expected =3D true }, + { .pat =3D "\\\\", .expected =3D true }, + { .pat =3D "", .expected =3D true }, + /* Invalid patterns */ + { .pat =3D "[", .expected =3D false }, + { .pat =3D "[abc", .expected =3D false }, + { .pat =3D "[!abc", .expected =3D false }, + { .pat =3D "abc\\", .expected =3D false }, + { .pat =3D "\\", .expected =3D false }, + { .pat =3D "abc[def", .expected =3D false }, +}; + +static void glob_validate_case_to_desc(const struct glob_validate_case *t, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\"", t->pat); +} + +KUNIT_ARRAY_PARAM(glob_validate, glob_validate_test_cases, + glob_validate_case_to_desc); + +static void glob_test_validate(struct kunit *test) +{ + const struct glob_validate_case *params =3D test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, + glob_validate(params->pat), + params->expected, + "validate Pattern: \"%s\", Expected: %d", + params->pat, params->expected); +} + static struct kunit_case glob_kunit_test_cases[] =3D { KUNIT_CASE_PARAM(glob_test_match, glob_gen_params), + KUNIT_CASE_PARAM(glob_test_match_nocase, glob_nocase_gen_params), + KUNIT_CASE_PARAM(glob_test_validate, glob_validate_gen_params), {} }; =20 --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o59.zoho.eu (sender-of-o59.zoho.eu [136.143.169.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9A0C37C917; Sun, 15 Mar 2026 21:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; cv=pass; b=FCSsQw5z7DfI4N8enr0q27KT1u0eneKPnzG7dJ1saKQy/cLOaCNKJQTo5qm+as/moM1PhXX/Od2EmvHrrwP2VDsyWsG0NJFLbF9S4v9F756JuRQeQgk2GUQsiAYvqJ0CEabVWpaU2fIRWbvEqYgK6btXDdQKmqnCGVbinu6u0YY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; c=relaxed/simple; bh=polKK+TVvNhEByk+/eHx32xRBSbjq2Xd9H4Z2XJ6PcI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rWSf56jgrdhaiMrbjyefqcLMp2IQn0CrBkaKqATaqPp2qXYz94Wm72b71JwN4OV3d9Cec0Y+EHF8PkUd3GrLGLS2FemccmJ2XYfmKgjQcVIsIiSOvTI+ytLBw9O0rHRGkcgycKiXNVslZ0+Ii0yG5jueKfQu13ukzFxG3Zh9PB8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=LZXScVzQ; arc=pass smtp.client-ip=136.143.169.59 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="LZXScVzQ" ARC-Seal: i=1; a=rsa-sha256; t=1773609409; cv=none; d=zohomail.eu; s=zohoarc; b=Bno4pcyLqOL9o7Bi79y9GprmpW3yMTKbk6d9otL9c3i0zsE+cwgce1yiuyvWarrN9KNZ3bQlxRhzhpV2mdXtmU6i5rdfRsDv2VYrzhW4/bdni2OxBlm4kvB0A1/He39CmMMr/cHofL6HUUQvNSjDfGKl5p7d8LotHv+LF7WTF10= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609409; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=wV6NoXecECb7bqi4ET6OkCEvhdV779F9FKJzjGTMHkA=; b=kHDMDzbgMvlnRc6j/zabnj8zZgSDvYcpznt5FG1G8tblGOQeJ04ov5V6kWuisyFqI0RoXduF4WMd/frELEo0Gh5Tg+RleFu2tMr2sgEokYi4RCdUxBIJs9ieb3zYO/j0L79jA2/x2kmONpgTHlgY9Ru+h5Con45hd3SELSr0v4g= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609409; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=wV6NoXecECb7bqi4ET6OkCEvhdV779F9FKJzjGTMHkA=; b=LZXScVzQZ4oeTxAilTYH+ntky06J6KenJEbszKszIIPWR+wyH3rwm00JjCmgExcy f5a1Wtl/YRPPinS5IuHOhqS9XNB6Lblrs03k4QIUzdmnrFnyVDcCftvNb/cqQqkymqF Cn0OBmdia8FBTN6dryv/n3YhzTFhPvCQCzT7QzsQ= Received: by mx.zoho.eu with SMTPS id 177360940741925.854410502414908; Sun, 15 Mar 2026 22:16:47 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 4/8] lib/glob: add case-insensitive glob_match_nocase() Date: Sun, 15 Mar 2026 21:16:35 +0000 Message-Id: <20260315211641.408318-8-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add a case-insensitive variant of glob_match() for callers that need to match patterns regardless of case. The immediate motivation is the ATA device quirk denylist in drivers/ata/libata-core.c, which uses glob_match() to match drive model and firmware revision strings. ATA IDENTIFY DEVICE data is space-padded ASCII and the specification does not mandate a particular case, so a denylist entry could miss a drive that reports its model string in unexpected casing. Switching the denylist to glob_match_nocase() (in a follow-up ATA patch) would make it robust against such variation. Refactor the matching logic into a static __glob_match() helper that takes a bool nocase parameter, and implement both glob_match() and glob_match_nocase() as thin wrappers. When nocase is true, literal characters and character class endpoints are folded through tolower() before comparison. Signed-off-by: Josh Law --- include/linux/glob.h | 1 + lib/glob.c | 75 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/include/linux/glob.h b/include/linux/glob.h index 861327b33e41..36527ae89730 100644 --- a/include/linux/glob.h +++ b/include/linux/glob.h @@ -6,5 +6,6 @@ #include /* For __pure */ =20 bool __pure glob_match(char const *pat, char const *str); +bool __pure glob_match_nocase(char const *pat, char const *str); =20 #endif /* _LINUX_GLOB_H */ diff --git a/lib/glob.c b/lib/glob.c index c5508be0d215..172b8ba3cd8e 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) +#include #include #include #include @@ -11,8 +12,8 @@ MODULE_DESCRIPTION("glob(7) matching"); MODULE_LICENSE("Dual MIT/GPL"); =20 -/** - * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) +/* + * __glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) * @pat: Shell-style pattern to match, e.g. "*.[ch]". * @str: String to match. The pattern must match the entire string. * @@ -20,7 +21,7 @@ MODULE_LICENSE("Dual MIT/GPL"); * succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str,= 0). * * Pattern metacharacters are ?, *, [ and \. - * (And, inside character classes, !, - and ].) + * (And, inside character classes, !, ^ - and ].) * * This is a small and simple implementation intended for device denylists * where a string is matched against a number of patterns. Thus, it @@ -39,7 +40,7 @@ MODULE_LICENSE("Dual MIT/GPL"); * * An opening bracket without a matching close is matched literally. */ -bool __pure glob_match(char const *pat, char const *str) +static bool __pure __glob_match(char const *pat, char const *str, bool noc= ase) { /* * Backtrack to previous * on mismatch and retry starting one @@ -58,6 +59,11 @@ bool __pure glob_match(char const *pat, char const *str) unsigned char c =3D *str++; unsigned char d =3D *pat++; =20 + if (nocase) { + c =3D tolower(c); + d =3D tolower(d); + } + switch (d) { case '?': /* Wildcard: anything but nul */ if (c =3D=3D '\0') @@ -94,13 +100,17 @@ bool __pure glob_match(char const *pat, char const *st= r) goto literal; =20 class +=3D 2; - /* Normalize inverted ranges like [z-a] */ - if (a > b) { - unsigned char tmp =3D a; + } + if (nocase) { + a =3D tolower(a); + b =3D tolower(b); + } + /* Normalize inverted ranges like [z-a] */ + if (a > b) { + unsigned char tmp =3D a; =20 - a =3D b; - b =3D tmp; - } + a =3D b; + b =3D tmp; } if (a <=3D c && c <=3D b) match =3D true; @@ -112,8 +122,11 @@ bool __pure glob_match(char const *pat, char const *st= r) } break; case '\\': - if (*pat !=3D '\0') + if (*pat !=3D '\0') { d =3D *pat++; + if (nocase) + d =3D tolower(d); + } fallthrough; default: /* Literal character */ literal: @@ -132,4 +145,44 @@ bool __pure glob_match(char const *pat, char const *st= r) } } } + +/** + * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) + * @pat: Shell-style pattern to match, e.g. "*.[ch]". + * @str: String to match. The pattern must match the entire string. + * + * Perform shell-style glob matching, returning true (1) if the match + * succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str,= 0). + * + * Pattern metacharacters are ?, *, [ and \. + * (And, inside character classes, !, ^ - and ].) + * + * This is small and simple and non-recursive, with run-time at most + * quadratic: strlen(@str)*strlen(@pat). It does not preprocess the + * patterns. An opening bracket without a matching close is matched + * literally. + * + * Return: true if @str matches @pat, false otherwise. + */ +bool __pure glob_match(char const *pat, char const *str) +{ + return __glob_match(pat, str, false); +} EXPORT_SYMBOL(glob_match); + +/** + * glob_match_nocase - Case-insensitive shell-style pattern matching + * @pat: Shell-style pattern to match. + * @str: String to match. The pattern must match the entire string. + * + * Identical to glob_match(), but performs case-insensitive comparisons + * for literal characters and character class contents using tolower(). + * Metacharacters (?, *, [, ]) are not affected by case folding. + * + * Return: true if @str matches @pat (case-insensitive), false otherwise. + */ +bool __pure glob_match_nocase(char const *pat, char const *str) +{ + return __glob_match(pat, str, true); +} +EXPORT_SYMBOL(glob_match_nocase); --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o53.zoho.eu (sender-of-o53.zoho.eu [136.143.169.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C707137C91E; Sun, 15 Mar 2026 21:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.53 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609429; cv=pass; b=nrGzH1MA/nPy/oT5trKsRYYxUD37z4wiXd4N/wxRut9Oj6udvEcCgqJB4QxQH0NpnJKqOqXx+72R5iAbHpwSHFV0qQoyI7M/ONtsyxA4/LPCYUMxK0cCt0/I03cMQwzM3rDPRIlTcwuWleC2SsYqJU+Ztu+OtpnNEJYtXDeNbew= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609429; c=relaxed/simple; bh=nDNdIz9w1v6GX9HKPOLSEpcSx9VPTmDZ0uZ7Lf2JPJQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=md+wBtYl6ZMWpLj/cq6cI561LArRYY3KetSC7Tm1HlznoH7/buXYjoB8AgG1a4gFtSZkQAYTbbBdL4/5YjWkgIRJJrMjLOTtq6SYcsV0wT/rjCaUFbAk5fuS1GdM57btZHyNRXfohkvqgl/DNsSUkOJCn61DVvvXu/eVtECR71U= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=ef0ifKlB; arc=pass smtp.client-ip=136.143.169.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="ef0ifKlB" ARC-Seal: i=1; a=rsa-sha256; t=1773609412; cv=none; d=zohomail.eu; s=zohoarc; b=EX8dFZtT0jQITut3bEFsSkfHsTNyJmRtAEd3Ll0A82JK1CKs/1RI7AFlyJuXLwHecNih5IuD8fwuiLh1AgjlSfeemV8fZLrWPWJMMxfhyn9tngBxAMcQ7/m5stofld0VYp61fiDZVfa8NIyMNzILLuBgxwF5b4/337wmXwbGOnY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609412; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=x5o3NZywWI/GlA27vRpItmX4VibMyB/hLnI+Hl7u6to=; b=RALPJU4pNJuVVCFPR9C638pwf7ebP7dlT/O/Zl8Ik/UwJmHR/oQAITmv2nZpy7T3GIk19Vf2MKV6GeqDkfyjBYWW+flfkvOhMNPhtQyjYpvosIdtKrAKx/g1fekn/tZc5wdlqOsGNTsskIbHhauNa8SgmgoibSf2pkWbDNr6Mpg= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609412; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Type:Content-Transfer-Encoding:Reply-To; bh=x5o3NZywWI/GlA27vRpItmX4VibMyB/hLnI+Hl7u6to=; b=ef0ifKlBRC1VmqbwX1whoKq7JQYDm5ePaybcfNqKU+uThXTKloJ+5NwvQRdYeO8/ ZJ+eSltbCp47/0e6HrWgw4Lmy97u5FdKAwKQMaKkbZpIF6SijsNurTep2Fagz7W4RAU 0BDI1tvtO6biNQZ+ClX3GaaqtNvld0ogOKn0ybhg= Received: by mx.zoho.eu with SMTPS id 177360940880345.2258325308685; Sun, 15 Mar 2026 22:16:48 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v2 5/5] kunit: validate glob filter patterns before use Date: Sun, 15 Mar 2026 21:16:37 +0000 Message-Id: <20260315211641.408318-10-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External kunit_parse_glob_filter() accepts user-provided glob patterns via the filter_glob module parameter but does not check whether they are well-formed. A malformed pattern like "suite[.test" (unclosed bracket) or "suite\" (trailing backslash) is silently passed to glob_match() which handles it gracefully but not in the way the user likely intended =E2=80=94 the bracket is matched as a literal character rather than startin= g a character class. Use glob_validate() to reject malformed patterns early with -EINVAL, so users get a clear error instead of silently wrong filter results. Signed-off-by: Josh Law --- lib/kunit/executor.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 1fef217de11d..f0cc15e4b34d 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -91,6 +91,8 @@ static int kunit_parse_glob_filter(struct kunit_glob_filt= er *parsed, const char *period =3D strchr(filter_glob, '.'); =20 if (!period) { + if (!glob_validate(filter_glob)) + return -EINVAL; parsed->suite_glob =3D kstrdup(filter_glob, GFP_KERNEL); if (!parsed->suite_glob) return -ENOMEM; @@ -102,12 +104,23 @@ static int kunit_parse_glob_filter(struct kunit_glob_= filter *parsed, if (!parsed->suite_glob) return -ENOMEM; =20 + if (!glob_validate(parsed->suite_glob)) { + kfree(parsed->suite_glob); + return -EINVAL; + } + parsed->test_glob =3D kstrdup(period + 1, GFP_KERNEL); if (!parsed->test_glob) { kfree(parsed->suite_glob); return -ENOMEM; } =20 + if (!glob_validate(parsed->test_glob)) { + kfree(parsed->test_glob); + kfree(parsed->suite_glob); + return -EINVAL; + } + return 0; } =20 --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o53.zoho.eu (sender-of-o53.zoho.eu [136.143.169.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0EFF837C918; Sun, 15 Mar 2026 21:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.53 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609427; cv=pass; b=lXHK3OMq67xt2JGpF2KX4JIwAlQtk0SjspT5Y6BgUgLYzgTKSF0WobBlTRyxxkHeHgqO+6w8/8S75DzlxHfNUCd3Uh8r5JBbhozrGSimDDz2872qyAQ+ssADejxN9l21u56N+6k4QZfjm7bCSIOU3dTFV8EBWiCEUDKJiret/GI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609427; c=relaxed/simple; bh=NK8NcdJxCO2LV2WJNqfKBaNOOeGuUndAUUlIXnyHtxA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EYFncOY6Lj3gzFqJCVH/WboqY0t6OgHJ1WgaZk8PLMUmeXW4UlVo9JuqgQCC8UIEel/RI7DInnJIvSxPLxDWuI6IaCQIQtN6nlwk5WX0KyMq6f0iKbkcEpQGvVVs1XYhBpLAk4i3pkGDeKGaljT6bjAxPy5VrsvvbDbWYwnIlhg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=LnwttyBw; arc=pass smtp.client-ip=136.143.169.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="LnwttyBw" ARC-Seal: i=1; a=rsa-sha256; t=1773609410; cv=none; d=zohomail.eu; s=zohoarc; b=VWHCOl5Um3eyt/X1/ABUglDYlZSoEa01lDZlnKt+zsIjR8tetkZSsjKRZXYLQYjCNm5VhB6QRFxMzS1iGDW0nvKZHD03MFC9KlezNpAR4gIrCP7yIuw1kATgS8/GRkNArtR4/CmD3DXESJkKB29fUc4IiMixjhp5H/A78YLc0+g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609410; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZH0GCSbT5tKftFXXPeA2gjcQUx1mgWMeocoKefb8MuM=; b=Nty+VLKeh89a4ix8/hXEU8ODnp3ygoPOoN9mEIQjFIWkh7Zs/6K6IURYncPN0WamAwrydmVKjJaWNT8yz7PILta/bA9SzPT67DHrCdm8k3uNZAUHfq+TQud7Dq6dNe6QpxIlE5xA67YaAIPSK7Ruc04TB9Na+mgGOFgoA1LMQO8= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609410; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=ZH0GCSbT5tKftFXXPeA2gjcQUx1mgWMeocoKefb8MuM=; b=LnwttyBwo2jd13WRNWvtdnQgpJQAgT2ng1Y6qhmp5+CUMXQuGcMzpwBY6Hpq27Ot +CskO6JFWom1RE175725UC8+eYR85oIZsajqpgvP7Aw221UUvseD5+8blInaBzYmsTc YRVX0R45+2WnwY6CJK5K3fh+NESaSi1Hp4n9DnpU= Received: by mx.zoho.eu with SMTPS id 1773609409472432.7371461662; Sun, 15 Mar 2026 22:16:49 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 5/8] lib/glob: add glob_validate() for pattern syntax checking Date: Sun, 15 Mar 2026 21:16:38 +0000 Message-Id: <20260315211641.408318-11-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add glob_validate() which checks whether a glob pattern is syntactically well-formed before matching. It detects: - Unclosed character classes: a '[' with no matching ']' - Trailing backslash: a '\' at end of pattern with nothing to escape glob_match() already handles these gracefully (unclosed brackets are matched literally, a trailing backslash matches itself), but callers that accept patterns from userspace may want to reject malformed input upfront with a clear error rather than silently falling back to literal matching. For example, the kunit executor accepts a filter_glob module parameter to select which tests to run. A user who types "snd_*.[codec_test" (forgetting the closing bracket) would currently see the '[' matched literally instead of starting a character class, producing silently wrong filter results. With glob_validate(), the executor can reject the pattern early and report -EINVAL, as done in the following patch. Signed-off-by: Josh Law --- include/linux/glob.h | 1 + lib/glob.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/linux/glob.h b/include/linux/glob.h index 36527ae89730..deceaa2e4a74 100644 --- a/include/linux/glob.h +++ b/include/linux/glob.h @@ -7,5 +7,6 @@ =20 bool __pure glob_match(char const *pat, char const *str); bool __pure glob_match_nocase(char const *pat, char const *str); +bool __pure glob_validate(char const *pat); =20 #endif /* _LINUX_GLOB_H */ diff --git a/lib/glob.c b/lib/glob.c index 172b8ba3cd8e..8ee539d19cc4 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -186,3 +186,46 @@ bool __pure glob_match_nocase(char const *pat, char co= nst *str) return __glob_match(pat, str, true); } EXPORT_SYMBOL(glob_match_nocase); + +/** + * glob_validate - Check whether a glob pattern is well-formed + * @pat: Shell-style pattern to validate. + * + * Return: true if @pat is a syntactically valid glob pattern, false + * if it contains malformed constructs. The following are considered + * invalid: + * + * - An opening '[' with no matching ']' (unclosed character class). + * - A trailing '\' with no character following it. + * + * Note that glob_match() handles these gracefully (an unclosed bracket + * is matched literally, a trailing backslash matches itself), but + * callers that accept patterns from user input may wish to reject + * malformed patterns early with a clear error. + */ +bool __pure glob_validate(char const *pat) +{ + while (*pat) { + switch (*pat++) { + case '\\': + if (*pat =3D=3D '\0') + return false; + pat++; + break; + case '[': + if (*pat =3D=3D '!' || *pat =3D=3D '^') + pat++; + /* ] as first character is literal, not end of class */ + if (*pat =3D=3D ']') + pat++; + while (*pat && *pat !=3D ']') + pat++; + if (*pat =3D=3D '\0') + return false; + pat++; /* skip ']' */ + break; + } + } + return true; +} +EXPORT_SYMBOL(glob_validate); --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o53.zoho.eu (sender-of-o53.zoho.eu [136.143.169.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C716C37C920; Sun, 15 Mar 2026 21:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.53 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; cv=pass; b=biJGjMFCL7t2D8rvbvQbn5L+VnSDnshXMhb8dNB6keL63CrcgYx64NuPdrw7aC2lUDO200WR+NFCoRhzfWznqV+XFxQoqcKj615ezsCNBA/4GgoUm/TNoPkOXjSREQA1LWAXZXhtEtpABnbTyl4O1UAS/p1EtPEUIRCdr6icWfM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; c=relaxed/simple; bh=DqDIHMd4MJlmLaUnm4FNNfD7TmiR4u66qXh4CXNuOwo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rBix0KL3kKC4EHCaVOXQw+RmbpoHIcxSAemdWoxQLV7CYUvbzOgiX66GmnRpe0hJ45vr1IX+hruTXQsmEx31xIlodm38HLzQBytjO893YMviMTSdyq9FOWYGVU/PKiKmqfMjwmdzs5KtbK9qgm7UAeIYBnBIcl4K9BCe66CpXjo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=FOXNVdlC; arc=pass smtp.client-ip=136.143.169.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="FOXNVdlC" ARC-Seal: i=1; a=rsa-sha256; t=1773609411; cv=none; d=zohomail.eu; s=zohoarc; b=f65gojbao9VWdme8gkz5snyZix8TCMOjn3WstebXdYGWzRhs2uwwlga7hF2nlhpmA+PYZ4P/MhuQKIBZU8nuJJktxiYSAbGkl4j/U1LOjl+ChK40U4hkZSrNAK6w1kwukDUEnBi6JG1Bm7dv9ioQbyTlqBlWYFQzUnXz6GsmjJU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609411; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=f220kEhJ66X+jXJtp71OpS8vD3cCaDjeBL3VruhruPw=; b=Wi4acQ0E0JtwrEZz5dZQ4ZvhRxY7lVYA1xoaTlLEHViiZBo8VjjncueCcczYrdSlmETBhCQeDtSQa9R449HuiYf2fBhGFgzulNzw9qD8r/BPicFrN6RbQenYMbn9e2FLdr5xLkOp8PloPItFBLNfB6liE7mKxenIpPvE1ODSxkA= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609411; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=f220kEhJ66X+jXJtp71OpS8vD3cCaDjeBL3VruhruPw=; b=FOXNVdlCrqL05u0tX3TNJ8Te65mNOw1uYqKwFLFFpYSJcmLCu/9qvsckfMVDjTPv gPn8othOUwzAxh0Nkg5fVO8dOxRM/irKjRqgbdOksDuCB+JE3fMYEAROqzviY9ROgge zTsryyrS5RX4mcPO7OrpnEnjE6Jo26N99+XkIR8E= Received: by mx.zoho.eu with SMTPS id 1773609410152946.5648712984375; Sun, 15 Mar 2026 22:16:50 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 6/8] lib/tests: add glob test cases for escapes, edge cases, and new features Date: Sun, 15 Mar 2026 21:16:39 +0000 Message-Id: <20260315211641.408318-12-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" The glob kunit test suite had no coverage for backslash escape sequences, and was missing edge cases around wildcards with empty strings, inverted ranges, unclosed brackets, and consecutive wildcards. Add test cases covering: - Backslash escapes: \*, \?, \[, \\, non-metachar after backslash, and trailing backslash matching a literal '\' character. - Wildcards matching special characters in the string (*, [, \, ?). - Wildcards with empty strings: * matches empty, ** matches empty, ? does not match empty. - Inverted (backwards) ranges: [z-a] and [9-0] now match thanks to endpoint normalization. - Single-character ranges: [a-a] matches 'a'. - Caret negation: [^a] and [^a-z] as alias for [!...]. - Unclosed bracket: [ treated as literal. - Consecutive wildcards: ***a, *?*, *?*?* patterns. Signed-off-by: Josh Law --- lib/tests/glob_kunit.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c index 362b1eda8e5b..9b53060e7c8e 100644 --- a/lib/tests/glob_kunit.c +++ b/lib/tests/glob_kunit.c @@ -80,6 +80,53 @@ static const struct glob_test_case glob_test_cases[] =3D= { { .pat =3D "*bc", .str =3D "bc", .expected =3D true }, { .pat =3D "*bc", .str =3D "bbc", .expected =3D true }, { .pat =3D "*bc", .str =3D "bcbc", .expected =3D true }, + /* Backslash escape sequences */ + { .pat =3D "\\*", .str =3D "*", .expected =3D true }, + { .pat =3D "\\*", .str =3D "a", .expected =3D false }, + { .pat =3D "\\?", .str =3D "?", .expected =3D true }, + { .pat =3D "\\?", .str =3D "a", .expected =3D false }, + { .pat =3D "\\[", .str =3D "[", .expected =3D true }, + { .pat =3D "\\[", .str =3D "a", .expected =3D false }, + { .pat =3D "a\\bc", .str =3D "abc", .expected =3D true }, + { .pat =3D "\\\\", .str =3D "\\", .expected =3D true }, + { .pat =3D "\\\\", .str =3D "a", .expected =3D false }, + /* Trailing backslash (matches literal backslash) */ + { .pat =3D "a\\", .str =3D "a\\", .expected =3D true }, + { .pat =3D "a\\", .str =3D "a", .expected =3D false }, + /* Wildcards matching special characters in string */ + { .pat =3D "?", .str =3D "*", .expected =3D true }, + { .pat =3D "?", .str =3D "[", .expected =3D true }, + { .pat =3D "?", .str =3D "\\", .expected =3D true }, + { .pat =3D "?", .str =3D "?", .expected =3D true }, + /* Wildcards with empty strings */ + { .pat =3D "*", .str =3D "", .expected =3D true }, + { .pat =3D "*", .str =3D "a", .expected =3D true }, + { .pat =3D "**", .str =3D "", .expected =3D true }, + { .pat =3D "**", .str =3D "abc", .expected =3D true }, + { .pat =3D "?", .str =3D "", .expected =3D false }, + /* Inverted (backwards) ranges */ + { .pat =3D "[z-a]", .str =3D "m", .expected =3D true }, + { .pat =3D "[z-a]", .str =3D "z", .expected =3D true }, + { .pat =3D "[z-a]", .str =3D "a", .expected =3D true }, + { .pat =3D "[9-0]", .str =3D "5", .expected =3D true }, + { .pat =3D "[9-0]", .str =3D "a", .expected =3D false }, + /* Single-character range */ + { .pat =3D "[a-a]", .str =3D "a", .expected =3D true }, + { .pat =3D "[a-a]", .str =3D "b", .expected =3D false }, + /* Caret negation syntax */ + { .pat =3D "[^a]", .str =3D "b", .expected =3D true }, + { .pat =3D "[^a]", .str =3D "a", .expected =3D false }, + { .pat =3D "[^a-z]", .str =3D "0", .expected =3D true }, + { .pat =3D "[^a-z]", .str =3D "m", .expected =3D false }, + /* Unclosed bracket (treated as literal) */ + { .pat =3D "[", .str =3D "[", .expected =3D true }, + { .pat =3D "[", .str =3D "a", .expected =3D false }, + { .pat =3D "[abc", .str =3D "[abc", .expected =3D true }, + /* Consecutive wildcards */ + { .pat =3D "***a", .str =3D "a", .expected =3D true }, + { .pat =3D "*?*", .str =3D "a", .expected =3D true }, + { .pat =3D "*?*?*", .str =3D "ab", .expected =3D true }, + { .pat =3D "*?*?*", .str =3D "a", .expected =3D false }, /* Multiple asterisks (complex backtracking) */ { .pat =3D "*ac*", .str =3D "abacadaeafag", .expected =3D true }, { .pat =3D "*ac*ae*ag*", .str =3D "abacadaeafag", .expected =3D true }, --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2A7537C937; Sun, 15 Mar 2026 21:17:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609429; cv=pass; b=TELF3JzSpebKNeG80ZP0iO/Tdt3EgKTHPSu0kh682lpJdyvq/0lBwPD8/cCWuDikadZakqBYs1UMUzMJqPxbBYuJKKEO0HYFriqRvNmqroq996VYtTU9CIIRjz6SWXgZo8WXbgDaUyQL9LV/xbjnrqjRIZMNTT+sB77DAtEEa+I= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609429; c=relaxed/simple; bh=MrFEroHwYorqSWGBoY5ocHzyEC+JzAla+WphZ3zVa6Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DkdGgmDcnU8NrSFFfzlD8mlqMLhs9cteoyhbs+6AYDKQ9Mw2n5hNnLm0PjHKsx+ual6KUw2acY15UeYTY6JVdbjFspmSg1L4A9lFl0AogdgDl5oyiofznJcF8IDZpg2iHss7/jihFA1bkE1ye6slZ4EGSVTV/vgdf9/LFOrn3hI= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=FkZa6v19; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="FkZa6v19" ARC-Seal: i=1; a=rsa-sha256; t=1773609413; cv=none; d=zohomail.eu; s=zohoarc; b=QFOGlDQ/oThiyWnDcIzNoiG4867Bw0ZsCkWl7HoaEm8XpFkuv4f6ke8tBtSa7QGrUm5vPiZlTSH5K3RW5H0Z6ErcQOJrWsWf4NztP341qFgx9+o0XtyUVQxBJkToVjiB2btQCCHBum/slFGzgQQTzTTh2ooZr1eBaxTnJBFy8C0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609413; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=/JtZCIPsgGracX5Mx/4hRAMi9BpwqYEGpkwpzrg8Moo=; b=ktkXv8sy9QHICW1PDoHm8WQpGrvsLzjd8hLWvFFLMVeBwDtL5FVKFGAW4G/uisDs48BxZtH5Ppx1UVX+AkiK96MX39e8P3x35/G6LieNw+19ofxlWg4UPOUC+A8dGDvS24YUPXYEUQ57v1azuqgGWtsp8KyB+l/C82lPpBt5YUw= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609413; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Reply-To; bh=/JtZCIPsgGracX5Mx/4hRAMi9BpwqYEGpkwpzrg8Moo=; b=FkZa6v19iQirozZShiSxQpsgKfafjq00GrJ3rFOGRjM6j8Pp9lMbOJ3V9iUQ/T/o Ti5Nf9QbaUw4yjIr+blBrJHfycywcvIpEwFgeRciUqzT5bqAoXZIV9iR9Ctl+mOI8yp IPQL0bK61dc3r7S1xQVILa2JPC5EzLw8raEkelik= Received: by mx.zoho.eu with SMTPS id 1773609410822343.7586299251037; Sun, 15 Mar 2026 22:16:50 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 7/8] lib/tests: add kunit tests for glob_match_nocase() and glob_validate() Date: Sun, 15 Mar 2026 21:16:40 +0000 Message-Id: <20260315211641.408318-13-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Add parameterized test cases for the new glob API functions: glob_match_nocase() tests verify case-insensitive matching for literal characters, wildcards, character class ranges, and backslash escapes -- e.g., pattern "a*c" matches string "ABC", and range [A-Z] matches lowercase 'm'. glob_validate() tests verify detection of malformed patterns: well-formed patterns (character classes, escapes, wildcards) return true, while unclosed brackets ("[abc") and trailing backslashes ("abc\") return false. Signed-off-by: Josh Law --- lib/tests/glob_kunit.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c index 9b53060e7c8e..711cb44d1fc8 100644 --- a/lib/tests/glob_kunit.c +++ b/lib/tests/glob_kunit.c @@ -157,8 +157,85 @@ static void glob_test_match(struct kunit *test) params->pat, params->str, params->expected); } =20 +/* Case-insensitive matching tests */ +static const struct glob_test_case glob_nocase_test_cases[] =3D { + { .pat =3D "abc", .str =3D "ABC", .expected =3D true }, + { .pat =3D "ABC", .str =3D "abc", .expected =3D true }, + { .pat =3D "aBc", .str =3D "AbC", .expected =3D true }, + { .pat =3D "a*c", .str =3D "ABC", .expected =3D true }, + { .pat =3D "A?C", .str =3D "abc", .expected =3D true }, + { .pat =3D "[A-Z]", .str =3D "m", .expected =3D true }, + { .pat =3D "[a-z]", .str =3D "M", .expected =3D true }, + { .pat =3D "abc", .str =3D "abd", .expected =3D false }, + { .pat =3D "ABC", .str =3D "ABD", .expected =3D false }, + { .pat =3D "a*z", .str =3D "ABZ", .expected =3D true }, + { .pat =3D "\\A", .str =3D "a", .expected =3D true }, +}; + +KUNIT_ARRAY_PARAM(glob_nocase, glob_nocase_test_cases, glob_case_to_desc); + +static void glob_test_match_nocase(struct kunit *test) +{ + const struct glob_test_case *params =3D test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, + glob_match_nocase(params->pat, params->str), + params->expected, + "nocase Pattern: \"%s\", String: \"%s\", Expected: %d", + params->pat, params->str, params->expected); +} + +/* Pattern validation tests */ +struct glob_validate_case { + const char *pat; + bool expected; +}; + +static const struct glob_validate_case glob_validate_test_cases[] =3D { + { .pat =3D "abc", .expected =3D true }, + { .pat =3D "*", .expected =3D true }, + { .pat =3D "?", .expected =3D true }, + { .pat =3D "[abc]", .expected =3D true }, + { .pat =3D "[!abc]", .expected =3D true }, + { .pat =3D "[^abc]", .expected =3D true }, + { .pat =3D "[a-z]", .expected =3D true }, + { .pat =3D "[]abc]", .expected =3D true }, + { .pat =3D "\\*", .expected =3D true }, + { .pat =3D "\\\\", .expected =3D true }, + { .pat =3D "", .expected =3D true }, + /* Invalid patterns */ + { .pat =3D "[", .expected =3D false }, + { .pat =3D "[abc", .expected =3D false }, + { .pat =3D "[!abc", .expected =3D false }, + { .pat =3D "abc\\", .expected =3D false }, + { .pat =3D "\\", .expected =3D false }, + { .pat =3D "abc[def", .expected =3D false }, +}; + +static void glob_validate_case_to_desc(const struct glob_validate_case *t, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\"", t->pat); +} + +KUNIT_ARRAY_PARAM(glob_validate, glob_validate_test_cases, + glob_validate_case_to_desc); + +static void glob_test_validate(struct kunit *test) +{ + const struct glob_validate_case *params =3D test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, + glob_validate(params->pat), + params->expected, + "validate Pattern: \"%s\", Expected: %d", + params->pat, params->expected); +} + static struct kunit_case glob_kunit_test_cases[] =3D { KUNIT_CASE_PARAM(glob_test_match, glob_gen_params), + KUNIT_CASE_PARAM(glob_test_match_nocase, glob_nocase_gen_params), + KUNIT_CASE_PARAM(glob_test_validate, glob_validate_gen_params), {} }; =20 --=20 2.34.1 From nobody Thu Apr 9 10:29:05 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F315C37C916; Sun, 15 Mar 2026 21:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; cv=pass; b=NJasfA05yTmfr4Utnq7u5XOJGxZ/Y+afZ4OiuOHFXcPdxuq8HOe0wi+PKIcq+an/JgqvwLWvx5f9xHr/wg3kmjTPEQ5E5KJTZXIMguNDBZTQrg03OdMHH5TLWKgQyQr0RppFc3XrYHo268tkbHV13L+WLH4s9RIdk+9y7lOdfBI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773609428; c=relaxed/simple; bh=nDNdIz9w1v6GX9HKPOLSEpcSx9VPTmDZ0uZ7Lf2JPJQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=if9hEJJ4V0oeHUISwttBFoUFN97fY4yGhCxi/maMXHMF4MGvM+hBw6OYWmLwAntTwNZI47FCjoeh3+CjYymHCGIvrcHUqH1i8/wWktIsA1ufk75b7tpRxYL4e3/2VkjA4/DgNKvmWZLPOI5AbUKx0NvmNDy38pql9f5sDO/RFlA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org; spf=pass smtp.mailfrom=objecting.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b=MQoCZPfA; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=objecting.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=objecting.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=objecting.org header.i=objecting@objecting.org header.b="MQoCZPfA" ARC-Seal: i=1; a=rsa-sha256; t=1773609412; cv=none; d=zohomail.eu; s=zohoarc; b=A79LWGUHiBGd6hZ14+/rGkKCS90fdDybm8lmdpHW5uwvE3S0Bj6PfsBkQqVmmefj9sYs7Voep2Eb+tDZ5EyvSEv5mE8tPuLeOa215bj5QKzJd5Fg+Rkd7lxwqs3ePh1veA0LS3HlFnCnQVksAjjePfXs+ZlVUQa5lBizMTgHGzE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1773609412; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=x5o3NZywWI/GlA27vRpItmX4VibMyB/hLnI+Hl7u6to=; b=aCEIasKyOqoW7mbO7m9uwp4XDxvseoZJ3OtOThVr/Isst2V7apkidmUsZu+37LUaadYPJBKgmXBhpVgzM0BPiliagYjr9Iv1FB09vMn7Rb5TdrMBvZEDw0zFgR6te0EkJwCUqWL2k/8+DyqJQsyU0MtqF1PU/lW/z0WySz2rQBk= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=objecting.org; spf=pass smtp.mailfrom=objecting@objecting.org; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1773609412; s=zmail; d=objecting.org; i=objecting@objecting.org; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-Id:Message-Id:In-Reply-To:References:MIME-Version:Content-Type:Content-Transfer-Encoding:Reply-To; bh=x5o3NZywWI/GlA27vRpItmX4VibMyB/hLnI+Hl7u6to=; b=MQoCZPfAaFkO+OAeQ/o/tegzYfrQDPNgKrvI8yPtk66vDhIW56cakCuafNJT6Hvm F+fbJqa7GsQsHpB7ykAOoUz9p5y3/WH6NbSBfjFvAiUNC5VCjpxsVm75z1WGZWz4UQr oAOoxxeGo2LgS4dETelyYveD7VK4HOyv2IeAOZAc= Received: by mx.zoho.eu with SMTPS id 1773609411488530.2548253520487; Sun, 15 Mar 2026 22:16:51 +0100 (CET) From: Josh Law To: Andrew Morton Cc: Brendan Higgins , David Gow , Rae Moar , linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Josh Law Subject: [PATCH v3 8/8] kunit: validate glob filter patterns before use Date: Sun, 15 Mar 2026 21:16:41 +0000 Message-Id: <20260315211641.408318-14-objecting@objecting.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260315211641.408318-1-objecting@objecting.org> References: <20260315211641.408318-1-objecting@objecting.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External kunit_parse_glob_filter() accepts user-provided glob patterns via the filter_glob module parameter but does not check whether they are well-formed. A malformed pattern like "suite[.test" (unclosed bracket) or "suite\" (trailing backslash) is silently passed to glob_match() which handles it gracefully but not in the way the user likely intended =E2=80=94 the bracket is matched as a literal character rather than startin= g a character class. Use glob_validate() to reject malformed patterns early with -EINVAL, so users get a clear error instead of silently wrong filter results. Signed-off-by: Josh Law --- lib/kunit/executor.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 1fef217de11d..f0cc15e4b34d 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -91,6 +91,8 @@ static int kunit_parse_glob_filter(struct kunit_glob_filt= er *parsed, const char *period =3D strchr(filter_glob, '.'); =20 if (!period) { + if (!glob_validate(filter_glob)) + return -EINVAL; parsed->suite_glob =3D kstrdup(filter_glob, GFP_KERNEL); if (!parsed->suite_glob) return -ENOMEM; @@ -102,12 +104,23 @@ static int kunit_parse_glob_filter(struct kunit_glob_= filter *parsed, if (!parsed->suite_glob) return -ENOMEM; =20 + if (!glob_validate(parsed->suite_glob)) { + kfree(parsed->suite_glob); + return -EINVAL; + } + parsed->test_glob =3D kstrdup(period + 1, GFP_KERNEL); if (!parsed->test_glob) { kfree(parsed->suite_glob); return -ENOMEM; } =20 + if (!glob_validate(parsed->test_glob)) { + kfree(parsed->test_glob); + kfree(parsed->suite_glob); + return -EINVAL; + } + return 0; } =20 --=20 2.34.1