From 78347da1522b69aee030d2b39bf9e2d70e0c70e9 Mon Sep 17 00:00:00 2001 From: Bartolomeooo Date: Mon, 17 Aug 2026 11:03:12 +0200 Subject: [PATCH] Fix remaining ResolverFully recursion edge case --- .../swagger/v3/parser/util/ResolverFully.java | 10 +++---- .../v3/parser/test/OpenAPIResolverTest.java | 22 ++++++++++++++++ .../issue_2297_allof_self_recursion.yaml | 26 +++++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 modules/swagger-parser-v3/src/test/resources/issue_2297_allof_self_recursion.yaml diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java index 755e8b6d32..5c06a5e0d3 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java @@ -529,7 +529,11 @@ private Schema resolveSchemaImpl(Schema schema) { for (String key : updated.keySet()) { Schema property = updated.get(key); - if (property.getProperties() != model.getProperties()) { + if (schemasInProgress.contains(property) || property.getProperties() == model.getProperties()) { + LOGGER.debug("not adding recursive properties, using generic object"); + ObjectSchema newSchema = new ObjectSchema(); + model.addProperties(key, newSchema); + } else { if (!hasSchemaType(property) && parseOptions.isExplicitObjectSchema()) { if (SpecVersion.V30.equals(property.getSpecVersion())) { property.setType("object"); @@ -538,10 +542,6 @@ private Schema resolveSchemaImpl(Schema schema) { } } model.addProperties(key, property); - } else { - LOGGER.debug("not adding recursive properties, using generic object"); - ObjectSchema newSchema = new ObjectSchema(); - model.addProperties(key, newSchema); } } diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java index 23193ea75a..dd76f6e037 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java @@ -1492,6 +1492,28 @@ public void recursiveResolvingIssue1751RecursiveArrayItems() { } } + @Test + public void recursiveResolvingAllOfSelfRecursionOas31() { + ParseOptions parseOptions = new ParseOptions(); + parseOptions.setResolve(true); + parseOptions.setResolveFully(true); + OpenAPI openAPI = new OpenAPIV3Parser().read("issue_2297_allof_self_recursion.yaml", null, parseOptions); + assertNotNull(openAPI, "OpenAPI should be parsed successfully"); + assertNotNull(openAPI.getComponents(), "Components should not be null"); + Schema node = openAPI.getComponents().getSchemas().get("Node"); + assertNotNull(node, "Node schema should be present"); + assertNotNull(node.getProperties(), "Node should have properties"); + assertNotNull(node.getProperties().get("child"), + "Node should contain the self-referencing property"); + try { + String serialized = Json.mapper().writeValueAsString(openAPI); + assertNotNull(serialized, "Serialized output should not be null"); + } + catch (Exception e) { + fail("Recursive loop found for self-reference combined with allOf: " + e.getMessage()); + } + } + @Test public void recursiveIssue984() { ParseOptions parseOptions = new ParseOptions(); diff --git a/modules/swagger-parser-v3/src/test/resources/issue_2297_allof_self_recursion.yaml b/modules/swagger-parser-v3/src/test/resources/issue_2297_allof_self_recursion.yaml new file mode 100644 index 0000000000..86043398f8 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue_2297_allof_self_recursion.yaml @@ -0,0 +1,26 @@ +openapi: 3.1.0 +info: + title: allOf self recursion regression + version: 1.0.0 +paths: + /node: + get: + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Node' +components: + schemas: + Node: + type: object + allOf: + - type: object + properties: + value: + type: number + properties: + child: + $ref: '#/components/schemas/Node'