From 8f130316d20cea32631f55a0ac4c69ffb4bd7d16 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 15 Sep 2023 13:46:04 +0200 Subject: [PATCH 1/2] MultipartParser should respect read position This commit ensures that the MultipartParser takes a buffer's read position into account. Closes gh-31110 --- .../http/codec/multipart/MultipartParser.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartParser.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartParser.java index 0def952d78e..1b59f6ddf1e 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartParser.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartParser.java @@ -523,7 +523,7 @@ final class MultipartParser extends BaseSubscriber { if (logger.isTraceEnabled()) { logger.trace("Boundary found @" + endIdx + " in " + buffer); } - int len = endIdx - this.boundaryLength + 1; + int len = endIdx - this.boundaryLength + 1 - boundaryBuffer.readPosition(); if (len > 0) { // whole boundary in buffer. // slice off the body part, and flush @@ -538,10 +538,11 @@ final class MultipartParser extends BaseSubscriber { DataBufferUtils.release(boundaryBuffer); DataBuffer prev; while ((prev = this.queue.pollLast()) != null) { - int prevLen = prev.readableByteCount() + len; + int prevByteCount = prev.readableByteCount(); + int prevLen = prevByteCount + len; if (prevLen > 0) { // slice body part of previous buffer, and flush it - DataBuffer body = prev.split(prevLen); + DataBuffer body = prev.split(prevLen + prev.readPosition()); DataBufferUtils.release(prev); enqueue(body); flush(); @@ -550,7 +551,7 @@ final class MultipartParser extends BaseSubscriber { else { // previous buffer only contains boundary bytes DataBufferUtils.release(prev); - len += prev.readableByteCount(); + len += prevByteCount; } } } From 227049824c7905048bda3d97c0a6fadd3d2fa73d Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 15 Sep 2023 17:50:53 +0200 Subject: [PATCH 2/2] Fix RuntimeHintsPredicates matching rules Prior to this commit, the `RuntimeHintsPredicates` would assume that registering introspection or invocation hints for "all declared methods" on a type would also include "all public methods". This is not true, as the Java reflection API itself behaves differently. `getDeclaredMethods()` does not return a superset of `getMethods()`, as the latter can return inherited methods, but not the former. Same reasoning applies to fields. This commit fixes the hints predicates to only match if the correct hint has been registered. Fixes gh-31224 --- .../aot/agent/InstrumentedMethodTests.java | 12 +++--- .../predicate/ReflectionHintsPredicates.java | 38 ++++++++++--------- .../ReflectionHintsPredicatesTests.java | 18 ++++----- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java b/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java index a9e4ab8520c..9a2edab4a46 100644 --- a/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java +++ b/spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java @@ -408,15 +408,15 @@ class InstrumentedMethodTests { } @Test - void classGetMethodShouldMatchIntrospectDeclaredMethodsHint() { + void classGetMethodShouldNotMatchIntrospectDeclaredMethodsHint() { hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS); - assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); + assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); } @Test - void classGetMethodShouldMatchInvokeDeclaredMethodsHint() { + void classGetMethodShouldNotMatchInvokeDeclaredMethodsHint() { hints.reflection().registerType(String.class, MemberCategory.INVOKE_DECLARED_METHODS); - assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); + assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod); } @Test @@ -544,9 +544,9 @@ class InstrumentedMethodTests { } @Test - void classGetFieldShouldMatchDeclaredFieldsHint() { + void classGetFieldShouldNotMatchDeclaredFieldsHint() { hints.reflection().registerType(PublicField.class, MemberCategory.DECLARED_FIELDS); - assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELD, this.getPublicField); + assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELD, this.getPublicField); } @Test diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java index 31c66348f8e..01d25229a0b 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -274,19 +274,6 @@ public class ReflectionHintsPredicates { return this; } - @Override - public boolean test(RuntimeHints runtimeHints) { - return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) - .withAnyMemberCategory(getPublicMemberCategories()) - .and(hints -> Modifier.isPublic(this.executable.getModifiers()))) - .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())).withAnyMemberCategory(getDeclaredMemberCategories())) - .or(exactMatch()).test(runtimeHints); - } - - abstract MemberCategory[] getPublicMemberCategories(); - - abstract MemberCategory[] getDeclaredMemberCategories(); - abstract Predicate exactMatch(); /** @@ -309,6 +296,14 @@ public class ReflectionHintsPredicates { } @Override + public boolean test(RuntimeHints runtimeHints) { + return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withAnyMemberCategory(getPublicMemberCategories()) + .and(hints -> Modifier.isPublic(this.executable.getModifiers()))) + .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())).withAnyMemberCategory(getDeclaredMemberCategories())) + .or(exactMatch()).test(runtimeHints); + } + MemberCategory[] getPublicMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, @@ -317,7 +312,6 @@ public class ReflectionHintsPredicates { return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS }; } - @Override MemberCategory[] getDeclaredMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { return new MemberCategory[] { MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, @@ -344,6 +338,16 @@ public class ReflectionHintsPredicates { } @Override + public boolean test(RuntimeHints runtimeHints) { + return (new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withAnyMemberCategory(getPublicMemberCategories()) + .and(hints -> Modifier.isPublic(this.executable.getModifiers()))) + .or(new TypeHintPredicate(TypeReference.of(this.executable.getDeclaringClass())) + .withAnyMemberCategory(getDeclaredMemberCategories()) + .and(hints -> !Modifier.isPublic(this.executable.getModifiers()))) + .or(exactMatch()).test(runtimeHints); + } + MemberCategory[] getPublicMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { return new MemberCategory[] { MemberCategory.INTROSPECT_PUBLIC_METHODS, @@ -352,7 +356,6 @@ public class ReflectionHintsPredicates { return new MemberCategory[] { MemberCategory.INVOKE_PUBLIC_METHODS }; } - @Override MemberCategory[] getDeclaredMemberCategories() { if (this.executableMode == ExecutableMode.INTROSPECT) { @@ -392,8 +395,7 @@ public class ReflectionHintsPredicates { private boolean memberCategoryMatch(TypeHint typeHint) { if (Modifier.isPublic(this.field.getModifiers())) { - return typeHint.getMemberCategories().contains(MemberCategory.PUBLIC_FIELDS) || - typeHint.getMemberCategories().contains(MemberCategory.DECLARED_FIELDS); + return typeHint.getMemberCategories().contains(MemberCategory.PUBLIC_FIELDS); } else { return typeHint.getMemberCategories().contains(MemberCategory.DECLARED_FIELDS); diff --git a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java index 3ac2a51670a..896da82a60d 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -329,15 +329,15 @@ class ReflectionHintsPredicatesTests { } @Test - void methodIntrospectionMatchesIntrospectDeclaredMethods() { + void methodIntrospectionDoesNotMatchIntrospectDeclaredMethods() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_METHODS); - assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); + assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); } @Test - void methodIntrospectionMatchesInvokeDeclaredMethods() { + void methodIntrospectionDoesNotMatchInvokeDeclaredMethods() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_METHODS); - assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); + assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").introspect()); } @Test @@ -373,9 +373,9 @@ class ReflectionHintsPredicatesTests { } @Test - void methodInvocationMatchesInvokeDeclaredMethods() { + void methodInvocationDoesNotMatchInvokeDeclaredMethods() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_METHODS); - assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").invoke()); + assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").invoke()); } @Test @@ -482,9 +482,9 @@ class ReflectionHintsPredicatesTests { } @Test - void fieldReflectionMatchesDeclaredFieldsHint() { + void fieldReflectionDoesNotMatchDeclaredFieldsHint() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.DECLARED_FIELDS); - assertPredicateMatches(reflection.onField(SampleClass.class, "publicField")); + assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField")); } @Test