fix(java/restclient): avoid IndexOutOfBoundsException for empty multi…#23314
Conversation
There was a problem hiding this comment.
5 issues found across 13 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="samples/client/petstore/java/restclient-useSingleRequestParameter-static/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient-useSingleRequestParameter-static/src/main/java/org/openapitools/client/ApiClient.java:805">
P2: Multipart enum-list conversion mutates arbitrary `List<?>` values in place, which can throw `UnsupportedOperationException` for immutable/fixed-size lists supplied in `formParams`.</violation>
</file>
<file name="samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java:732">
P2: Multipart enum normalization now mutates any `List<?>`, which can throw `UnsupportedOperationException` for immutable/fixed-size list implementations.</violation>
</file>
<file name="samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java:805">
P2: Multipart enum-list normalization mutates generic `List<?>` in place and can throw `UnsupportedOperationException` on immutable/unmodifiable lists.</violation>
</file>
<file name="samples/client/others/java/restclient-enum-in-multipart/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/others/java/restclient-enum-in-multipart/src/main/java/org/openapitools/client/ApiClient.java:733">
P2: Multipart enum normalization mutates arbitrary `List` values in place; immutable lists can trigger `UnsupportedOperationException` at runtime.</violation>
</file>
<file name="samples/client/others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java:732">
P2: Multipart enum normalization mutates caller-provided lists in place, which can fail on non-mutable lists and causes side effects on input data.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
...client-useSingleRequestParameter-static/src/main/java/org/openapitools/client/ApiClient.java
Outdated
Show resolved
Hide resolved
...etstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java
Outdated
Show resolved
Hide resolved
...lient/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java
Outdated
Show resolved
Hide resolved
...thers/java/restclient-enum-in-multipart/src/main/java/org/openapitools/client/ApiClient.java
Outdated
Show resolved
Hide resolved
.../others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
5 issues found across 13 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="samples/client/petstore/java/restclient-springBoot4-jackson2/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient-springBoot4-jackson2/src/main/java/org/openapitools/client/ApiClient.java:750">
P2: Multipart form parameter order can become unstable because `HashMap` is used as the intermediate normalization container before repopulating `formParams`.</violation>
</file>
<file name="modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache:865">
P1: `formParams.putAll(normalizedParams)` passes `Map<String, Object>` where `MultiValueMap<String, Object>` requires map values of `List<Object>`, causing a compile-time generic type mismatch.</violation>
</file>
<file name="samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java:797">
P2: Multipart form field order can become unstable because params are rebuilt through an unordered `HashMap` before re-inserting into `formParams`.</violation>
</file>
<file name="samples/client/petstore/java/restclient-springBoot4-jackson3/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/restclient-springBoot4-jackson3/src/main/java/org/openapitools/client/ApiClient.java:759">
P2: Multipart normalization now requires mutating `formParams` (`clear`/`putAll`), which can fail for immutable `MultiValueMap` inputs passed to public `invokeAPI`.</violation>
</file>
<file name="samples/client/others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java:724">
P2: Multipart form parameter normalization now uses `HashMap`, which can reorder parts and change request part order nondeterministically.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| normalizedParams.put(k, normalizedValue); | ||
| }); | ||
| formParams.clear(); | ||
| formParams.putAll(normalizedParams); |
There was a problem hiding this comment.
P1: formParams.putAll(normalizedParams) passes Map<String, Object> where MultiValueMap<String, Object> requires map values of List<Object>, causing a compile-time generic type mismatch.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache, line 865:
<comment>`formParams.putAll(normalizedParams)` passes `Map<String, Object>` where `MultiValueMap<String, Object>` requires map values of `List<Object>`, causing a compile-time generic type mismatch.</comment>
<file context>
@@ -845,20 +845,24 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
+ normalizedParams.put(k, normalizedValue);
});
+ formParams.clear();
+ formParams.putAll(normalizedParams);
}
</file context>
| if (o != null && o.getClass().getEnumConstants() != null) { | ||
| v.set(0, o.toString()); | ||
| } | ||
| Map<String, Object> normalizedParams = new HashMap<>(); |
There was a problem hiding this comment.
P2: Multipart form parameter order can become unstable because HashMap is used as the intermediate normalization container before repopulating formParams.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/restclient-springBoot4-jackson2/src/main/java/org/openapitools/client/ApiClient.java, line 750:
<comment>Multipart form parameter order can become unstable because `HashMap` is used as the intermediate normalization container before repopulating `formParams`.</comment>
<file context>
@@ -747,20 +747,24 @@ protected RestClient.RequestBodySpec prepareRequest(String path, HttpMethod meth
addCookiesToRequest(defaultCookies, requestBuilder);
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
+ Map<String, Object> normalizedParams = new HashMap<>();
formParams.forEach((k, v) -> {
+ Object normalizedValue = v;
</file context>
| Map<String, Object> normalizedParams = new HashMap<>(); | |
| + Map<String, Object> normalizedParams = new java.util.LinkedHashMap<>(); |
| if (o != null && o.getClass().getEnumConstants() != null) { | ||
| v.set(0, o.toString()); | ||
| } | ||
| Map<String, Object> normalizedParams = new HashMap<>(); |
There was a problem hiding this comment.
P2: Multipart form field order can become unstable because params are rebuilt through an unordered HashMap before re-inserting into formParams.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java, line 797:
<comment>Multipart form field order can become unstable because params are rebuilt through an unordered `HashMap` before re-inserting into `formParams`.</comment>
<file context>
@@ -794,20 +794,24 @@ protected RestClient.RequestBodySpec prepareRequest(String path, HttpMethod meth
addCookiesToRequest(defaultCookies, requestBuilder);
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
+ Map<String, Object> normalizedParams = new HashMap<>();
formParams.forEach((k, v) -> {
+ Object normalizedValue = v;
</file context>
| Map<String, Object> normalizedParams = new HashMap<>(); | |
| Map<String, Object> normalizedParams = new java.util.LinkedHashMap<>(); |
| } | ||
| normalizedParams.put(k, normalizedValue); | ||
| }); | ||
| formParams.clear(); |
There was a problem hiding this comment.
P2: Multipart normalization now requires mutating formParams (clear/putAll), which can fail for immutable MultiValueMap inputs passed to public invokeAPI.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/restclient-springBoot4-jackson3/src/main/java/org/openapitools/client/ApiClient.java, line 759:
<comment>Multipart normalization now requires mutating `formParams` (`clear`/`putAll`), which can fail for immutable `MultiValueMap` inputs passed to public `invokeAPI`.</comment>
<file context>
@@ -740,20 +740,24 @@ protected RestClient.RequestBodySpec prepareRequest(String path, HttpMethod meth
}
+ normalizedParams.put(k, normalizedValue);
});
+ formParams.clear();
+ formParams.putAll(normalizedParams);
}
</file context>
| if (o != null && o.getClass().getEnumConstants() != null) { | ||
| v.set(0, o.toString()); | ||
| } | ||
| Map<String, Object> normalizedParams = new HashMap<>(); |
There was a problem hiding this comment.
P2: Multipart form parameter normalization now uses HashMap, which can reorder parts and change request part order nondeterministically.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/java/restclient-sealedInterface/src/main/java/org/openapitools/client/ApiClient.java, line 724:
<comment>Multipart form parameter normalization now uses `HashMap`, which can reorder parts and change request part order nondeterministically.</comment>
<file context>
@@ -721,20 +721,24 @@ protected RestClient.RequestBodySpec prepareRequest(String path, HttpMethod meth
addCookiesToRequest(defaultCookies, requestBuilder);
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
+ Map<String, Object> normalizedParams = new HashMap<>();
formParams.forEach((k, v) -> {
+ Object normalizedValue = v;
</file context>
| Map<String, Object> normalizedParams = new HashMap<>(); | |
| Map<String, Object> normalizedParams = new java.util.LinkedHashMap<>(); |
| Map<String, Object> normalizedParams = new HashMap<>(); | ||
| formParams.forEach((k, v) -> { | ||
| Object normalizedValue = v; | ||
| if (v instanceof List<?> && !((List<?>) v).isEmpty()) { |
There was a problem hiding this comment.
- v instanceof List<?> list (cast, declare and assign in one step)
- Move empty list check into the if block. this will make it much easier to see how "normalizedValue" is potentially a redundant variable. It will also make it obvious that get(0) is safe.
There was a problem hiding this comment.
Unfortunately using pattern matching like v instanceof List<?> list is not possible because the generators would need to support older Java versions. But maybe I'm mistaken here as I'm still pretty new to the project
Chrimle
left a comment
There was a problem hiding this comment.
Minor refactors, but concerns about modifying the original formParams beyond the scope of enum-entries.
| } | ||
| normalizedParams.put(k, normalizedValue); | ||
| }); | ||
| formParams.clear(); |
There was a problem hiding this comment.
This is questionable. Before, the behavior was to replace a list of enums with a single entry enum string.
now, this would modify non-enum entries (by removing them completely)
There was a problem hiding this comment.
As mentioned below, I now reduced this PR to just tackle the original issue.
The fix is now much smaller in scope. I would open a new issue concerning the normalizing of all enum elements
c0eaf2b to
e0d29ae
Compare
|
Thanks for all your feedback @Chrimle I now did not address the broader question of whether only the first enum element should be normalized, since that appears to be a separate issue in the original implementation and would expand the scope of this PR. Changing this behavior could also introduce backwards incompatibility, as existing code might implicitly rely on the current behavior (even if it is inconsistent). I think this should be discussed separately, so I’m happy to open a follow-up issue to evaluate a more complete fix. |
…part list params (#23153)
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
master(upcoming7.x.0minor release - breaking changes with fallbacks),8.0.x(breaking changes without fallbacks)"fixes #123"present in the PR description)Description
This PR fixes an issue in the
javagenerator (restclientlibrary) where multipart form parameters containing lists could cause anIndexOutOfBoundsException.Root cause
The existing implementation:
v.get(0)getEnumConstants() != nullString, leaving the rest unchangedArrayList, excluding otherListimplementationsThis leads to:
Fix
getEnumConstants()withisEnum()for clearer intentUpdated logic:
This preserves the original intent (enum list handling) while making it safe and consistent.
Tests
Added a regression test in JavaClientCodegenTest to verify that:
Generated ApiClient.java contains the new guarded logic
Summary by cubic
Fixes an IndexOutOfBoundsException for empty multipart/form-data list params in
javarestclientby adding an empty-list guard and safer enum detection.ArrayListbefore accessing index 0 in multipart form params.isEnum()and convert the first enum item to a string.Written for commit e0d29ae. Summary will update on new commits.