浏览代码

Add fuzz test for pattern matching

bel2125 3 年之前
父节点
当前提交
c2461ca295
共有 2 个文件被更改,包括 207 次插入1 次删除
  1. 1 1
      src/civetweb.c
  2. 206 0
      unittest/private.c

+ 1 - 1
src/civetweb.c

@@ -4005,7 +4005,7 @@ match_prefix(const char *pattern, size_t pattern_len, const char *str)
 		/* Pattern * or ** matches multiple characters */
 		if (pattern[i] == '*') {
 			i++;
-			if (pattern[i] == '*') {
+			if ((pattern[i] == '*') && (i < (ptrdiff_t)pattern_len)) {
 				/* Pattern ** matches all */
 				i++;
 				len = (ptrdiff_t)strlen(str + j);

+ 206 - 0
unittest/private.c

@@ -443,6 +443,211 @@ START_TEST(test_match_prefix_strlen)
 	ck_assert_int_eq(15,
 	                 match_prefix_strlen("**.jpg$|**.jpeg$",
 	                                     "/sub/image.jpeg"));
+	ck_assert_int_eq(14,
+	                 match_prefix_strlen("/*/*.jpg$|/*/*.jpeg$",
+	                                     "/sub/image.jpg"));
+	ck_assert_int_eq(15,
+	                 match_prefix_strlen("/*/*.jpg$|/*/*.jpeg$",
+	                                     "/sub/image.jpeg"));
+}
+END_TEST
+
+
+START_TEST(test_match_prefix_fuzz)
+{
+	/* Copyright (c) 2022 the CivetWeb developers */
+	{
+		/* From fuzz test */
+		const char *pat = "**cacc//d/?dad?";
+		const char *str =
+		    "dbbddb/cb/ddcdbcbbab/dcdcbbbcaaacdbcac/dbdcadaa/bcaca/d/a/adcad";
+		ck_assert_int_eq(6, match_prefix(pat, 1, str));
+		ck_assert_int_eq(63, match_prefix(pat, 2, str));
+		ck_assert_int_eq(61, match_prefix(pat, 3, str));
+		ck_assert_int_eq(62, match_prefix(pat, 4, str));
+		ck_assert_int_eq(52, match_prefix(pat, 5, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 6, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "a/a*d**/?*/*cdd";
+		const char *str =
+		    "a/aaddba/ddadbaacac//bcaadbc/badaccbdadadcbb//ccd/dcbacdcddc//c";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(2, match_prefix(pat, 2, str));
+		ck_assert_int_eq(3, match_prefix(pat, 3, str));
+		ck_assert_int_eq(8, match_prefix(pat, 4, str));
+		ck_assert_int_eq(6, match_prefix(pat, 5, str));
+		ck_assert_int_eq(8, match_prefix(pat, 6, str));
+		ck_assert_int_eq(63, match_prefix(pat, 7, str));
+		ck_assert_int_eq(62, match_prefix(pat, 8, str));
+		ck_assert_int_eq(63, match_prefix(pat, 9, str));
+		ck_assert_int_eq(63, match_prefix(pat, 10, str));
+		ck_assert_int_eq(61, match_prefix(pat, 11, str));
+		ck_assert_int_eq(61, match_prefix(pat, 12, str));
+		ck_assert_int_eq(60, match_prefix(pat, 13, str));
+		ck_assert_int_eq(58, match_prefix(pat, 14, str));
+		ck_assert_int_eq(59, match_prefix(pat, 15, str));
+		ck_assert_int_eq(59, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "cc/?**ba????**b";
+		const char *str =
+		    "cc/babdb/cbb/baa/da/cd///ccabbcdcdaa/dbacbdbadaccb/dbdcc/cdbbac";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(2, match_prefix(pat, 2, str));
+		ck_assert_int_eq(3, match_prefix(pat, 3, str));
+		ck_assert_int_eq(4, match_prefix(pat, 4, str));
+		ck_assert_int_eq(8, match_prefix(pat, 5, str));
+		ck_assert_int_eq(63, match_prefix(pat, 6, str));
+		ck_assert_int_eq(61, match_prefix(pat, 7, str));
+		ck_assert_int_eq(62, match_prefix(pat, 8, str));
+		ck_assert_int_eq(63, match_prefix(pat, 9, str));
+		ck_assert_int_eq(47, match_prefix(pat, 10, str));
+		ck_assert_int_eq(48, match_prefix(pat, 11, str));
+		ck_assert_int_eq(49, match_prefix(pat, 12, str));
+		ck_assert_int_eq(50, match_prefix(pat, 13, str));
+		ck_assert_int_eq(63, match_prefix(pat, 14, str));
+		ck_assert_int_eq(61, match_prefix(pat, 15, str));
+		ck_assert_int_eq(61, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "?**ba*db*b?*/a?";
+		const char *str =
+		    "bd/bcdddabbd//bcb//acbcaaac/dcbbcdadabadba/bd/baadbabcc/a/bcb//";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(2, match_prefix(pat, 2, str));
+		ck_assert_int_eq(63, match_prefix(pat, 3, str));
+		ck_assert_int_eq(61, match_prefix(pat, 4, str));
+		ck_assert_int_eq(52, match_prefix(pat, 5, str));
+		ck_assert_int_eq(55, match_prefix(pat, 6, str));
+		ck_assert_int_eq(50, match_prefix(pat, 7, str));
+		ck_assert_int_eq(51, match_prefix(pat, 8, str));
+		ck_assert_int_eq(55, match_prefix(pat, 9, str));
+		ck_assert_int_eq(53, match_prefix(pat, 10, str));
+		ck_assert_int_eq(54, match_prefix(pat, 11, str));
+		ck_assert_int_eq(55, match_prefix(pat, 12, str));
+		ck_assert_int_eq(56, match_prefix(pat, 13, str));
+		ck_assert_int_eq(57, match_prefix(pat, 14, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 15, str));
+		ck_assert_int_eq(-1, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "?b*da*bc?c**//*";
+		const char *str =
+		    "dbadabcbcbbba/a///d//dcdd////daccbcaaa/a/bacddab/bdcbbdd/bbaa/a";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(2, match_prefix(pat, 2, str));
+		ck_assert_int_eq(13, match_prefix(pat, 3, str));
+		ck_assert_int_eq(4, match_prefix(pat, 4, str));
+		ck_assert_int_eq(5, match_prefix(pat, 5, str));
+		ck_assert_int_eq(13, match_prefix(pat, 6, str));
+		ck_assert_int_eq(12, match_prefix(pat, 7, str));
+		ck_assert_int_eq(9, match_prefix(pat, 8, str));
+		ck_assert_int_eq(10, match_prefix(pat, 9, str));
+		ck_assert_int_eq(9, match_prefix(pat, 10, str));
+		ck_assert_int_eq(13, match_prefix(pat, 11, str));
+		ck_assert_int_eq(63, match_prefix(pat, 12, str));
+		ck_assert_int_eq(62, match_prefix(pat, 13, str));
+		ck_assert_int_eq(29, match_prefix(pat, 14, str));
+		ck_assert_int_eq(38, match_prefix(pat, 15, str));
+		ck_assert_int_eq(38, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "?**c**dc**b*c*a";
+		const char *str = "cba/a/bbcdcccc/bcacacdadab/dad/";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(3, match_prefix(pat, 2, str));
+		ck_assert_int_eq(31, match_prefix(pat, 3, str));
+		ck_assert_int_eq(21, match_prefix(pat, 4, str));
+		ck_assert_int_eq(26, match_prefix(pat, 5, str));
+		ck_assert_int_eq(31, match_prefix(pat, 6, str));
+		ck_assert_int_eq(30, match_prefix(pat, 7, str));
+		ck_assert_int_eq(11, match_prefix(pat, 8, str));
+		ck_assert_int_eq(14, match_prefix(pat, 9, str));
+		ck_assert_int_eq(31, match_prefix(pat, 10, str));
+		ck_assert_int_eq(26, match_prefix(pat, 11, str));
+		ck_assert_int_eq(26, match_prefix(pat, 12, str));
+		ck_assert_int_eq(21, match_prefix(pat, 13, str));
+		ck_assert_int_eq(26, match_prefix(pat, 14, str));
+		ck_assert_int_eq(25, match_prefix(pat, 15, str));
+		ck_assert_int_eq(25, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "$|*ca|**c/c*b|a";
+		const char *str = "bcdaa/a//acdc/bac/caacacdcbcdc/";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(0, match_prefix(pat, 2, str));
+		ck_assert_int_eq(5, match_prefix(pat, 3, str));
+		ck_assert_int_eq(2, match_prefix(pat, 4, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 5, str));
+		ck_assert_int_eq(0, match_prefix(pat, 6, str));
+		ck_assert_int_eq(5, match_prefix(pat, 7, str));
+		ck_assert_int_eq(31, match_prefix(pat, 8, str));
+		ck_assert_int_eq(30, match_prefix(pat, 9, str));
+		ck_assert_int_eq(31, match_prefix(pat, 10, str));
+		ck_assert_int_eq(19, match_prefix(pat, 11, str));
+		ck_assert_int_eq(30, match_prefix(pat, 12, str));
+		ck_assert_int_eq(27, match_prefix(pat, 13, str));
+		ck_assert_int_eq(27, match_prefix(pat, 14, str));
+		ck_assert_int_eq(27, match_prefix(pat, 15, str));
+		ck_assert_int_eq(27, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "*b?c|?$|*b?b**?";
+		const char *str = "cbbbddddda/dbcdbbbccdcb/a//ddab";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(10, match_prefix(pat, 1, str));
+		ck_assert_int_eq(4, match_prefix(pat, 2, str));
+		ck_assert_int_eq(5, match_prefix(pat, 3, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 4, str));
+		ck_assert_int_eq(0, match_prefix(pat, 5, str));
+		ck_assert_int_eq(1, match_prefix(pat, 6, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 7, str));
+		ck_assert_int_eq(0, match_prefix(pat, 8, str));
+		ck_assert_int_eq(10, match_prefix(pat, 9, str));
+		ck_assert_int_eq(4, match_prefix(pat, 10, str));
+		ck_assert_int_eq(5, match_prefix(pat, 11, str));
+		ck_assert_int_eq(4, match_prefix(pat, 12, str));
+		ck_assert_int_eq(10, match_prefix(pat, 13, str));
+		ck_assert_int_eq(31, match_prefix(pat, 14, str));
+		ck_assert_int_eq(31, match_prefix(pat, 15, str));
+		ck_assert_int_eq(31, match_prefix_strlen(pat, str));
+	}
+	{
+		/* From fuzz test */
+		const char *pat = "c|b?*$|*ca*/*ba";
+		const char *str = "bdccacb/aaadbadd/ccaca/c/cdcb/d";
+		ck_assert_int_eq(0, match_prefix(pat, 0, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 1, str));
+		ck_assert_int_eq(0, match_prefix(pat, 2, str));
+		ck_assert_int_eq(1, match_prefix(pat, 3, str));
+		ck_assert_int_eq(2, match_prefix(pat, 4, str));
+		ck_assert_int_eq(7, match_prefix(pat, 5, str));
+		ck_assert_int_eq(-1, match_prefix(pat, 6, str));
+		ck_assert_int_eq(0, match_prefix(pat, 7, str));
+		ck_assert_int_eq(7, match_prefix(pat, 8, str));
+		ck_assert_int_eq(6, match_prefix(pat, 9, str));
+		ck_assert_int_eq(5, match_prefix(pat, 10, str));
+		ck_assert_int_eq(7, match_prefix(pat, 11, str));
+		ck_assert_int_eq(8, match_prefix(pat, 12, str));
+		ck_assert_int_eq(16, match_prefix(pat, 13, str));
+		ck_assert_int_eq(13, match_prefix(pat, 14, str));
+		ck_assert_int_eq(14, match_prefix(pat, 15, str));
+		ck_assert_int_eq(14, match_prefix_strlen(pat, str));
+	}
 }
 END_TEST
 
@@ -1489,6 +1694,7 @@ make_private_suite(void)
 
 	tcase_add_test(tcase_url_parsing_1, test_match_prefix);
 	tcase_add_test(tcase_url_parsing_1, test_match_prefix_strlen);
+	tcase_add_test(tcase_url_parsing_1, test_match_prefix_fuzz);
 	tcase_set_timeout(tcase_url_parsing_1, civetweb_min_test_timeout);
 	suite_add_tcase(suite, tcase_url_parsing_1);