From 68bd01cbc15e50359739bbef2a7e15559c9e9630 Mon Sep 17 00:00:00 2001 From: ghidragon <106987263+ghidragon@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:56:03 -0400 Subject: [PATCH] GP-5615 fixed NPE in GoTo dialog when '\' entered --- .../util/navigation/SymbolMatcherTest.java | 10 ++++++ .../java/ghidra/util/UserSearchUtilsTest.java | 10 ++++++ .../java/ghidra/util/UserSearchUtils.java | 36 +++++++++---------- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/navigation/SymbolMatcherTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/navigation/SymbolMatcherTest.java index 30fe219b0f..dfdfe14492 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/navigation/SymbolMatcherTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/navigation/SymbolMatcherTest.java @@ -421,6 +421,16 @@ public class SymbolMatcherTest { } + @Test + public void testBackslash() { + matcher = new SymbolMatcher("\\", false); + assertMatches(matcher, "\\"); + + matcher = new SymbolMatcher("\\bob\\", false); + assertMatches(matcher, "\\bob\\"); + + } + private Symbol symbol(String path) { String[] split = path.split(Namespace.DELIMITER); String name = split[split.length - 1]; diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/UserSearchUtilsTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/UserSearchUtilsTest.java index 315b9ae458..a51b43240b 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/UserSearchUtilsTest.java +++ b/Ghidra/Framework/Generic/src/test/java/ghidra/util/UserSearchUtilsTest.java @@ -147,6 +147,16 @@ public class UserSearchUtilsTest { assertTrue(pattern.matcher("foo\\[bob").matches()); } + @Test + public void testCreateContainsSingleBackslash() { + Pattern pattern = UserSearchUtils.createContainsPattern("\\", true, CASE_SENSITIVE); + + assertTrue(pattern.matcher("\\").matches()); + assertTrue(pattern.matcher("\\bob").matches()); + assertTrue(pattern.matcher("bob\\").matches()); + assertTrue(pattern.matcher("b\\ob").matches()); + } + @Test public void testStartsPatternNoWildCards() { Pattern pattern = UserSearchUtils.createStartsWithPattern("bob", true, CASE_SENSITIVE); diff --git a/Ghidra/Framework/Utility/src/main/java/ghidra/util/UserSearchUtils.java b/Ghidra/Framework/Utility/src/main/java/ghidra/util/UserSearchUtils.java index 5b9e81b62d..b2a5540a54 100644 --- a/Ghidra/Framework/Utility/src/main/java/ghidra/util/UserSearchUtils.java +++ b/Ghidra/Framework/Utility/src/main/java/ghidra/util/UserSearchUtils.java @@ -313,7 +313,6 @@ public class UserSearchUtils { if (allowGlobbing) { // Note: Order is important! (due to how escape characters added and checked) - escaped = escapeEscapeCharacters(escaped); escaped = escapeNonGlobbingRegexCharacters(escaped); escaped = convertGlobbingCharactersToRegex(escaped); } @@ -352,22 +351,6 @@ public class UserSearchUtils { return starReplaced; } - /** - * Replaces all escape characters ('\') by escaping that character ('\\'). - *
- * Note: this method will not escape characters that are escaping a globbing character - * (see {@link #NON_GLOB_BACKSLASH_PATTERN}. - * - * @param input - * The string containing potential escape characters. - * @return The fixed string - */ - private static String escapeEscapeCharacters(String input) { - // replace all '\' chars that are not followed by *known* special chars - Matcher backslashMatcher = NON_GLOB_BACKSLASH_PATTERN.matcher(input); - return backslashMatcher.replaceAll("\\\\\\\\"); - } - /** * Escapes all special regex characters so that they are treated as literal characters * by the regex engine. @@ -400,9 +383,24 @@ public class UserSearchUtils { */ // package for testing static String escapeSomeRegexCharacters(String input, char[] doNotEscape) { + // + // Note: we have to handle backslash characters specially, since we have to look at the + // character that follows the backslash. + // + // This search utility allows users to perform globbing operations + // using '*' and '?'. To disable that feature, users can escape those specific characters + // using a backslash. Except for these special cases, we want to treat backslashes + // literally, assuming users wish to search for backslash characters. + // + // Escape any '\' characters that are not followed by a globbing char + // + Matcher backslashMatcher = NON_GLOB_BACKSLASH_PATTERN.matcher(input); + String updated = backslashMatcher.replaceAll("\\\\\\\\"); + + // Escape all other regex chars individually with a backslash StringBuilder buffy = new StringBuilder(); - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); + for (int i = 0; i < updated.length(); i++) { + char c = updated.charAt(i); if (contains(doNotEscape, c)) { // a bit inefficient, but the array should always be short