swagger-api / swagger-api/swagger-parser

[Bug]: ResolverFully remaining recursion edge case after #2297 for OAS 3.1 self-referencing allOf schema

Open
#2,374 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
Dominant language
Java
Stars
867
Forks
560
Avg merge
2d 21h
Merged PRs (30d)
7

Description

Description

This looks like a remaining ResolverFully recursion edge case after the fix for #2297, which closed #1751.

I am parsing an OpenAPI 3.1 definition with resolve = true and resolveFully = true.

The main recursion issue from #1751 appears to be fixed already, but there still seems to be a narrower case involving:

  • a self-referencing schema
  • allOf
  • OpenAPI 3.1
  • combinator aggregation during resolveFully

In this scenario, ResolverFully.resolveSchemaImpl creates a new aggregated schema for allOf, and later re-attaches properties using a properties map identity check. That seems insufficient when the resolved property points back to a schema that is still present in schemasInProgress, but the current model is already a newly created aggregated schema instance.

As a result, the recursive schema can be inserted back into the aggregated schema, creating a cyclic Java object graph.

Affected Version

2.1.47<=

Steps to Reproduce

  1. Parse the following OpenAPI 3.1 definition with resolveFully = true:

    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'
    
  2. Use parse options equivalent to:

    ParseOptions parseOptions = new ParseOptions();
    parseOptions.setResolve(true);
    parseOptions.setResolveFully(true);
    OpenAPI openAPI = new OpenAPIV3Parser().read("issue_2297_allof_self_recursion.yaml", null, parseOptions);
    
  3. Serialize the resolved OpenAPI, for example with:

    Json.mapper().writeValueAsString(openAPI);
    

Expected Behavior

resolveFully should resolve the schema without producing a cyclic Java object graph, and the resulting OpenAPI should serialize normally.

Actual Behavior

A recursive object graph can still be created in this OAS 3.1 + allOf + self-reference case, because the recursive property may be attached back to the newly aggregated schema.

In my local testing, this is fixed by also treating schemas still present in schemasInProgress as recursive placeholders when re-attaching properties, instead of relying only on:

property.getProperties() == model.getProperties()

Logs / Stack Traces

In earlier related reports, the failure manifested as StackOverflowError in ResolverFully.
This case appears to be a follow-up to that family of bugs rather than a totally separate issue.

If useful, I can provide a regression test and patch.

Environment

  • Java version: OpenJDK 17
  • Build tool: Maven
  • OS: macOS

Additional Context

Related issues:

This report is intended as a follow-up to #2297, not a duplicate of the original recursion bug fixed there.

Checklist

  • I have searched the existing issues and this is not a duplicate.
  • I have provided sufficient information for maintainers to reproduce the issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in ResolverFully.resolveSchemaImpl and reproduce the OAS 3.1 example with resolve and resolveFully enabled, then serialize the parsed OpenAPI with Json.mapper().writeValueAsString. Trace allOf aggregation, property re-attachment, and schemasInProgress. Done means the self-referencing schema does not create a cyclic object graph and the resolved OpenAPI serializes normally.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.