git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 8/8] grep: optimistically use PCRE2_MATCH_INVALID_UTF

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jul 26, 2019, 15:08 UTC
Message-ID
<20190726150818.6373-9-avarab@gmail.com>
In-Reply-To
<20190724151415.3698-1-avarab@gmail.com>

As discussed in the "grep: stess test PCRE v2 on invalid UTF-8 data" commit leading up to this one there's a regression in b65abcafc7 ("grep: use PCRE v2 for optimized fixed-string search", 2019-07-01) when matching UTF-8 data.

This ultimately isn't straightforward to just "fix", because the kwset backend was so dumb about icase matching that we'd skip it entirely on non-ASCII. See the code removed in 48de2a768c ("grep: remove the kwset optimization", 2019-07-01).

Just going back to the C library for those isn't ideal, since it's likely to be even dumber about these mixed-encoding cases.

So let's support this "properly" using the PCRE2_MATCH_INVALID_UTF flag. This is new code that's not in any released PCRE v2 version, so we might need a fix that emulates it somehow. I figure that the case that with the non-icase bug out of the way this is obscure enough to tell people "upgrade your PCRE v2 too!'. It'll likely be released by the time we release the git version this commit is part of.

We can't just use PCRE2_NO_UTF_CHECK instead for the reasons discussed in [1].

1. https://public-inbox.org/git/87lfwn70nb.fsf@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                        |  1 +
 grep.c                          |  2 +-
 grep.h                          |  3 +++
 t/helper/test-pcre2-config.c    | 12 ++++++++++++
 t/helper/test-tool.c            |  1 +
 t/helper/test-tool.h            |  1 +
 t/t7812-grep-icase-non-ascii.sh | 13 ++++++++++++-
 7 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 t/helper/test-pcre2-config.c
diff --git a/Makefile b/Makefile
index bd246f2989..dd38d5e527 100644
--- a/Makefile
+++ b/Makefile
@@ -726,6 +726,7 @@ TEST_BUILTINS_OBJS += test-oidmap.o
 TEST_BUILTINS_OBJS += test-online-cpus.o
 TEST_BUILTINS_OBJS += test-parse-options.o
 TEST_BUILTINS_OBJS += test-path-utils.o
+TEST_BUILTINS_OBJS += test-pcre2-config.o
 TEST_BUILTINS_OBJS += test-pkt-line.o
 TEST_BUILTINS_OBJS += test-prio-queue.o
 TEST_BUILTINS_OBJS += test-reach.o
diff --git a/grep.c b/grep.c
index c7c06ae08d..8b8b9efe12 100644
--- a/grep.c
+++ b/grep.c
@@ -474,7 +474,7 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
 	}
 	if (!opt->ignore_locale && is_utf8_locale() && has_non_ascii(p->pattern) &&
 	    !(!opt->ignore_case && (p->fixed || p->is_fixed)))
-		options |= PCRE2_UTF;
+		options |= (PCRE2_UTF | PCRE2_MATCH_INVALID_UTF);
 
 	p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
 					 p->patternlen, options, &error, &erroffset,
diff --git a/grep.h b/grep.h
index c0c71eb4a9..506f05b97b 100644
--- a/grep.h
+++ b/grep.h
@@ -21,6 +21,9 @@ typedef int pcre_extra;
 #ifdef USE_LIBPCRE2
 #define PCRE2_CODE_UNIT_WIDTH 8
 #include <pcre2.h>
+#ifndef PCRE2_MATCH_INVALID_UTF
+#define PCRE2_MATCH_INVALID_UTF 0
+#endif
 #else
 typedef int pcre2_code;
 typedef int pcre2_match_data;
diff --git a/t/helper/test-pcre2-config.c b/t/helper/test-pcre2-config.c
new file mode 100644
index 0000000000..5258fdddba
--- /dev/null
+++ b/t/helper/test-pcre2-config.c
@@ -0,0 +1,12 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "grep.h"
+
+int cmd__pcre2_config(int argc, const char **argv)
+{
+	if (argc == 2 && !strcmp(argv[1], "has-PCRE2_MATCH_INVALID_UTF")) {
+		int value = PCRE2_MATCH_INVALID_UTF;
+		return !value;
+	}
+	return 1;
+}
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index ce7e89028c..e022ce0e48 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -40,6 +40,7 @@ static struct test_cmd cmds[] = {
 	{ "online-cpus", cmd__online_cpus },
 	{ "parse-options", cmd__parse_options },
 	{ "path-utils", cmd__path_utils },
+	{ "pcre2-config", cmd__pcre2_config },
 	{ "pkt-line", cmd__pkt_line },
 	{ "prio-queue", cmd__prio_queue },
 	{ "reach", cmd__reach },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index f805bb39ae..acd8af2a9d 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -30,6 +30,7 @@ int cmd__oidmap(int argc, const char **argv);
 int cmd__online_cpus(int argc, const char **argv);
 int cmd__parse_options(int argc, const char **argv);
 int cmd__path_utils(int argc, const char **argv);
+int cmd__pcre2_config(int argc, const char **argv);
 int cmd__pkt_line(int argc, const char **argv);
 int cmd__prio_queue(int argc, const char **argv);
 int cmd__reach(int argc, const char **argv);
diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
index 531eb59d57..848d46e4f9 100755
--- a/t/t7812-grep-icase-non-ascii.sh
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -74,11 +74,22 @@ test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep non-ASCII from invali
 	test_cmp expected actual
 '
 
-test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep non-ASCII from invalid UTF-8 data with -i' '
+test_lazy_prereq PCRE2_MATCH_INVALID_UTF '
+	test-tool pcre2-config has-PCRE2_MATCH_INVALID_UTF
+'
+
+test_expect_success GETTEXT_LOCALE,LIBPCRE2,!PCRE2_MATCH_INVALID_UTF 'PCRE v2: grep non-ASCII from invalid UTF-8 data with -i' '
 	test_might_fail git grep -hi "Æ" invalid-0x80 >actual &&
 	test_cmp expected actual &&
 	test_must_fail git grep -hi "(*NO_JIT)Æ" invalid-0x80 &&
 	test_cmp expected actual
 '
 
+test_expect_success GETTEXT_LOCALE,LIBPCRE2,PCRE2_MATCH_INVALID_UTF 'PCRE v2: grep non-ASCII from invalid UTF-8 data with -i' '
+	git grep -hi "Æ" invalid-0x80 >actual &&
+	test_cmp expected actual &&
+	git grep -hi "(*NO_JIT)Æ" invalid-0x80 &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.22.0.455.g172b71a6c5
Previous: Junio C HamanoNext: Junio C Hamano
Message 36 of 70 in “grep: use custom JIT stack with pcre2”
  1. grep: use custom JIT stack with pcre2Carlo Marcelo Arenas Belón, Jul 21, 2019
  2. 0/3 grep: PCRE JIT fixesÆvar Arnfjörð Bjarmason, Jul 24, 2019
  3. Junio C HamanoJul 24, 2019
  4. Ævar Arnfjörð BjarmasonJul 24, 2019
  5. 1/8 grep: remove overly paranoid BUG(...) codeÆvar Arnfjörð Bjarmason, Jul 26, 2019
  6. 2/8 grep: stop "using" a custom JIT stack with PCRE v2Ævar Arnfjörð Bjarmason, Jul 26, 2019
  7. Carlo ArenasJul 29, 2019
  8. 3/8 grep: stop using a custom JIT stack with PCRE v1Ævar Arnfjörð Bjarmason, Jul 26, 2019
  9. Carlo ArenasJul 29, 2019
  10. 4/8 grep: consistently use "p->fixed" in compile_regexp()Ævar Arnfjörð Bjarmason, Jul 26, 2019
  11. Carlo ArenasJul 29, 2019
  12. Ævar Arnfjörð BjarmasonJul 29, 2019
  13. Ævar Arnfjörð BjarmasonJul 29, 2019
  14. Junio C HamanoJul 29, 2019
  15. 5/8 grep: create a "is_fixed" member in "grep_pat"Ævar Arnfjörð Bjarmason, Jul 26, 2019
  16. 7/8 grep: do not enter PCRE2_UTF mode on fixed matchingÆvar Arnfjörð Bjarmason, Jul 26, 2019
  17. Junio C HamanoJul 26, 2019
  18. 6/8 grep: stess test PCRE v2 on invalid UTF-8 dataÆvar Arnfjörð Bjarmason, Jul 26, 2019
  19. Junio C HamanoJul 26, 2019
  20. Ævar Arnfjörð BjarmasonJul 26, 2019
  21. Carlo ArenasJul 29, 2019
  22. t7812: add missing redirectsAndreas Schwab, Nov 26, 2019
  23. Johannes SchindelinNov 26, 2019
  24. Andreas SchwabNov 26, 2019
  25. Jeff KingNov 27, 2019
  26. t7812: expect failure for grep -i with invalid UTF-8 dataTodd Zullinger, Nov 30, 2019
  27. Andreas SchwabNov 30, 2019
  28. Junio C HamanoDec 1, 2019
  29. Andreas SchwabDec 1, 2019
  30. Todd ZullingerDec 1, 2019
  31. Junio C HamanoDec 2, 2019
  32. 0/8 grep: PCRE JIT fixes + ab/no-kwset fixÆvar Arnfjörð Bjarmason, Jul 26, 2019
  33. Junio C HamanoJul 26, 2019
  34. Ævar Arnfjörð BjarmasonJul 29, 2019
  35. Junio C HamanoJul 29, 2019
  36. 8/8 grep: optimistically use PCRE2_MATCH_INVALID_UTFÆvar Arnfjörð Bjarmason, Jul 26, 2019
  37. Junio C HamanoJul 26, 2019
  38. Ævar Arnfjörð BjarmasonJul 26, 2019
  39. Ævar Arnfjörð BjarmasonJul 26, 2019
  40. 0/4 grep: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  41. 1/2 grep/pcre2 tests: don't rely on invalid UTF-8 data testÆvar Arnfjörð Bjarmason, Jan 24, 2021
  42. 2/2 grep/pcre2: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  43. Ramsay JonesJan 24, 2021
  44. Ramsay JonesJan 24, 2021
  45. Ævar Arnfjörð BjarmasonJan 24, 2021
  46. Ramsay JonesJan 24, 2021
  47. Ævar Arnfjörð BjarmasonJan 24, 2021
  48. 0/2 grep: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  49. 0/2 grep: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  50. 1/2 grep/pcre2 tests: don't rely on invalid UTF-8 data testÆvar Arnfjörð Bjarmason, Jan 24, 2021
  51. 2/2 grep/pcre2: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  52. 1/4 grep/pcre2 tests: don't rely on invalid UTF-8 data testÆvar Arnfjörð Bjarmason, Jan 24, 2021
  53. 4/4 grep/pcre2: better support invalid UTF-8 haystacksÆvar Arnfjörð Bjarmason, Jan 24, 2021
  54. 3/4 grep/pcre2: further simplify boolean spaghettiÆvar Arnfjörð Bjarmason, Jan 24, 2021
  55. 2/4 grep/pcre2: simplify boolean spaghettiÆvar Arnfjörð Bjarmason, Jan 24, 2021
  56. Junio C HamanoJan 24, 2021
  57. Johannes SixtJan 24, 2021
  58. 2/3 grep: stop "using" a custom JIT stack with PCRE v2Ævar Arnfjörð Bjarmason, Jul 24, 2019
  59. Junio C HamanoJul 24, 2019
  60. Ævar Arnfjörð BjarmasonJul 24, 2019
  61. Carlo ArenasJul 25, 2019
  62. 1/3 grep: remove overly paranoid BUG(...) codeÆvar Arnfjörð Bjarmason, Jul 24, 2019
  63. 3/3 grep: stop using a custom JIT stack with PCRE v1Ævar Arnfjörð Bjarmason, Jul 24, 2019
  64. Carlo ArenasJul 26, 2019
  65. Ævar Arnfjörð BjarmasonJul 26, 2019
  66. Carlo ArenasJul 26, 2019
  67. Ævar Arnfjörð BjarmasonJul 26, 2019
  68. 0/2 PCRE1 cleanupCarlo Marcelo Arenas Belón, Jul 26, 2019
  69. 1/2 grep: make sure NO_LIBPCRE1_JIT disable JIT in PCRE1Carlo Marcelo Arenas Belón, Jul 26, 2019
  70. 2/2 grep: refactor and simplify PCRE1 supportCarlo Marcelo Arenas Belón, Jul 26, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.