diff --git a/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequestImpl.java b/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequestImpl.java index dd786a0f6c..bebf266de8 100755 --- a/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequestImpl.java +++ b/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequestImpl.java @@ -395,13 +395,15 @@ public String getHeader(String s, boolean checkCase) { public String getParameter(String s) { String name = isNotNoOps() ? b.request.getParameter(s) : null; if (name == null) { - if (b.queryStrings.get(s) != null) { - return b.queryStrings.get(s)[0]; + String[] values = b.queryStrings.get(s); + if (values != null) { + return values[0]; } } return name; } + @Override public Map getParameterMap() { if (!queryComputed) { diff --git a/modules/cpr/src/test/java/org/atmosphere/cpr/AtmosphereRequestTest.java b/modules/cpr/src/test/java/org/atmosphere/cpr/AtmosphereRequestTest.java index b61a064d9d..f3a1997fe3 100644 --- a/modules/cpr/src/test/java/org/atmosphere/cpr/AtmosphereRequestTest.java +++ b/modules/cpr/src/test/java/org/atmosphere/cpr/AtmosphereRequestTest.java @@ -31,6 +31,9 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import static org.mockito.Mockito.mock; @@ -40,6 +43,7 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; +import static org.testng.AssertJUnit.fail; public class AtmosphereRequestTest { private AtmosphereFramework framework; @@ -351,5 +355,41 @@ public void testWrapMethodWithNullAttributeValue() throws IOException, ServletEx assertNull(wrappedRequest.getAttribute("org.eclipse.jetty.multipartConfig"), "Attribute value should be null"); } + public class AtmosphereRequestImplTest { + + @Test + public void testGetParameterRaceCondition() throws InterruptedException { + final Map queryStrings = Collections.synchronizedMap(new HashMap<>()); + queryStrings.put("testParam", new String[]{"testValue"}); + + AtmosphereRequestImpl.Builder builder = new AtmosphereRequestImpl.Builder(); + builder.queryStrings(queryStrings); + + final AtmosphereRequest request = builder.build(); + + Runnable addAndRemove = () -> { + queryStrings.put("testParam", new String[]{"testValue"}); + queryStrings.remove("testParam"); + }; + + Runnable getParameter = () -> { + try { + request.getParameter("testParam"); + } catch (NullPointerException e) { + fail("NullPointerException occurred"); + } + }; + + ExecutorService executor = Executors.newFixedThreadPool(2); + for (int i = 0; i < 10000; i++) { + executor.execute(addAndRemove); + executor.execute(getParameter); + } + + executor.shutdown(); + executor.awaitTermination(1, TimeUnit.MINUTES); + } + } + }