Skip to content

Commit cb43499

Browse files
committed
fix(java/restclient): avoid IndexOutOfBoundsException for empty multipart list params (#23153)
1 parent 054c65c commit cb43499

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -845,15 +845,20 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
845845
addCookiesToRequest(defaultCookies, requestBuilder);
846846
847847
if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
848-
formParams.forEach(
849-
(k, v) -> {
850-
if (v instanceof java.util.ArrayList) {
851-
Object o = v.get(0);
852-
if (o != null && o.getClass().getEnumConstants() != null) {
853-
v.set(0, o.toString());
848+
formParams.forEach((k, v) -> {
849+
if (v instanceof List<?> && !((List<?>) v).isEmpty()) {
850+
List<Object> list = (List<Object>) v;
851+
Object first = list.get(0);
852+
if (first != null && first.getClass().isEnum()) {
853+
for (int i = 0; i < list.size(); i++) {
854+
Object item = list.get(i);
855+
if (item != null) {
856+
((List) list).set(i, item.toString());
854857
}
855858
}
856-
});
859+
}
860+
}
861+
});
857862
}
858863
859864
var selectedBody = selectBody(body, formParams, contentType);

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4211,4 +4211,36 @@ public void testFeignHc5CustomTemplateDirIsPreserved() {
42114211
"feign-hc5 must preserve a user-provided templateDir and not overwrite it with 'feign'");
42124212
}
42134213

4214+
@Test(description = "Regression test for multipart/form-data list handling in restclient ApiClient to avoid IndexOutOfBoundsException on empty lists")
4215+
public void testRestClientMultipartFormParamsGuardAgainstEmptyLists() {
4216+
final Path output = newTempFolder();
4217+
final CodegenConfigurator configurator = new CodegenConfigurator()
4218+
.setGeneratorName(JAVA_GENERATOR)
4219+
.setLibrary(JavaClientCodegen.RESTCLIENT)
4220+
.setAdditionalProperties(Map.of(CodegenConstants.API_PACKAGE, "xyz.abcdef.api"))
4221+
.setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml")
4222+
.setOutputDir(output.toString().replace("\\", "/"));
4223+
4224+
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
4225+
4226+
validateJavaSourceFiles(files);
4227+
4228+
assertFileContains(
4229+
output.resolve("src/main/java/xyz/abcdef/ApiClient.java"),
4230+
"if (v instanceof List<?> && !((List<?>) v).isEmpty()) {",
4231+
"List<Object> list = (List<Object>) v;",
4232+
"Object first = list.get(0);",
4233+
"if (first != null && first.getClass().isEnum()) {",
4234+
"for (int i = 0; i < list.size(); i++) {",
4235+
"Object item = list.get(i);",
4236+
"if (item != null) {",
4237+
"((List) list).set(i, item.toString());"
4238+
);
4239+
4240+
TestUtils.assertFileNotContains(
4241+
output.resolve("src/main/java/xyz/abcdef/ApiClient.java"),
4242+
"if (v instanceof java.util.ArrayList) {",
4243+
"o.getClass().getEnumConstants() != null"
4244+
);
4245+
}
42144246
}

0 commit comments

Comments
 (0)