Prior to this commit, the List branch in
AbstractNestablePropertyAccessor's getPropertyValue() method called
list.get(index) unconditionally after invoking
growCollectionIfNecessary(), which implicitly relied on the list
throwing an IndexOutOfBoundsException for out-of-range access. Such an
exception is caught downstream and wrapped as an
InvalidPropertyException; however, any List implementation whose get()
method allocates elements on demand rather than throwing an
IndexOutOfBoundsException could bypass that check.
This behavior was also inconsistent with the Collection/Iterable branch
in the same method, which already performs an explicit `index >=
collection.size()` bounds check before attempting element access.
To address that, this commit aligns the List branch with the
Collection/Iterable branch by adding an explicit `index < 0 || index >=
list.size()` check immediately after the auto-grow attempt. If the
index remains out of bounds after growCollectionIfNecessary() runs –
for example, because growth was capped by autoGrowCollectionLimit or
auto-growing was disabled – an InvalidPropertyException is now thrown
rather than delegating to list.get() which may or may not throw an
exception.
Closes gh-37036
Prior to this commit, many classes would support writing Server Sent
Events in some way to the response output stream. This has lead to some
code duplication.
This commit refactors the duplicated code in a shared `SseUtils` class.
Closes gh-37065
Prior to this commit, building a "Content-Disposition" header to a
String and then parsing it back would not always result in the original
header.
This commit ensures that ContentDisposition guarantees this and honors
the "equals" contract.
Fixes gh-37064
Prior to this commit, the MVC and WebFlux view fragments rendering would
only partially escape rendered view fragments before sending then as SSE
events. This could in some cases break the SSE stream with invalid data.
This commit ensures that the rendered views are properly escaped before
they are sent as SSE events.
Fixes gh-37061
A user reported confusion between two distinct uses of "wraps" in the
AOP proxy documentation for Bean Overrides: the sense in which a
Mockito spy wraps the original bean instance it was created from, and
the sense in which a Spring AOP proxy wraps the spy in the actual
object graph.
To address that, this commit adds two small diagrams to the general
"Bean Overrides and Spring AOP Proxies" section, illustrating, from a
caller's perspective, the shape of the bean for the
REPLACE/REPLACE_OR_CREATE strategy (no proxy at all) versus the WRAP
strategy (an AOP proxy still created, now wrapping the override
instance instead of the original bean). Both diagrams use the same
generic "override instance" label, since the section is not specific to
Mockito; a Mockito spy created by @MockitoSpyBean is mentioned only as
an example.
The accompanying text is revised to reserve "wraps" for the AOP proxy
relationship and to explicitly call out that a Mockito spy's
relationship to its original bean instance is a separate concern from
AOP proxy nesting.
The @MockitoSpyBean-specific strategy paragraph in the
@MockitoBean/@MockitoSpyBean documentation has also been revised
similarly, and now points to the new diagram.
See gh-37121
This commit documents how the Bean Override support in the TestContext
framework interacts with Spring AOP proxies created for annotations
such as @Transactional, @Cacheable, and @Retryable.
The new "Bean Overrides and Spring AOP Proxies" section in the general
Bean Overriding documentation explains that overrides using the WRAP
strategy (such as @MockitoSpyBean) end up as the target of any AOP
proxy subsequently created for the original bean; whereas, overrides
using the REPLACE or REPLACE_OR_CREATE strategy (such as @TestBean,
@MockitoBean) bypass the container's bean post-processing entirely and
therefore carry no AOP advice at all.
The new "@MockitoSpyBean and Spring AOP Proxies" section documents the
resulting stubbing and verification semantics. Verification via
Mockito's verify() API works transparently regardless of whether it is
invoked on the proxy or on the spy. Stubbing via doReturn(...)/doThrow(...)
is safe for stateless advice such as @Retryable, but can silently
corrupt the spy's configured answers for stateful or memoizing advice
such as @Cacheable, since the invocation used to declare a stub is
intercepted by Mockito before it reaches the spy and returns an empty
value that such advice may then cache.
AopTestUtils.getUltimateTargetObject(...) is documented as the way to
stub directly against the spy in that case.
The same section also documents how to disable the AOP advice for a
test altogether while leaving it in place in production code – for
example, binding a @Retryable attribute to a property placeholder
overridden via @TestPropertySource, or replacing the CacheManager with
a NoOpCacheManager via @TestBean.
Brief cross-referencing notes have also been added to the @TestBean
documentation and to the existing AopTestUtils description in the
"General Testing Utilities" section, to avoid duplicating the
explanation across pages.
In addition, the Javadoc for @MockitoSpyBean now contains a concise
WARNING summarizing these AOP proxy implications and linking to the new
reference documentation section for details.
Closes gh-37121
DataBufferUtils.TwoByteMatcher inherited AbstractNestedMatcher.match(byte)
without providing the mismatch fallback that its siblings implement
(KnuthMorrisPrattMatcher backtracks via its suffix-prefix table, and
SingleByteMatcher is stateless). As a result, once the first delimiter
byte had matched, the match counter stayed at 1 across any number of
intervening non-matching bytes, so a later occurrence of the second
delimiter byte falsely completed the match.
For a two-byte delimiter such as \r\n this made the matcher report a
match across non-contiguous bytes. CompositeMatcher prefers the longest
delimiter that matches at a position, so the false \r\n match was chosen
over a real single \n, causing StringDecoder to strip two bytes and drop
the character preceding a lone \n whenever a line contained a stray \r.
TwoByteMatcher now overrides match(byte) to reset the counter to 0 when
the incoming byte is not the expected next delimiter byte before
delegating to super.match(), mirroring KnuthMorrisPrattMatcher. A
genuine contiguous delimiter is unaffected.
Signed-off-by: junhyeong9812 <pickjog@gmail.com>
ClassFileAnnotationDelegate passed the raw java.lang.classfile
Annotation to MergedAnnotation.of() as the annotation source. That
annotation holds a Utf8Entry, so retaining the metadata of an
annotated class also retained its class file byte[], the parsed
constant pool, and the class model.
Store the declaring class name instead, as the ASM variant does.
See gh-37111
Signed-off-by: Boris Perović <boris.perovic@sysdig.com>
This commit ensures that workflow dispatches to docs build only happen
on OSS branches.
This also upgrades the verification project to the latest version.
See gh-37097
Property accessors resolved via SpEL's ReflectivePropertyAccessor and
DataBindingPropertyAccessor may be JavaBean-style accessors or plain
accessor methods used to support data classes such as Java records and
Kotlin data classes. However, neither accessor can determine, via
reflection, whether such a method is a side-effect-free read or an
action that happens to return a value. For example, File.delete() is a
public method that returns a boolean and therefore looks like a
plain "property".
To better inform users, this commit updates the Javadoc for
ReflectivePropertyAccessor, DataBindingPropertyAccessor, and
SimpleEvaluationContext (as well as in the SpEL reference
documentation) to clarify that restricting a SimpleEvaluationContext to
read-only data binding governs only whether assignment to a property is
permitted and does not guarantee that reading a property is free of
side effects. The reference documentation's "Security Considerations"
section now also defines what makes a method "accessor-shaped", with
concrete examples of safe versus side-effecting methods that share that
shape (for example, File.delete(), Queue.poll(), and
AtomicInteger.incrementAndGet()).
Building on that clarification, this commit introduces a new "Object
Design" section to the SpEL reference documentation, analogous to the
"Model Design" guidance for web data binding. This new section
recommends that any object reachable from an untrusted SpEL expression
(not only the root object) be a purpose-built, immutable type with a
deliberately limited surface area, and that its accessor-shaped methods
be audited for unsafe side effects. The new section also notes that
reachability is transitive through both property navigation and
indexing (for example, rootObject.child.grandchild or
rootObject.items[0]).
In any case, it remains the responsibility of the code that exposes a
root object or other reachable object to an expression from an
untrusted source to ensure that none of its accessor-shaped methods
perform an unsafe action.
Closes gh-37102
The Javadoc for EvaluationContext, StandardEvaluationContext, and
SimpleEvaluationContext previously repeated the same detailed
explanation of trusted sources and best-effort restrictions in four
places, making it hard to maintain and to digest.
This commit condenses each class-level warning to a succinct summary
that links to the new "Security Considerations" section of the SpEL
reference documentation, which remains the single, detailed source of
truth introduced in 9b42a40a2a.
See gh-36997
This commit adds a "Lifecycle and Reuse" section to the SpEL reference
documentation, immediately following the security considerations
introduced for gh-36997, explaining that AST nodes within a parsed
Expression may cache resolved PropertyAccessor, IndexAccessor,
MethodExecutor, and ConstructorExecutor instances for performance.
We also now document that reusing a parsed Expression across
EvaluationContext instances of the same type and with equivalent
configuration is supported (even if atypical), including when accessors
or resolvers registered with a context change between evaluations, but
that reusing a parsed Expression across contexts with different
security implications (for example, first against a
StandardEvaluationContext and later against a SimpleEvaluationContext)
is not supported, since cached state from a more permissive evaluation
may be reused during a more restrictive one.
The Javadoc for Expression, SpelExpression, EvaluationContext,
StandardEvaluationContext, SimpleEvaluationContext, PropertyAccessor,
IndexAccessor, MethodExecutor, and ConstructorExecutor has also been
updated to make these contracts discoverable via the API as well.
Closes gh-36968
This commit clarifies in the Javadoc for EvaluationContext,
StandardEvaluationContext, and SimpleEvaluationContext (as well as in
the SpEL reference documentation) that StandardEvaluationContext must
never be used to evaluate expressions from an untrusted source, and
that SimpleEvaluationContext's restricted language and feature subset
is only a best-effort measure. The updated documentation also defines a
"trusted" source as a developer or administrator of the application and
points out that it is the responsibility of the code that configures an
EvaluationContext to ensure that no object reachable via the context
exposes dangerous operations.
Closes gh-36997
This commit introduces a constructor argument to select whether
to use the standard "Forwarded" header or the "X-Forwarded-*"
alternative headers. A separate property to control support for
X-Forwarded-Prefix.
Closes gh-37090
Prior to this commit, the SpEL Indexer's PropertyAccessorValueRef could
reuse a cached PropertyAccessor for reads and writes even after that
accessor had been removed from the current EvaluationContext, leading
to stale property access if the EvaluationContext changes between
evaluations of the same expression.
This commit aligns PropertyAccessorValueRef with the analogous logic
in PropertyOrFieldReference and Indexer's IndexAccessorValueRef by
verifying that the cached PropertyAccessor is still registered in the
current EvaluationContext before reusing it in getValue() and
setValue().
Closes gh-36986
Prior to this commit, a SpEL ConstructorReference could reuse a cached
ConstructorExecutor even when the current EvaluationContext no longer
had any registered ConstructorResolvers, leading to inconsistent
behavior if the EvaluationContext changes between evaluations of the
same expression.
This commit aligns ConstructorReference with the analogous logic in
PropertyOrFieldReference by discarding the cached ConstructorExecutor
whenever there are no ConstructorResolvers registered in the current
EvaluationContext, ensuring that constructor resolution consistently
fails with a CONSTRUCTOR_NOT_FOUND exception in that scenario.
Closes gh-36985
Following gh-26004, the registration order of active profiles in
@ActiveProfiles is preserved; however, the Javadoc in
MergedContextConfiguration and WebMergedContextConfiguration still
described the old sorting behavior, which is misleading since profile
order is part of the context cache key (equals/hashCode).
This commit updates the Javadoc to document the status quo.
Closes gh-36950
Signed-off-by: Alexis SEGURA <alex.segura06@gmail.com>
Prior to this commit, `ClassFileAnnotationDelegate#parseArrayValue`
would only consider `int[]`, `double[]` and `long[]` array
annotation attributes; other primitive array types like `byte[]`
would use a generic path that would use boxed types.
This commit ensures that a comprehensive pass is made for all
primitive typed arrays. Because the `AnnotationValue` hierarchy
is sealed, we can now maje sure that the implementation is
exhaustive.
Closes gh-37083
Previously, the @return tag in MessageSizeReader.readMessageSize() was
followed by a redundant "return", which rendered as "Returns: return
the message size..." in the published API documentation.
Closes gh-37079
Signed-off-by: BAE JAE HYEON <roblery128@gmail.com>
Prior to this commit, gh-36328 avoided using RFC 2047 encoding for the
"filename" parameter and use ISO-8859-1 only. This change unfortunately
caused issues because some implementations might try and detect the
encoding automatically.
This commit restricts the filename parameter to ASCII encoding only by:
* transliterating characters to the closes ASCII character
("é"->"e", "ä"->"ae"...)
* falling back to "_" for other chacacters with non latin alphabet or
emojis
Closes gh-37062
Both encoders acquire a pooled BufferRecycler via
factory._getBufferRecycler() but never return it. Jackson 3 changed the
default pool from a ThreadLocal to a per-factory ConcurrentDequePool that
only refills on an explicit releaseToPool(), so the gap leaves the pool
empty and every encode allocates a fresh recycler and buffers.
Hold the recycler in a local and release it once the generator and byte
builder are done: in encodeValue's finally, and in the streaming path's
doAfterTerminate after generator.close() and byteBuilder.release().
releaseToPool() is idempotent, so sharing the recycler with the generator
cannot double-release.
Closes gh-37059
Signed-off-by: samlightfoot <samueldlightfoot@gmail.com>
The taskTerminationTimeoutWithImmediateCancel test submitted a task and
immediately closed the executor, then asserted that the future was
cancelled. The cancellation flag is set by close() on the calling thread,
while it is checked at the start of the task on a separate worker thread.
With no ordering guarantee between the two, a quickly scheduled worker
could pass the cancellation check before close() set the flag, complete
the trivial task normally, and leave the future uncancelled, making the
test fail intermittently under load.
Override doExecute to capture the task-tracking wrapper instead of
running it on a background thread, then run it on the test thread after
close() has set the cancellation flag. This exercises the same
cancellation path deterministically, with no reliance on thread
scheduling.
Signed-off-by: junhyeong9812 <pickjog@gmail.com>