diff --git a/CVE-2016-5007.patch b/CVE-2016-5007.patch new file mode 100644 index 0000000000000000000000000000000000000000..b33c778a0175a13c4c39b5635d3138f4edba1429 --- /dev/null +++ b/CVE-2016-5007.patch @@ -0,0 +1,659 @@ +From a30ab30e4e9ae021fdda04e9abfc228476b846b5 Mon Sep 17 00:00:00 2001 +From: Rossen Stoyanchev +Date: Mon, 25 Apr 2016 21:33:50 -0400 +Subject: [PATCH] Introduce HandlerMapping introspection API + +--- + .../handler/AbstractHandlerMapping.java | 7 + + .../handler/AbstractUrlHandlerMapping.java | 19 +- + .../RequestMappingHandlerMapping.java | 18 +- + .../support/HandlerMappingIntrospector.java | 192 ++++++++++++++++++ + .../support/MatchableHandlerMapping.java | 41 ++++ + .../servlet/support/RequestMatchResult.java | 77 +++++++ + .../HandlerMappingIntrospectorTests.java | 190 +++++++++++++++++ + 7 files changed, 542 insertions(+), 2 deletions(-) + create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/support/HandlerMappingIntrospector.java + create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/support/MatchableHandlerMapping.java + create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestMatchResult.java + create mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/support/HandlerMappingIntrospectorTests.java + +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +index a1464ce..3532502 100644 +--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +@@ -27,8 +27,15 @@ import org.springframework.core.Ordered; + import org.springframework.util.AntPathMatcher; + import org.springframework.util.Assert; + import org.springframework.util.PathMatcher; ++import org.springframework.web.HttpRequestHandler; + import org.springframework.web.context.request.WebRequestInterceptor; + import org.springframework.web.context.support.WebApplicationObjectSupport; ++import org.springframework.web.cors.CorsConfiguration; ++import org.springframework.web.cors.CorsConfigurationSource; ++import org.springframework.web.cors.CorsProcessor; ++import org.springframework.web.cors.CorsUtils; ++import org.springframework.web.cors.DefaultCorsProcessor; ++import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + import org.springframework.web.servlet.HandlerExecutionChain; + import org.springframework.web.servlet.HandlerInterceptor; + import org.springframework.web.servlet.HandlerMapping; +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +index df23203..3ef0d98 100644 +--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +@@ -31,6 +31,8 @@ import org.springframework.util.Assert; + import org.springframework.util.CollectionUtils; + import org.springframework.web.servlet.HandlerExecutionChain; + import org.springframework.web.servlet.HandlerMapping; ++import org.springframework.web.servlet.support.MatchableHandlerMapping; ++import org.springframework.web.servlet.support.RequestMatchResult; + + /** + * Abstract base class for URL-mapped {@link org.springframework.web.servlet.HandlerMapping} +@@ -51,7 +53,8 @@ import org.springframework.web.servlet.HandlerMapping; + * @author Arjen Poutsma + * @since 16.04.2003 + */ +-public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { ++public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping ++ implements MatchableHandlerMapping { + + private Object rootHandler; + +@@ -253,6 +256,20 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { + request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); + } + ++ @Override ++ public RequestMatchResult match(HttpServletRequest request, String pattern) { ++ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); ++ if (getPathMatcher().match(pattern, lookupPath)) { ++ return new RequestMatchResult(pattern, lookupPath, getPathMatcher()); ++ } ++ else if (useTrailingSlashMatch()) { ++ if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) { ++ return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher()); ++ } ++ } ++ return null; ++ } ++ + /** + * Register the specified handler for the given URL paths. + * @param urlPaths the URLs that the bean should be mapped to +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java +index b4a4a0f..c1c74ba 100644 +--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java +@@ -19,6 +19,8 @@ package org.springframework.web.servlet.mvc.method.annotation; + import java.lang.reflect.Method; + import java.util.ArrayList; + import java.util.List; ++import java.util.Set; ++import javax.servlet.http.HttpServletRequest; + + import org.springframework.context.EmbeddedValueResolverAware; + import org.springframework.core.annotation.AnnotationUtils; +@@ -38,6 +40,8 @@ import org.springframework.web.servlet.mvc.condition.RequestCondition; + import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; + import org.springframework.web.servlet.mvc.method.RequestMappingInfo; + import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; ++import org.springframework.web.servlet.support.MatchableHandlerMapping; ++import org.springframework.web.servlet.support.RequestMatchResult; + + /** + * Creates {@link RequestMappingInfo} instances from type and method-level +@@ -49,7 +53,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi + * @since 3.1 + */ + public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping +- implements EmbeddedValueResolverAware { ++ implements EmbeddedValueResolverAware, MatchableHandlerMapping { + + private boolean useSuffixPatternMatch = true; + +@@ -261,4 +265,16 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi + } + } + ++ @Override ++ public RequestMatchResult match(HttpServletRequest request, String pattern) { ++ RequestMappingInfo info = RequestMappingInfo.paths(pattern).options(this.config).build(); ++ RequestMappingInfo matchingInfo = info.getMatchingCondition(request); ++ if (matchingInfo == null) { ++ return null; ++ } ++ Set patterns = matchingInfo.getPatternsCondition().getPatterns(); ++ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); ++ return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher()); ++ } ++ + } +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/HandlerMappingIntrospector.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/HandlerMappingIntrospector.java +new file mode 100644 +index 0000000..cc727c8 +--- /dev/null ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/HandlerMappingIntrospector.java +@@ -0,0 +1,192 @@ ++/* ++ * Copyright 2002-2016 the original author or authors. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++package org.springframework.web.servlet.support; ++ ++import java.io.IOException; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Properties; ++import javax.servlet.http.HttpServletRequest; ++import javax.servlet.http.HttpServletRequestWrapper; ++ ++import org.springframework.beans.factory.BeanFactoryUtils; ++import org.springframework.context.ApplicationContext; ++import org.springframework.core.annotation.AnnotationAwareOrderComparator; ++import org.springframework.core.io.ClassPathResource; ++import org.springframework.core.io.Resource; ++import org.springframework.core.io.support.PropertiesLoaderUtils; ++import org.springframework.util.ClassUtils; ++import org.springframework.util.StringUtils; ++import org.springframework.web.cors.CorsConfiguration; ++import org.springframework.web.cors.CorsConfigurationSource; ++import org.springframework.web.servlet.DispatcherServlet; ++import org.springframework.web.servlet.HandlerExecutionChain; ++import org.springframework.web.servlet.HandlerInterceptor; ++import org.springframework.web.servlet.HandlerMapping; ++ ++/** ++ * Helper class to get information from the {@code HandlerMapping} that would ++ * serve a specific request. ++ * ++ *

Provides the following methods: ++ *

++ * ++ * @author Rossen Stoyanchev ++ * @since 4.3 ++ */ ++public class HandlerMappingIntrospector implements CorsConfigurationSource { ++ ++ private final List handlerMappings; ++ ++ ++ /** ++ * Constructor that detects the configured {@code HandlerMapping}s in the ++ * given {@code ApplicationContext} or falling back on ++ * "DispatcherServlet.properties" like the {@code DispatcherServlet}. ++ */ ++ public HandlerMappingIntrospector(ApplicationContext context) { ++ this.handlerMappings = initHandlerMappings(context); ++ } ++ ++ ++ private static List initHandlerMappings(ApplicationContext context) { ++ ++ Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( ++ context, HandlerMapping.class, true, false); ++ ++ if (!beans.isEmpty()) { ++ List mappings = new ArrayList(beans.values()); ++ AnnotationAwareOrderComparator.sort(mappings); ++ return mappings; ++ } ++ ++ return initDefaultHandlerMappings(context); ++ } ++ ++ private static List initDefaultHandlerMappings(ApplicationContext context) { ++ Properties props; ++ String path = "DispatcherServlet.properties"; ++ try { ++ Resource resource = new ClassPathResource(path, DispatcherServlet.class); ++ props = PropertiesLoaderUtils.loadProperties(resource); ++ } ++ catch (IOException ex) { ++ throw new IllegalStateException("Could not load '" + path + "': " + ex.getMessage()); ++ } ++ ++ String value = props.getProperty(HandlerMapping.class.getName()); ++ String[] names = StringUtils.commaDelimitedListToStringArray(value); ++ List result = new ArrayList(names.length); ++ for (String name : names) { ++ try { ++ Class clazz = ClassUtils.forName(name, DispatcherServlet.class.getClassLoader()); ++ Object mapping = context.getAutowireCapableBeanFactory().createBean(clazz); ++ result.add((HandlerMapping) mapping); ++ } ++ catch (ClassNotFoundException ex) { ++ throw new IllegalStateException("Could not find default HandlerMapping [" + name + "]"); ++ } ++ } ++ return result; ++ } ++ ++ ++ /** ++ * Return the configured HandlerMapping's. ++ */ ++ public List getHandlerMappings() { ++ return this.handlerMappings; ++ } ++ ++ ++ /** ++ * Find the {@link HandlerMapping} that would handle the given request and ++ * return it as a {@link MatchableHandlerMapping} that can be used to ++ * test request-matching criteria. If the matching HandlerMapping is not an ++ * instance of {@link MatchableHandlerMapping}, an IllegalStateException is ++ * raised. ++ * ++ * @param request the current request ++ * @return the resolved matcher, or {@code null} ++ * @throws Exception if any of the HandlerMapping's raise an exception ++ */ ++ public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception { ++ HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); ++ for (HandlerMapping handlerMapping : this.handlerMappings) { ++ Object handler = handlerMapping.getHandler(wrapper); ++ if (handler == null) { ++ continue; ++ } ++ if (handlerMapping instanceof MatchableHandlerMapping) { ++ return ((MatchableHandlerMapping) handlerMapping); ++ } ++ throw new IllegalStateException("HandlerMapping is not a MatchableHandlerMapping"); ++ } ++ return null; ++ } ++ ++ @Override ++ public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { ++ HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request); ++ for (HandlerMapping handlerMapping : this.handlerMappings) { ++ HandlerExecutionChain handler = null; ++ try { ++ handler = handlerMapping.getHandler(wrapper); ++ } ++ catch (Exception ex) { ++ // Ignore ++ } ++ if (handler == null) { ++ continue; ++ } ++ if (handler.getInterceptors() != null) { ++ for (HandlerInterceptor interceptor : handler.getInterceptors()) { ++ if (interceptor instanceof CorsConfigurationSource) { ++ return ((CorsConfigurationSource) interceptor).getCorsConfiguration(wrapper); ++ } ++ } ++ } ++ if (handler.getHandler() instanceof CorsConfigurationSource) { ++ return ((CorsConfigurationSource) handler.getHandler()).getCorsConfiguration(wrapper); ++ } ++ } ++ return null; ++ } ++ ++ ++ /** ++ * Request wrapper that ignores request attribute changes. ++ */ ++ private static class RequestAttributeChangeIgnoringWrapper extends HttpServletRequestWrapper { ++ ++ ++ private RequestAttributeChangeIgnoringWrapper(HttpServletRequest request) { ++ super(request); ++ } ++ ++ @Override ++ public void setAttribute(String name, Object value) { ++ // Ignore attribute change ++ } ++ } ++ ++} +\ No newline at end of file +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/MatchableHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/MatchableHandlerMapping.java +new file mode 100644 +index 0000000..1c82586 +--- /dev/null ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/MatchableHandlerMapping.java +@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2002-2016 the original author or authors. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++package org.springframework.web.servlet.support; ++ ++import javax.servlet.http.HttpServletRequest; ++ ++import org.springframework.web.servlet.HandlerMapping; ++ ++/** ++ * Additional interface that a {@link HandlerMapping} can implement to expose ++ * a request matching API aligned with its internal request matching ++ * configuration and implementation. ++ * ++ * @author Rossen Stoyanchev ++ * @since 4.3 ++ * @see HandlerMappingIntrospector ++ */ ++public interface MatchableHandlerMapping { ++ ++ /** ++ * Whether the given request matches the request criteria. ++ * @param request the current request ++ * @param pattern the pattern to match ++ * @return the result from request matching or {@code null} ++ */ ++ RequestMatchResult match(HttpServletRequest request, String pattern); ++ ++} +diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestMatchResult.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestMatchResult.java +new file mode 100644 +index 0000000..b196d92 +--- /dev/null ++++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestMatchResult.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2002-2016 the original author or authors. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++package org.springframework.web.servlet.support; ++ ++import java.util.Collections; ++import java.util.Map; ++ ++import org.springframework.util.Assert; ++import org.springframework.util.PathMatcher; ++ ++/** ++ * Container for the result from request pattern matching via ++ * {@link MatchableHandlerMapping} with a method to further extract URI template ++ * variables from the pattern. ++ * ++ * @author Rossen Stoyanchev ++ * @since 4.3 ++ */ ++public class RequestMatchResult { ++ ++ private final String matchingPattern; ++ ++ private final String lookupPath; ++ ++ private final PathMatcher pathMatcher; ++ ++ ++ /** ++ * Create an instance with a matching pattern. ++ * @param matchingPattern the matching pattern, possibly not the same as the ++ * input pattern, e.g. inputPattern="/foo" and matchingPattern="/foo/". ++ * @param lookupPath the lookup path extracted from the request ++ * @param pathMatcher the PathMatcher used ++ */ ++ public RequestMatchResult(String matchingPattern, String lookupPath, PathMatcher pathMatcher) { ++ Assert.hasText(matchingPattern, "'matchingPattern' is required"); ++ Assert.hasText(lookupPath, "'lookupPath' is required"); ++ Assert.notNull(pathMatcher, "'pathMatcher' is required"); ++ this.matchingPattern = matchingPattern; ++ this.lookupPath = lookupPath; ++ this.pathMatcher = pathMatcher; ++ } ++ ++ ++ /** ++ * Whether the pattern was matched to the request. ++ */ ++ public boolean isMatch() { ++ return (this.matchingPattern != null); ++ } ++ ++ /** ++ * Extract URI template variables from the matching pattern as defined in ++ * {@link PathMatcher#extractUriTemplateVariables}. ++ * @return a map with URI template variables ++ */ ++ public Map extractUriTemplateVariables() { ++ if (!isMatch()) { ++ return Collections.emptyMap(); ++ } ++ return this.pathMatcher.extractUriTemplateVariables(this.matchingPattern, this.lookupPath); ++ } ++ ++} +diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/support/HandlerMappingIntrospectorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/support/HandlerMappingIntrospectorTests.java +new file mode 100644 +index 0000000..b7e1c76 +--- /dev/null ++++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/support/HandlerMappingIntrospectorTests.java +@@ -0,0 +1,190 @@ ++/* ++ * Copyright 2002-2016 the original author or authors. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++package org.springframework.web.servlet.support; ++ ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++import javax.servlet.http.HttpServletRequest; ++ ++import org.junit.Test; ++ ++import org.springframework.beans.MutablePropertyValues; ++import org.springframework.context.annotation.Bean; ++import org.springframework.context.annotation.Configuration; ++import org.springframework.http.HttpHeaders; ++import org.springframework.mock.web.test.MockHttpServletRequest; ++import org.springframework.stereotype.Controller; ++import org.springframework.web.bind.annotation.CrossOrigin; ++import org.springframework.web.bind.annotation.PostMapping; ++import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; ++import org.springframework.web.context.support.StaticWebApplicationContext; ++import org.springframework.web.cors.CorsConfiguration; ++import org.springframework.web.servlet.HandlerExecutionChain; ++import org.springframework.web.servlet.HandlerMapping; ++import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; ++import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; ++import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; ++import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; ++ ++import static org.junit.Assert.assertEquals; ++import static org.junit.Assert.assertNotNull; ++import static org.junit.Assert.assertNull; ++import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE; ++ ++/** ++ * Unit tests for {@link HandlerMappingIntrospector}. ++ * @author Rossen Stoyanchev ++ */ ++public class HandlerMappingIntrospectorTests { ++ ++ @Test ++ public void detectHandlerMappings() throws Exception { ++ StaticWebApplicationContext cxt = new StaticWebApplicationContext(); ++ cxt.registerSingleton("hmA", SimpleUrlHandlerMapping.class); ++ cxt.registerSingleton("hmB", SimpleUrlHandlerMapping.class); ++ cxt.registerSingleton("hmC", SimpleUrlHandlerMapping.class); ++ cxt.refresh(); ++ ++ List expected = Arrays.asList(cxt.getBean("hmA"), cxt.getBean("hmB"), cxt.getBean("hmC")); ++ List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); ++ ++ assertEquals(expected, actual); ++ } ++ ++ @Test ++ public void detectHandlerMappingsOrdered() throws Exception { ++ StaticWebApplicationContext cxt = new StaticWebApplicationContext(); ++ MutablePropertyValues pvs = new MutablePropertyValues(Collections.singletonMap("order", "3")); ++ cxt.registerSingleton("hmA", SimpleUrlHandlerMapping.class, pvs); ++ pvs = new MutablePropertyValues(Collections.singletonMap("order", "2")); ++ cxt.registerSingleton("hmB", SimpleUrlHandlerMapping.class, pvs); ++ pvs = new MutablePropertyValues(Collections.singletonMap("order", "1")); ++ cxt.registerSingleton("hmC", SimpleUrlHandlerMapping.class, pvs); ++ cxt.refresh(); ++ ++ List expected = Arrays.asList(cxt.getBean("hmC"), cxt.getBean("hmB"), cxt.getBean("hmA")); ++ List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); ++ ++ assertEquals(expected, actual); ++ } ++ ++ @Test @SuppressWarnings("deprecation") ++ public void defaultHandlerMappings() throws Exception { ++ StaticWebApplicationContext cxt = new StaticWebApplicationContext(); ++ cxt.refresh(); ++ ++ List actual = new HandlerMappingIntrospector(cxt).getHandlerMappings(); ++ assertEquals(2, actual.size()); ++ assertEquals(BeanNameUrlHandlerMapping.class, actual.get(0).getClass()); ++ assertEquals(DefaultAnnotationHandlerMapping.class, actual.get(1).getClass()); ++ } ++ ++ @Test ++ public void getMatchable() throws Exception { ++ ++ MutablePropertyValues pvs = new MutablePropertyValues( ++ Collections.singletonMap("urlMap", ++ Collections.singletonMap("/path", new Object()))); ++ ++ StaticWebApplicationContext cxt = new StaticWebApplicationContext(); ++ cxt.registerSingleton("hm", SimpleUrlHandlerMapping.class, pvs); ++ cxt.refresh(); ++ ++ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/path"); ++ MatchableHandlerMapping hm = new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); ++ ++ assertEquals(cxt.getBean("hm"), hm); ++ assertNull("Attributes changes not ignored", request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)); ++ } ++ ++ @Test(expected = IllegalStateException.class) ++ public void getMatchableWhereHandlerMappingDoesNotImplementMatchableInterface() throws Exception { ++ StaticWebApplicationContext cxt = new StaticWebApplicationContext(); ++ cxt.registerSingleton("hm1", TestHandlerMapping.class); ++ cxt.refresh(); ++ ++ MockHttpServletRequest request = new MockHttpServletRequest(); ++ new HandlerMappingIntrospector(cxt).getMatchableHandlerMapping(request); ++ } ++ ++ @Test ++ public void getCorsConfigurationPreFlight() throws Exception { ++ AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); ++ cxt.register(TestConfig.class); ++ cxt.refresh(); ++ ++ // PRE-FLIGHT ++ ++ MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/path"); ++ request.addHeader("Origin", "http://localhost:9000"); ++ request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST"); ++ CorsConfiguration corsConfig = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); ++ ++ assertNotNull(corsConfig); ++ assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); ++ assertEquals(Collections.singletonList("POST"), corsConfig.getAllowedMethods()); ++ } ++ ++ @Test ++ public void getCorsConfigurationActual() throws Exception { ++ AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); ++ cxt.register(TestConfig.class); ++ cxt.refresh(); ++ ++ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/path"); ++ request.addHeader("Origin", "http://localhost:9000"); ++ CorsConfiguration corsConfig = new HandlerMappingIntrospector(cxt).getCorsConfiguration(request); ++ ++ assertNotNull(corsConfig); ++ assertEquals(Collections.singletonList("http://localhost:9000"), corsConfig.getAllowedOrigins()); ++ assertEquals(Collections.singletonList("POST"), corsConfig.getAllowedMethods()); ++ } ++ ++ ++ private static class TestHandlerMapping implements HandlerMapping { ++ ++ @Override ++ public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { ++ return new HandlerExecutionChain(new Object()); ++ } ++ } ++ ++ @Configuration @SuppressWarnings({"WeakerAccess", "unused"}) ++ static class TestConfig { ++ ++ @Bean ++ public RequestMappingHandlerMapping handlerMapping() { ++ return new RequestMappingHandlerMapping(); ++ } ++ ++ @Bean ++ public TestController testController() { ++ return new TestController(); ++ } ++ ++ } ++ ++ @CrossOrigin("http://localhost:9000") ++ @Controller ++ private static class TestController { ++ ++ @PostMapping("/path") ++ public void handle() { ++ } ++ } ++ ++} +-- +2.23.0 + diff --git a/springframework.spec b/springframework.spec index b09578c25e44bc4dca5ddd112a25ac1af60f9139..110af6561881067b0b3742bacaeab03015a3690c 100644 --- a/springframework.spec +++ b/springframework.spec @@ -1,6 +1,6 @@ Name: springframework Version: 3.2.18 -Release: 7 +Release: 8 Summary: The Spring Java Application Framework License: ASL 2.0 URL: http://projects.spring.io/spring-framework/ @@ -33,6 +33,7 @@ Patch7: springframework-3.2.14-jopt-simple.patch Patch8: springframework-3.2.14-build-with-tomcat8.patch Patch9: springframework-3.2.18-hibernate4.3.patch Patch10: CVE-2020-5421.patch +patch11: CVE-2016-5007.patch BuildRequires: maven-local mvn(aopalliance:aopalliance) mvn(c3p0:c3p0) mvn(com.caucho:hessian) BuildRequires: mvn(com.fasterxml.jackson.core:jackson-databind) mvn(com.h2database:h2) BuildRequires: mvn(com.jamonapi:jamon) mvn(com.rometools:rome) @@ -364,6 +365,9 @@ done %files web -f .mfiles-spring-web %changelog +* Fri Oct 29 2021 houyingchao - 3.2.18-8 +- Fix CVE-2016-5007 + * Thu Dec 17 2020 caodongxia - 3.2.18-7 - Fix CVE-2020-5421