Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request body validation panic when body uses array circular reference field #107

Open
pariola opened this issue Nov 18, 2024 · 1 comment

Comments

@pariola
Copy link

pariola commented Nov 18, 2024

Building the model with the following specification reports an infinite circular reference because of GroupCondition having a required conditions array.

I do not think this should be reported as a circular reference since Condition uses a oneOf and has at least one option that doesn't cause a cycle.

spec.yml

openapi: 3.1.0
info:
  title: Panic at request body validation
  version: 1.0.0
paths:
  /operations:
    patch:
      description: Update operations
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Condition"
components:
  schemas:
    Condition:
      oneOf:
        - $ref: "#/components/schemas/GroupCondition"
        - $ref: "#/components/schemas/EqualCondition"
    GroupCondition:
      type: object
      properties:
        operator:
          type: string
          enum:
            - and
            - or
        conditions:
          type: array
          items:
            $ref: "#/components/schemas/Condition"
        required:
          - operator
          - conditions
    EqualCondition:
      type: object
      properties:
        operator:
          type: string
          enum:
            - equal
        data:
          type: object
          properties:
            property:
              type: string
            value: {}
          required:
            - property
      required:
        - operator
        - data

main.go

package main

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/pb33f/libopenapi"
	validator "github.com/pb33f/libopenapi-validator"
	"github.com/pb33f/libopenapi/datamodel"
)

func main() {
	spec, _ := os.ReadFile("./test.yml")

	cfg := datamodel.NewDocumentConfiguration()
	// cfg.IgnoreArrayCircularReferences = true

	document, err := libopenapi.NewDocumentWithConfiguration(spec, cfg)
	if err != nil {
		panic(fmt.Sprintf("cannot create new document: %e", err))
	}

	vv, _ := document.BuildV3Model()
	circ := vv.Index.GetCircularReferences()
	fmt.Printf("Circular references?: %v\n", len(circ) > 0)

	v, validatorErrs := validator.NewValidator(document)
	if len(validatorErrs) > 0 {
		for i := range validatorErrs {
			fmt.Printf("error: %e\n", validatorErrs[i])
		}
	}

	req, _ := http.NewRequest(http.MethodPatch, "https://localhost:4000/operations", strings.NewReader("{}"))
	req.Header.Set("Content-Type", "application/json")

	fmt.Println(v.ValidateHttpRequest(req))
}

Also, using the IgnoreArrayCircularReferences causes the validator to crash with a stack overflow error.

runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0x14035100340 stack=[0x14035100000, 0x14055100000]
fatal error: stack overflow

Please, any ideas on how to solve this?

@daveshanley
Copy link
Member

The behavior is correct, this spec absolutely has an array based circular reference. Disabling the check, will mean that a stack overflow is all but inevitable as the schema generated by inlining all those references, creates an endless loop.

The solution is to stop the stack overflow, but I don't know where it's coming from, there isn't enough information in your report to determine when the stack is exploding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants