Skip to content

Commit

Permalink
Remove endless loop detection to address linkedin#15.
Browse files Browse the repository at this point in the history
So the obvious downside is the risk of actually getting into an endless
loop but I think the risk is worth it.  If the code is solid then this
is not possible, so I'd rather address those cases as (if?) they come
up, instead causing false failures like the case in this issue.
  • Loading branch information
pgalbraith authored and cstroe committed Nov 4, 2018
1 parent e016ac9 commit 940784b
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 62 deletions.
44 changes: 0 additions & 44 deletions src/main/java/com/linkedin/urls/detection/InputTextReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@
*/
public class InputTextReader {

/**
* The number of times something can be backtracked is this multiplier times the length of the string.
*/
protected static final int MAX_BACKTRACK_MULTIPLIER = 10;

/**
* The content to read.
*/
Expand All @@ -29,16 +24,6 @@ public class InputTextReader {
*/
private int _index = 0;

/**
* Contains the amount of characters that were backtracked. This is used for performance analysis.
*/
private int _backtracked = 0;

/**
* When detecting for exceeding the backtrack limit, make sure the text is at least 20 characters.
*/
private final static int MINIMUM_BACKTRACK_LENGTH = 20;

/**
* Creates a new instance of the InputTextReader using the content to read.
* @param content The content to read.
Expand Down Expand Up @@ -102,47 +87,18 @@ public int getPosition() {
return _index;
}

/**
* Gets the total number of characters that were backtracked when reading.
*/
public int getBacktrackedCount() {
return _backtracked;
}

/**
* Moves the index to the specified position.
* @param position The position to set the index to.
*/
public void seek(int position) {
int backtrackLength = Math.max(_index - position, 0);
_backtracked += backtrackLength;
_index = position;
checkBacktrackLoop(backtrackLength);
}

/**
* Goes back a single character.
*/
public void goBack() {
_backtracked++;
_index--;
checkBacktrackLoop(1);
}

private void checkBacktrackLoop(int backtrackLength) {
if (_backtracked > (_content.length * MAX_BACKTRACK_MULTIPLIER)) {
if (backtrackLength < MINIMUM_BACKTRACK_LENGTH) {
backtrackLength = MINIMUM_BACKTRACK_LENGTH;
}

int start = Math.max(_index, 0);
if (start + backtrackLength > _content.length) {
backtrackLength = _content.length - start;
}

String badText = new String(_content, start, backtrackLength);
throw new NegativeArraySizeException("Backtracked max amount of characters. Endless loop detected. Bad Text: '"
+ badText + "'");
}
}
}
9 changes: 0 additions & 9 deletions src/main/java/com/linkedin/urls/detection/UrlDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,6 @@ public UrlDetector(String content, UrlDetectorOptions options) {
_options = options;
}

/**
* Gets the number of characters that were backtracked while reading the input. This is useful for performance
* measurement.
* @return The count of characters that were backtracked while reading.
*/
public int getBacktracked() {
return _reader.getBacktrackedCount();
}

/**
* Detects the urls and returns a list of detected url strings.
* @return A list with detected urls.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,4 @@ public void testSeek() {
reader.seek(1);
Assert.assertEquals(reader.read(), CONTENT.charAt(1));
}

@Test(expectedExceptions = NegativeArraySizeException.class, expectedExceptionsMessageRegExp = ".*" + CONTENT + ".*")
public void testEndlessLoopDetection() {
InputTextReader reader = new InputTextReader(CONTENT);
for (int i = 0; i < InputTextReader.MAX_BACKTRACK_MULTIPLIER + 1; i++) {
reader.seek(CONTENT.length());
reader.seek(0);
}
}
}
36 changes: 36 additions & 0 deletions src/test/java/com/linkedin/urls/detection/TestUriDetection.java
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,42 @@ public void testBacktrackInvalidUsernamePassword() {
runTest("http://hello:asdf.com", UrlDetectorOptions.Default, "asdf.com");
}

/*
* https://github.com/linkedin/URL-Detector/issues/12
*/
@Test
public void testIssue12() {
runTest("http://user:[email protected] host.com", UrlDetectorOptions.Default, "http://user:[email protected]", "host.com");
}

/*
* https://github.com/linkedin/URL-Detector/issues/13
*/
@Test
public void testIssue13() {
runTest("[email protected]/page", UrlDetectorOptions.Default, "[email protected]/page");
runTest("[email protected]", UrlDetectorOptions.Default, "[email protected]");
runTest("[email protected]", UrlDetectorOptions.Default, "[email protected]");
runTest("[email protected]", UrlDetectorOptions.Default, "[email protected]");
runTest("first.middle.reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylonglastname@gmail.com", UrlDetectorOptions.Default, "first.middle.reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylonglastname@gmail.com");
}

/*
* https://github.com/linkedin/URL-Detector/issues/15
*/
@Test
public void testIssue15() {
runTest(".............:::::::::::;;;;;;;;;;;;;;;::...............................................:::::::::::::::::::::::::::::....................", UrlDetectorOptions.Default);
}

/*
* https://github.com/linkedin/URL-Detector/issues/16
*/
@Test
public void testIssue16() {
runTest("://VIVE MARINE LE PEN//:@.", UrlDetectorOptions.Default);
}

private void runTest(String text, UrlDetectorOptions options, String... expected) {
//do the detection
UrlDetector parser = new UrlDetector(text, options);
Expand Down

0 comments on commit 940784b

Please sign in to comment.