Skip to content

Instantly share code, notes, and snippets.

Created October 17, 2010 16:09
Show Gist options
  • Save anonymous/630969 to your computer and use it in GitHub Desktop.
Save anonymous/630969 to your computer and use it in GitHub Desktop.
DoSSaveRegex
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