Skip to content
This repository has been archived by the owner on Oct 26, 2024. It is now read-only.

Commit

Permalink
fix(YouTube - Custom filter): Fix app crash if invalid character is u…
Browse files Browse the repository at this point in the history
…sed in custom filter (#506)
  • Loading branch information
LisoUseInAIKyrios authored Oct 21, 2023
1 parent e68646d commit debd0a2
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,20 @@ public FilterGroupResult check(final String string) {

final class CustomFilterGroup extends StringFilterGroup {

public CustomFilterGroup(final SettingsEnum setting, final SettingsEnum filter) {
super(setting, filter.getString().split("\\s+"));
private static String[] getFilterPatterns(SettingsEnum setting) {
String[] patterns = setting.getString().split("\\s+");
for (String pattern : patterns) {
if (!StringTrieSearch.isValidPattern(pattern)) {
ReVancedUtils.showToastLong("Invalid custom filter, resetting to default");
setting.saveValue(setting.defaultValue);
return getFilterPatterns(setting);
}
}
return patterns;
}

public CustomFilterGroup(SettingsEnum setting, SettingsEnum filter) {
super(setting, getFilterPatterns(filter));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package app.revanced.integrations.utils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Objects;

public final class ByteTrieSearch extends TrieSearch<byte[]> {

private static final class ByteTrieNode extends TrieNode<byte[]> {
Expand All @@ -22,35 +17,25 @@ TrieNode<byte[]> createNode(char nodeCharacterValue) {
char getCharValue(byte[] text, int index) {
return (char) text[index];
}
@Override
int getTextLength(byte[] text) {
return text.length;
}
}

public ByteTrieSearch() {
super(new ByteTrieNode());
}

@Override
public void addPattern(@NonNull byte[] pattern) {
super.addPattern(pattern, pattern.length, null);
}

@Override
public void addPattern(@NonNull byte[] pattern, @NonNull TriePatternMatchedCallback<byte[]> callback) {
super.addPattern(pattern, pattern.length, Objects.requireNonNull(callback));
}

@Override
public boolean matches(@NonNull byte[] textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
return super.matches(textToSearch, textToSearch.length, startIndex, endIndex, callbackParameter);
}

@Override
public boolean matches(@NonNull byte[] textToSearch, int startIndex) {
return matches(textToSearch, startIndex, textToSearch.length, null);
/**
* @return If the pattern is valid to add to this instance.
*/
public static boolean isValidPattern(byte[] pattern) {
for (byte b : pattern) {
if (TrieNode.isInvalidRange((char) b)) {
return false;
}
}
return true;
}

@Override
public boolean matches(@NonNull byte[] textToSearch, @Nullable Object callbackParameter) {
return matches(textToSearch,0, textToSearch.length, callbackParameter);
public ByteTrieSearch() {
super(new ByteTrieNode());
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package app.revanced.integrations.utils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Objects;

/**
* Text pattern searching using a prefix tree (trie).
*/
Expand All @@ -25,34 +20,25 @@ TrieNode<String> createNode(char nodeValue) {
char getCharValue(String text, int index) {
return text.charAt(index);
}
@Override
int getTextLength(String text) {
return text.length();
}
}

public StringTrieSearch() {
super(new StringTrieNode());
}

@Override
public void addPattern(@NonNull String pattern) {
super.addPattern(pattern, pattern.length(), null);
}

@Override
public void addPattern(@NonNull String pattern, @NonNull TriePatternMatchedCallback<String> callback) {
super.addPattern(pattern, pattern.length(), Objects.requireNonNull(callback));
}

@Override
public boolean matches(@NonNull String textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
return super.matches(textToSearch, textToSearch.length(), startIndex, endIndex, callbackParameter);
}

@Override
public boolean matches(@NonNull String textToSearch, @Nullable Object callbackParameter) {
return matches(textToSearch, 0, textToSearch.length(), callbackParameter);
/**
* @return If the pattern is valid to add to this instance.
*/
public static boolean isValidPattern(String pattern) {
for (int i = 0, length = pattern.length(); i < length; i++) {
if (TrieNode.isInvalidRange(pattern.charAt(i))) {
return false;
}
}
return true;
}

@Override
public boolean matches(@NonNull String textToSearch, int startIndex) {
return matches(textToSearch, startIndex, textToSearch.length(), null);
public StringTrieSearch() {
super(new StringTrieNode());
}
}
93 changes: 52 additions & 41 deletions app/src/main/java/app/revanced/integrations/utils/TrieSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static abstract class TrieNode<T> {
private static final int CHILDREN_ARRAY_INCREASE_SIZE_INCREMENT = 2;
private static final int CHILDREN_ARRAY_MAX_SIZE = MAX_VALID_CHAR - MIN_VALID_CHAR + 1;

private static boolean isInvalidRange(char character) {
static boolean isInvalidRange(char character) {
return character < MIN_VALID_CHAR || character > MAX_VALID_CHAR;
}

Expand Down Expand Up @@ -227,7 +227,7 @@ private static <T> boolean addNodeToArray(TrieNode<T>[] array, TrieNode<T> child
}

private static int hashIndexForTableSize(int arraySize, char nodeValue) {
return (nodeValue - MIN_VALID_CHAR) % arraySize;
return nodeValue % arraySize;
}

/**
Expand Down Expand Up @@ -300,6 +300,7 @@ private int estimatedNumberOfPointersUsed() {

abstract TrieNode<T> createNode(char nodeValue);
abstract char getCharValue(T text, int index);
abstract int getTextLength(T text);
}

/**
Expand All @@ -323,15 +324,62 @@ public final void addPatterns(@NonNull T... patterns) {
}
}

/**
* Adds a pattern that will always return a positive match if found.
*
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
*/
public void addPattern(@NonNull T pattern) {
addPattern(pattern, root.getTextLength(pattern), null);
}

/**
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
* @param callback Callback to determine if searching should halt when a match is found.
*/
public void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback<T> callback) {
addPattern(pattern, root.getTextLength(pattern), Objects.requireNonNull(callback));
}

void addPattern(@NonNull T pattern, int patternLength, @Nullable TriePatternMatchedCallback<T> callback) {
if (patternLength == 0) return; // Nothing to match

patterns.add(pattern);
root.addPattern(pattern, patternLength, 0, callback);
}

final boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex,
@Nullable Object callbackParameter) {
public final boolean matches(@NonNull T textToSearch) {
return matches(textToSearch, 0);
}

public boolean matches(@NonNull T textToSearch, @NonNull Object callbackParameter) {
return matches(textToSearch, 0, root.getTextLength(textToSearch),
Objects.requireNonNull(callbackParameter));
}

public boolean matches(@NonNull T textToSearch, int startIndex) {
return matches(textToSearch, startIndex, root.getTextLength(textToSearch));
}

public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) {
return matches(textToSearch, startIndex, endIndex, null);
}

/**
* Searches through text, looking for any substring that matches any pattern in this tree.
*
* @param textToSearch Text to search through.
* @param startIndex Index to start searching, inclusive value.
* @param endIndex Index to stop matching, exclusive value.
* @param callbackParameter Optional parameter passed to the callbacks.
* @return If any pattern matched, and it's callback halted searching.
*/
public boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
return matches(textToSearch, root.getTextLength(textToSearch), startIndex, endIndex, callbackParameter);
}

private boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex,
@Nullable Object callbackParameter) {
if (endIndex > textToSearchLength) {
throw new IllegalArgumentException("endIndex: " + endIndex
+ " is greater than texToSearchLength: " + textToSearchLength);
Expand Down Expand Up @@ -365,41 +413,4 @@ public int numberOfPatterns() {
public List<T> getPatterns() {
return Collections.unmodifiableList(patterns);
}

/**
* Adds a pattern that will always return a positive match if found.
*
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
*/
public abstract void addPattern(@NonNull T pattern);

/**
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
* @param callback Callback to determine if searching should halt when a match is found.
*/
public abstract void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback<T> callback);


/**
* Searches through text, looking for any substring that matches any pattern in this tree.
*
* @param textToSearch Text to search through.
* @param startIndex Index to start searching, inclusive value.
* @param endIndex Index to stop matching, exclusive value.
* @param callbackParameter Optional parameter passed to the callbacks.
* @return If any pattern matched, and it's callback halted searching.
*/
public abstract boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter);

public abstract boolean matches(@NonNull T textToSearch, int startIndex);

public abstract boolean matches(@NonNull T textToSearch, @Nullable Object callbackParameter);

public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) {
return matches(textToSearch, startIndex, endIndex, null);
}

public final boolean matches(@NonNull T textToSearch) {
return matches(textToSearch, 0);
}
}

0 comments on commit debd0a2

Please sign in to comment.