Skip to content

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

@pariola

Description

@pariola

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions