Created
October 17, 2010 16:09
-
-
Save anonymous/630969 to your computer and use it in GitHub Desktop.
DoSSaveRegex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.Assert.*; | |
import java.util.Arrays; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.TimeUnit; | |
import java.util.regex.PatternSyntaxException; | |
import org.junit.After; | |
import org.junit.Before; | |
import org.junit.Test; | |
public class DoSSafeRegexTest { | |
DoSPreventingExecutor executor; | |
DoSSafeRegex regex; | |
@Before | |
public void setUp() throws Exception { | |
executor = new DoSPreventingExecutor(); | |
} | |
@After | |
public void tearDown() throws Exception { | |
executor.shutDown(); | |
} | |
@Test(expected=IllegalStateException.class) | |
public void testTimeout() { | |
executor = new DoSPreventingExecutor(Executors.newFixedThreadPool(1), | |
100, TimeUnit.MILLISECONDS); | |
executor.execute(new Callable<Boolean>() { | |
@Override | |
public Boolean call() throws Exception { | |
for(;;); | |
} | |
}, new DoSSafeRegex.ExceptionMapper()); | |
} | |
@Test(expected=PatternSyntaxException.class) | |
public void testInvalidPattern() { | |
regex = new DoSSafeRegex(executor, "[[0-9]"); | |
regex.match(""); | |
} | |
@Test | |
public void testMatch() { | |
regex = new DoSSafeRegex(executor, "[0-9]"); | |
assertTrue(regex.match("0")); | |
assertFalse(regex.match("X")); | |
} | |
@Test | |
public void testSplit() { | |
regex = new DoSSafeRegex(executor, ";"); | |
assertEquals("[a, b]", | |
Arrays.asList(regex.split("a;b", 2)).toString()); | |
} | |
} | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Future; | |
import java.util.concurrent.TimeUnit; | |
public class DoSPreventingExecutor { | |
private final ExecutorService service; | |
private final long tiemout; | |
private final TimeUnit unit; | |
public DoSPreventingExecutor(ExecutorService service, | |
long timeout, | |
TimeUnit unit) { | |
this.service = service; | |
this.tiemout = timeout; | |
this.unit = unit; | |
} | |
public DoSPreventingExecutor() { | |
this(Executors.newFixedThreadPool(10), 30, TimeUnit.SECONDS); | |
} | |
public <T> T execute(Callable<T> task, ExceptionMapper handler) { | |
Future<T> result = service.submit(task); | |
try { | |
return result.get(tiemout, unit); | |
} catch(Exception e) { | |
throw handler.map(e); | |
} | |
} | |
public void shutDown() { | |
this.service.shutdown(); | |
} | |
interface ExceptionMapper { | |
public RuntimeException map(Exception e); | |
} | |
} | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutionException; | |
public class DoSSafeRegex { | |
private final DoSPreventingExecutor executor; | |
private final String pattern; | |
private static final ExceptionMapper mapper = | |
new ExceptionMapper(); | |
public DoSSafeRegex(DoSPreventingExecutor executor, | |
String pattern) { | |
this.executor = executor; | |
this.pattern = pattern; | |
} | |
public boolean match(final String value) { | |
return executor.execute( | |
new Callable<Boolean>() { | |
@Override | |
public Boolean call() | |
throws Exception { | |
return value.matches(pattern); | |
} | |
}, mapper); | |
} | |
public String[] split(final String value, | |
final int limit) { | |
return executor.execute( | |
new Callable<String[]>() { | |
@Override | |
public String[] call() | |
throws Exception { | |
return value.split(pattern, | |
limit); | |
} | |
}, mapper); | |
} | |
protected static class ExceptionMapper | |
implements DoSPreventingExecutor.ExceptionMapper { | |
@Override | |
public RuntimeException map(Exception e) { | |
if(e instanceof ExecutionException) { | |
Throwable cause = e.getCause(); | |
if (cause instanceof RuntimeException) { | |
throw (RuntimeException) cause; | |
} else if (cause instanceof Error) { | |
throw (Error) cause; | |
} else { | |
throw new IllegalStateException(cause); | |
} | |
} else { | |
throw new IllegalStateException(e); | |
} | |
} | |
} | |
} | |
public class ExecutionFailedException extends Exception { | |
private static final long serialVersionUID = 1L; | |
public ExecutionFailedException(Exception e) { | |
super(e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment