From 116023e0ac3d9fd92beb33401f9e6f0db6c8408f Mon Sep 17 00:00:00 2001 From: arimu1 <19286898+arimu1@users.noreply.github.com> Date: Sat, 29 Aug 2026 09:58:16 +0700 Subject: [PATCH] fix: prevent StringIndexOutOfBoundsException in uniqueName with leading separators Skip empty tokens produced by split() when camelCaseFlattenNaming is enabled, and fall back to inline_object when the sanitized name would otherwise be blank. Fixes #2386 --- .../v3/parser/util/InlineModelResolver.java | 10 +++++--- .../parser/util/InlineModelResolverTest.java | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java index 6ea832e816..6f3ef489e6 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/InlineModelResolver.java @@ -438,14 +438,18 @@ public String uniqueName(String key) { int count = 0; boolean done = false; if (camelCaseFlattenNaming) { - String uniqueKey; String concatenated = ""; - for (int i = 0; i < key.split("[-|\\s|_]").length; i++) { - uniqueKey = key.split("[-|\\s|_]")[i]; + for (String uniqueKey : key.split("[-|\\s|_]")) { + if (uniqueKey.isEmpty()) { + continue; + } uniqueKey = uniqueKey.substring(0, 1).toUpperCase() + uniqueKey.substring(1); concatenated = concatenated.concat(uniqueKey); } key = concatenated.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter + if (key.isEmpty()) { + key = "inline_object"; + } }else { key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter } diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/InlineModelResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/InlineModelResolverTest.java index 2d2d1de6a8..544d8be11a 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/InlineModelResolverTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/InlineModelResolverTest.java @@ -1709,6 +1709,31 @@ public void testInlineItemsSchema() { assertNotNull(openAPI.getComponents().getSchemas().get("inline_response_200")); } + @Test(description = "https://github.com/swagger-api/swagger-parser/issues/2386") + public void testUniqueNameSkipsEmptyTokensFromLeadingSeparators() { + OpenAPI openAPI = new OpenAPI(); + openAPI.setComponents(new Components()); + InlineModelResolver resolver = new InlineModelResolver(false, true); + resolver.flatten(openAPI); + + assertEquals("MyModel", resolver.uniqueName(" my model")); + assertEquals("Foo", resolver.uniqueName("-foo")); + assertEquals("Foo", resolver.uniqueName("_foo")); + assertEquals("FooBar", resolver.uniqueName("foo--bar")); + assertEquals("inline_object", resolver.uniqueName("")); + assertEquals("inline_object", resolver.uniqueName("---")); + } + + @Test(description = "https://github.com/swagger-api/swagger-parser/issues/2386") + public void testFlattenSchemaTitleWithLeadingSeparator() { + String title = " my model"; + OpenAPI openAPI = openAPIWithInlineResponseSchema(title); + + new InlineModelResolver(false, true).flatten(openAPI); + + assertFlattenedResponseSchema(openAPI, "MyModel", "#/components/schemas/MyModel"); + } + @Test(description = "https://github.com/swagger-api/swagger-parser/issues/1200") public void testSchemaPropertiesBeingPassedToFlattenedModel() { OpenAPI openAPI = new OpenAPI();