Merge branch 'main' into ordered-libopenapi

This commit is contained in:
Tristan Cartledge
2023-12-03 20:43:45 +00:00
3 changed files with 1447 additions and 1377 deletions

View File

@@ -310,7 +310,8 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
}
journey = append(journey, ref)
relatives := resolver.extractRelatives(ref, ref.Node, nil, seen, journey, resolve)
seenRelatives := make(map[int]bool)
relatives := resolver.extractRelatives(ref, ref.Node, nil, seen, journey, seenRelatives, resolve, 0)
seen = make(map[string]bool)
@@ -421,19 +422,50 @@ func (resolver *Resolver) isInfiniteCircularDependency(ref *Reference, visitedDe
func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.Node,
foundRelatives map[string]bool,
journey []*Reference, resolve bool) []*Reference {
journey []*Reference, seen map[int]bool, resolve bool, depth int) []*Reference {
if len(journey) > 100 {
return nil
}
// this is a safety check to prevent a stack overflow.
if depth > 500 {
def := "unknown"
if ref != nil {
def = ref.FullDefinition
}
if resolver.specIndex != nil && resolver.specIndex.logger != nil {
resolver.specIndex.logger.Warn("libopenapi resolver: relative depth exceeded 500 levels, "+
"check for circular references - resolving may be incomplete",
"reference", def)
}
loop := append(journey, ref)
circRef := &CircularReferenceResult{
Journey: loop,
Start: ref,
LoopIndex: depth,
LoopPoint: ref,
}
resolver.circularReferences = append(resolver.circularReferences, circRef)
resolver.resolvingErrors = append(resolver.resolvingErrors, &ResolvingError{
ErrorRef: fmt.Errorf("circular reference detected: %s", circRef.GenerateJourneyPath()),
Node: node,
Path: circRef.GenerateJourneyPath(),
})
ref.Circular = true
return nil
}
var found []*Reference
if len(node.Content) > 0 {
for i, n := range node.Content {
if utils.IsNodeMap(n) || utils.IsNodeArray(n) {
depth++
found = append(found, resolver.extractRelatives(ref, n, node, foundRelatives, journey, seen, resolve, depth)...)
found = append(found, resolver.extractRelatives(ref, n, node, foundRelatives, journey, resolve)...)
}
if i%2 == 0 && n.Value == "$ref" {

View File

@@ -1,11 +1,13 @@
package index
import (
"bytes"
"errors"
"fmt"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/utils"
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
"log/slog"
"net/http"
"net/url"
"os"
@@ -432,7 +434,43 @@ func TestResolver_DeepJourney(t *testing.T) {
}
idx := NewSpecIndexWithConfig(nil, CreateClosedAPIIndexConfig())
resolver := NewResolver(idx)
assert.Nil(t, resolver.extractRelatives(nil, nil, nil, nil, journey, false))
assert.Nil(t, resolver.extractRelatives(nil, nil, nil, nil, journey, nil, false, 0))
}
func TestResolver_DeepDepth(t *testing.T) {
var refA, refB *yaml.Node
refA = &yaml.Node{
Value: "A",
Tag: "!!seq",
}
refB = &yaml.Node{
Value: "B",
Tag: "!!seq",
}
refA.Content = append(refA.Content, refB)
refB.Content = append(refB.Content, refA)
idx := NewSpecIndexWithConfig(nil, CreateClosedAPIIndexConfig())
resolver := NewResolver(idx)
// add a logger
var log []byte
buf := bytes.NewBuffer(log)
logger := slog.New(slog.NewTextHandler(buf, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
idx.logger = logger
ref := &Reference{
FullDefinition: "#/components/schemas/A",
}
found := resolver.extractRelatives(ref, refA, nil, nil, nil, nil, false, 0)
assert.Nil(t, found)
assert.Contains(t, buf.String(), "libopenapi resolver: relative depth exceeded 500 levels")
}
func TestResolver_ResolveComponents_Stripe_NoRolodex(t *testing.T) {