Defensively copy array returned from forAnnotations

Update the proxy used in `AnnotatedElementUtils.forAnnotations` so
that it returns a cloned array for calls to `getDeclaredAnnotations`
or `getAnnotations`. This matches the behavior of standard JDK
`AnnotatedElement` implementations.

Closes gh-22655
This commit is contained in:
Phillip Webb 2019-03-25 07:51:01 -07:00
parent 78fd882141
commit cb7f997962
2 changed files with 18 additions and 4 deletions

View File

@ -864,12 +864,12 @@ public abstract class AnnotatedElementUtils {
@Override
public Annotation[] getAnnotations() {
return this.annotations;
return this.annotations.clone();
}
@Override
public Annotation[] getDeclaredAnnotations() {
return this.annotations;
return this.annotations.clone();
}
};

View File

@ -23,9 +23,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
@ -43,6 +41,7 @@ import org.springframework.util.MultiValueMap;
import static java.util.Arrays.*;
import static java.util.stream.Collectors.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.core.annotation.AnnotatedElementUtils.*;
@ -736,6 +735,15 @@ public class AnnotatedElementUtilsTests {
assertNotNull(order);
}
@Test // gh-22655
public void forAnnotationsCreatesCopyOfArrayOnEachCall() {
AnnotatedElement element = AnnotatedElementUtils.forAnnotations(ForAnnotationsClass.class.getDeclaredAnnotations());
// Trigger the NPE as originally reported in the bug
AnnotationsScanner.getDeclaredAnnotations(element, false);
AnnotationsScanner.getDeclaredAnnotations(element, false);
// Also specifically test we get different instances
assertThat(element.getDeclaredAnnotations()).isNotSameAs(element.getDeclaredAnnotations());
}
// -------------------------------------------------------------------------
@ -1301,4 +1309,10 @@ public class AnnotatedElementUtilsTests {
}
}
@Deprecated
@ComponentScan
class ForAnnotationsClass {
}
}