Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
module github.com/go-openapi/validate

require (
github.com/go-openapi/analysis v0.25.3
github.com/go-openapi/analysis v0.25.5
github.com/go-openapi/errors v0.22.8
github.com/go-openapi/jsonpointer v1.0.0
github.com/go-openapi/loads v0.24.0
github.com/go-openapi/spec v0.22.6
github.com/go-openapi/loads v0.25.0
github.com/go-openapi/spec v0.22.9
github.com/go-openapi/strfmt v0.27.0
github.com/go-openapi/swag/conv v0.27.0
github.com/go-openapi/swag/fileutils v0.27.0
github.com/go-openapi/swag/jsonutils v0.27.0
github.com/go-openapi/swag/stringutils v0.27.0
github.com/go-openapi/swag/conv v0.27.3
github.com/go-openapi/swag/fileutils v0.27.3
github.com/go-openapi/swag/jsonutils v0.27.3
github.com/go-openapi/swag/loading v0.27.3
github.com/go-openapi/swag/stringutils v0.27.3
github.com/go-openapi/testify/v2 v2.6.0
go.yaml.in/yaml/v3 v3.0.4
)

require (
github.com/go-openapi/jsonreference v0.21.6 // indirect
github.com/go-openapi/swag/jsonname v0.26.1 // indirect
github.com/go-openapi/swag/loading v0.26.1 // indirect
github.com/go-openapi/swag/mangling v0.26.1 // indirect
github.com/go-openapi/swag/typeutils v0.27.0 // indirect
github.com/go-openapi/swag/yamlutils v0.26.1 // indirect
github.com/go-openapi/jsonreference v1.0.0 // indirect
github.com/go-openapi/swag/mangling v0.27.3 // indirect
github.com/go-openapi/swag/pools v0.27.3 // indirect
github.com/go-openapi/swag/typeutils v0.27.3 // indirect
github.com/go-openapi/swag/yamlutils v0.27.3 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/oklog/ulid/v2 v2.1.1 // indirect
Expand Down
56 changes: 28 additions & 28 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
github.com/go-openapi/analysis v0.25.3 h1:4zlcg85pd2xq3sEgjW887n1IpwCpCqTmqeT6dP9OxDw=
github.com/go-openapi/analysis v0.25.3/go.mod h1:6PEmUIra9/rn6SPstzbrMkhFAsMB2qm7g6E+4DRFyCU=
github.com/go-openapi/analysis v0.25.5 h1:xPYEvTb90o1y0epuiOPAoG4QqahjP3cdp5xNlHeKJRI=
github.com/go-openapi/analysis v0.25.5/go.mod h1:d3UGtQC5uq5Kqqqis2VH09Km/v3vwsWrYkbp4gdm+Rc=
github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I=
github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w=
github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s=
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
github.com/go-openapi/jsonreference v0.21.6 h1:NZ5nGfnaM1n4I43Xjm1e5/M2GjOwQwndQz22uhxwD+Y=
github.com/go-openapi/jsonreference v0.21.6/go.mod h1:xzbgtQ3ZbWxvET3AxdzCJlJt6vkovbf+IfSPJjD0tUY=
github.com/go-openapi/loads v0.24.0 h1:4LLorXRPTzIN9V6ngMUZbAscsBOUBk3Oa8cClu/bFrQ=
github.com/go-openapi/loads v0.24.0/go.mod h1:xQMgX+hw5xRAhGrcDXxeMw78IFqUpIzhleu3HqPhyF4=
github.com/go-openapi/spec v0.22.6 h1:Tyy1pLaNCM8GBCFLoGYLonjJi6zykqyLCjXLc19ZPic=
github.com/go-openapi/spec v0.22.6/go.mod h1:HZvTHat+iH0PALQRWhrqIHtU/PEqxqd89fu0MxGlMeM=
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
github.com/go-openapi/loads v0.25.0 h1:74Bc2snfaVlsHzwdQj/3gsA9XJz3daXTJVs+4ZaK7jI=
github.com/go-openapi/loads v0.25.0/go.mod h1:JFBw4SIB9+PTIFHDfcXuSSy5h6aWzjtUCrPYyx3qWU8=
github.com/go-openapi/spec v0.22.9 h1:/vKIFDcGKp0ktZWGbym/tJEWbk6/XOEmAVU0kqKMH+w=
github.com/go-openapi/spec v0.22.9/go.mod h1:b/mNUYIOQOyIiUzUzXEE8xzyZqf93KvM9hQGP91yfl0=
github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM=
github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc=
github.com/go-openapi/swag/conv v0.27.0 h1:EKOH4feXrvdo8DbSsXSAqRT8fz1epEnS5O2IfXUOzE8=
github.com/go-openapi/swag/conv v0.27.0/go.mod h1:pfiv0uKQTbaGApk8Zs/lZV3uSjmSpa2FO1y183YngN8=
github.com/go-openapi/swag/fileutils v0.27.0 h1:ib5jMUqGq5tY1EyO4inlrabsaeDAleFU+XD1FXQcgp8=
github.com/go-openapi/swag/fileutils v0.27.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
github.com/go-openapi/swag/jsonname v0.26.1 h1:VReupaV6WxlAsCn0e4DUfgV6bPmINnPpyJDLqSfNPcE=
github.com/go-openapi/swag/jsonname v0.26.1/go.mod h1:OvdW6BoWoj33pTfi7x9vFrgmT+fk7aw0BRwvCE0YOuc=
github.com/go-openapi/swag/jsonutils v0.27.0 h1:VYtd9jEQYeU4j8q5vdn5KWotF4vKywhGdMBrALtAsfE=
github.com/go-openapi/swag/jsonutils v0.27.0/go.mod h1:U7pb8AGuwhok3RDicHeHwSG4L3PXSq6PAL98Aon632g=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0 h1:+d7C7Ur/SsGg/UZ9G0JEovnfRqtMNZCJQGKc2h/ojoE=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
github.com/go-openapi/swag/loading v0.26.1 h1:E9K4wqXeROlhjFQ13K9zMz6ojFGXIggGe+ad1odrK9w=
github.com/go-openapi/swag/loading v0.26.1/go.mod h1:3qvRIlWzWdq1HvmldwmuJ2ohpcAryN6xVt2OTKd0/7E=
github.com/go-openapi/swag/mangling v0.26.1 h1:gpYI4WuPKFJJVjV5cDLGlDVJhFIxYjQc7yN5eEb4CqM=
github.com/go-openapi/swag/mangling v0.26.1/go.mod h1:POETDH01hqAdASXfw7ISEd9bCOE6xBHOt8NHmGZRmYM=
github.com/go-openapi/swag/stringutils v0.27.0 h1:Of7w/HljWsNZvuxsUAnw3n+hCOyI6HLJOxW2kQRAxio=
github.com/go-openapi/swag/stringutils v0.27.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
github.com/go-openapi/swag/typeutils v0.27.0 h1:aCf4MSGo8NLwZP8Q6t32DWLJSvl/WwNqgmEG+xJ6v2o=
github.com/go-openapi/swag/typeutils v0.27.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
github.com/go-openapi/swag/yamlutils v0.26.1 h1:0TSLK+lXs9vfIhAWzBeI/lOzEnIoot6WTCO1aAeWFTk=
github.com/go-openapi/swag/yamlutils v0.26.1/go.mod h1:7W5b7PRX9MxwL7TjeG7H8HkyBGRsIDRObhyMWFgBI2M=
github.com/go-openapi/swag/conv v0.27.3 h1:iqJFmGEjmX3AY0lSszABFqRVqOSt99XS0LzNIMJYuhU=
github.com/go-openapi/swag/conv v0.27.3/go.mod h1:nPRmN6jgNme99hpf+nM0auDZGALWIqlwhisKPK/bQhQ=
github.com/go-openapi/swag/fileutils v0.27.3 h1:3UVoZ2RLaIs1lt+2jcKzL8RM3Yk0rmsDE9FLA/HGxFE=
github.com/go-openapi/swag/fileutils v0.27.3/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
github.com/go-openapi/swag/jsonutils v0.27.3 h1:1DEz+O82frtSMBcos/7XIn1GnpNTbsD4Bru4Dc/uhRc=
github.com/go-openapi/swag/jsonutils v0.27.3/go.mod h1:qiDCoQvzkMxrV3G8FLEdIU5L+EFYc0zcDOHWT3Yofvo=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3 h1:h/eT9kmGCDdFLJF29lOhzLtF0FmP1AX2MhLJWVebsb8=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
github.com/go-openapi/swag/loading v0.27.3 h1:L9nQkEgzU7QgFQL+pLEMfGUKxeM4pWwGwbET9Z3weW0=
github.com/go-openapi/swag/loading v0.27.3/go.mod h1:rJ0NeaKsF4CVPnMGjPQl7JlSHzvD0bc2DKXLss1hiuE=
github.com/go-openapi/swag/mangling v0.27.3 h1:gRzzD1PAUoLTtGMgI3KpBmCSOlTuLTFWnviLxLcTnyg=
github.com/go-openapi/swag/mangling v0.27.3/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
github.com/go-openapi/swag/pools v0.27.3 h1:gXjImP3F6/56wRRcFgEPld084Y6u2gs21ikPBt8NKBk=
github.com/go-openapi/swag/pools v0.27.3/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
github.com/go-openapi/swag/stringutils v0.27.3 h1:Ru28hnbAvN5wycALQYy8IobHvASq+FUFMlp1QzLM0JI=
github.com/go-openapi/swag/stringutils v0.27.3/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
github.com/go-openapi/swag/typeutils v0.27.3 h1:l6SSrx5eR5/WVwrGNzN6bQ9WqL04mrxNBl9YgQ3rcJ4=
github.com/go-openapi/swag/typeutils v0.27.3/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
github.com/go-openapi/swag/yamlutils v0.27.3 h1:cRFCAoYtslYn9L9T0xWryHy1t7c1MACC+DMj3CLvwvs=
github.com/go-openapi/swag/yamlutils v0.27.3/go.mod h1:6JYBGj8sw/NawMllyZY+cTA8Mzk2etS3ZBASdcyPsiU=
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
Expand Down
8 changes: 4 additions & 4 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ func (h *paramHelper) resolveParam(path, method, operationID string, param *spec
res := new(Result)
isRef := param.Ref.String() != ""
if s.spec.SpecFilePath() == "" {
err = spec.ExpandParameterWithRoot(param, s.spec.Spec(), nil)
err = spec.ExpandParameterWithOptions(param, s.spec.Spec(), nil, s.schemaOptions.expandOptions(""))
} else {
err = spec.ExpandParameter(param, s.spec.SpecFilePath())
err = spec.ExpandParameterWithOptions(param, nil, nil, s.schemaOptions.expandOptions(s.spec.SpecFilePath()))
}
if err != nil { // Safeguard
// NOTE: we may enter here when the whole parameter is an unresolved $ref
Expand Down Expand Up @@ -295,9 +295,9 @@ func (r *responseHelper) expandResponseRef(
res := new(Result)
if s.spec.SpecFilePath() == "" {
// there is no physical document to resolve $ref in response
err = spec.ExpandResponseWithRoot(response, s.spec.Spec(), nil)
err = spec.ExpandResponseWithOptions(response, s.spec.Spec(), nil, s.schemaOptions.expandOptions(""))
} else {
err = spec.ExpandResponse(response, s.spec.SpecFilePath())
err = spec.ExpandResponseWithOptions(response, nil, nil, s.schemaOptions.expandOptions(s.spec.SpecFilePath()))
}
if err != nil { // Safeguard
// NOTE: we may enter here when the whole response is an unresolved $ref.
Expand Down
10 changes: 5 additions & 5 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,18 @@ func newSchemaValidator(schema *spec.Schema, rootSchema any, root string, format
rootSchema = schema
}

if opts == nil {
opts = new(SchemaValidatorOptions)
}

if schema.ID != "" || schema.Ref.String() != "" || schema.Ref.IsRoot() {
err := spec.ExpandSchema(schema, rootSchema, nil)
err := spec.ExpandSchemaWithOptions(schema, rootSchema, nil, opts.expandOptions(""))
if err != nil {
msg := invalidSchemaProvidedMsg(err).Error()
panic(msg)
}
}

if opts == nil {
opts = new(SchemaValidatorOptions)
}

var s *SchemaValidator
if opts.recycleValidators {
s = pools.poolOfSchemaValidators.BorrowValidator()
Expand Down
55 changes: 55 additions & 0 deletions schema_loader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
// SPDX-License-Identifier: Apache-2.0

package validate

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag/loading"
"github.com/go-openapi/testify/v2/assert"
"github.com/go-openapi/testify/v2/require"
)

// TestSchemaValidator_WithPathLoader verifies that a document loader injected through
// WithPathLoader is the one used to resolve a remote $ref when building a schema validator — the
// hook a caller uses to confine loading when validating input from an untrusted source.
func TestSchemaValidator_WithPathLoader(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte(`{"type":"string"}`))
}))
defer srv.Close()

var calls int
loader := func(pth string, opts ...loading.Option) (json.RawMessage, error) {
calls++
return loading.LoadFromFileOrHTTP(pth, opts...)
}

schema := &spec.Schema{SchemaProps: spec.SchemaProps{Ref: spec.MustCreateRef(srv.URL + "/schema.json")}}
v := NewSchemaValidator(schema, nil, "", strfmt.Default, WithPathLoader(loader))

require.NotNil(t, v)
assert.TrueT(t, calls > 0, "expected the injected loader to resolve the remote $ref")
}

// TestSpecValidator_WithPathLoader verifies that WithPathLoader passed to the spec validator
// constructors reaches the schema options consumed by both the schema validation and the $ref
// resolution ($ref resolveRef) performed during spec validation.
func TestSpecValidator_WithPathLoader(t *testing.T) {
loader := func(string, ...loading.Option) (json.RawMessage, error) { return nil, nil }

s := NewSpecValidator(spec.MustLoadSwagger20Schema(), strfmt.Default, WithPathLoader(loader))
require.NotNil(t, s.schemaOptions)
require.NotNil(t, s.schemaOptions.pathLoaderWithOptions,
"WithPathLoader must reach the spec validator's schema options (used by resolveRef and schema validation)")

// built-in defaults are still applied alongside the injected option
assert.TrueT(t, s.schemaOptions.EnableObjectArrayTypeCheck)
assert.TrueT(t, s.schemaOptions.recycleValidators)
}
37 changes: 37 additions & 0 deletions schema_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@

package validate

import (
"encoding/json"

"github.com/go-openapi/spec"
"github.com/go-openapi/swag/loading"
)

// SchemaValidatorOptions defines optional rules for schema validation.
type SchemaValidatorOptions struct {
EnableObjectArrayTypeCheck bool
EnableArrayMustHaveItemsCheck bool
recycleValidators bool
recycleResult bool
skipSchemataResult bool
pathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error)
}

// Option sets optional rules for schema validation.
Expand Down Expand Up @@ -60,6 +68,23 @@ func WithSkipSchemataResult(enable bool) Option {
}
}

// WithPathLoader injects the document loader used to resolve remote and relative $ref while
// validating a schema or specification. It matches the option-aware loader signature of
// github.com/go-openapi/swag/loading (and go-openapi/loads).
//
// This lets validation resolve references through a caller-provided loader instead of the spec
// package's global default. The loader may carry any loading options — a custom HTTP client or
// timeout, authentication or custom headers, an embedded or rooted file system, and so on.
//
// One important use is confining loading of untrusted input: build the loader with loading.WithRoot
// (to confine local reads) and loading.WithHTTPClient (to restrict remote fetches), or use a
// restricted loader from go-openapi/loads. Left unset, the spec package default loader is used.
func WithPathLoader(loader func(string, ...loading.Option) (json.RawMessage, error)) Option {
return func(svo *SchemaValidatorOptions) {
svo.pathLoaderWithOptions = loader
}
}

// Options returns the current set of options.
func (svo SchemaValidatorOptions) Options() []Option {
return []Option{
Expand All @@ -68,5 +93,17 @@ func (svo SchemaValidatorOptions) Options() []Option {
WithRecycleValidators(svo.recycleValidators),
withRecycleResults(svo.recycleResult),
WithSkipSchemataResult(svo.skipSchemataResult),
WithPathLoader(svo.pathLoaderWithOptions),
}
}

// expandOptions builds the spec expand options for schema/$ref expansion during validation,
// carrying the injected loader (when set) so resolution can be confined. relativeBase is used for
// base-path-relative resolution; it is ignored by [spec.ExpandSchemaWithOptions], which derives the
// base from the root.
func (svo *SchemaValidatorOptions) expandOptions(relativeBase string) *spec.ExpandOptions {
return &spec.ExpandOptions{
RelativeBase: relativeBase,
PathLoaderWithOptions: svo.pathLoaderWithOptions,
}
}
28 changes: 20 additions & 8 deletions spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
//
// Returns an error flattening in a single standard error, all validation messages.
//
// Options are forwarded to the underlying [SpecValidator]; in particular [WithPathLoader] injects a
// confined document loader for validating a specification from an untrusted source.
//
// - Proposal for enhancement: $ref should not have siblings
// - Proposal for enhancement: make sure documentation reflects all checks and warnings
// - Proposal for enhancement: check on discriminators
Expand All @@ -35,8 +38,8 @@ import (
// - Proposal for enhancement: check on required properties to support anyOf, allOf, oneOf
//
// NOTE: SecurityScopes are maps: no need to check uniqueness.
func Spec(doc *loads.Document, formats strfmt.Registry) error {
errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats).Validate(doc)
func Spec(doc *loads.Document, formats strfmt.Registry, options ...Option) error {
errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats, options...).Validate(doc)
if errs.HasErrors() {
return errors.CompositeValidationError(errs.Errors...)
}
Expand All @@ -55,14 +58,20 @@ type SpecValidator struct {
}

// NewSpecValidator creates a new swagger spec validator instance.
func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry) *SpecValidator {
// schema options that apply to all called validators
//
// Options apply to the schema validators used internally. In particular, [WithPathLoader] injects
// the document loader used to resolve $ref while validating the specification — set a confined
// loader when validating a specification from an untrusted source (see the package "Security"
// notes on [WithPathLoader]).
func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry, options ...Option) *SpecValidator {
// schema options that apply to all called validators: built-in defaults first, then
// caller-supplied options (which may add a loader or override a default).
schemaOptions := new(SchemaValidatorOptions)
for _, o := range []Option{
for _, o := range append([]Option{
SwaggerSchema(true),
WithRecycleValidators(true),
// withRecycleResults(true),
} {
}, options...) {
o(schemaOptions)
}

Expand Down Expand Up @@ -252,7 +261,7 @@ func (s *SpecValidator) validateDuplicatePropertyNames() *Result {

func (s *SpecValidator) resolveRef(ref *spec.Ref) (*spec.Schema, error) {
if s.spec.SpecFilePath() != "" {
return spec.ResolveRefWithBase(s.spec.Spec(), ref, &spec.ExpandOptions{RelativeBase: s.spec.SpecFilePath()})
return spec.ResolveRefWithBase(s.spec.Spec(), ref, s.schemaOptions.expandOptions(s.spec.SpecFilePath()))
}
// NOTE: it looks like with the new spec resolver, this code is now unrecheable
return spec.ResolveRef(s.spec.Spec(), ref)
Expand Down Expand Up @@ -789,7 +798,10 @@ func (s *SpecValidator) validateReferencesValid() *Result {
// NOTE: with default settings, loads.Document.Expanded()
// stops on first error. Anyhow, the expand option to continue
// on errors fails to report errors at all.
exp, err := s.spec.Expanded()
//
// Pass the injected loader (if any) so whole-spec expansion is confined too. When no loader
// is set, this is a no-op: loads falls back to the document's own loader.
exp, err := s.spec.Expanded(s.schemaOptions.expandOptions(""))
if err != nil {
res.AddErrors(unresolvedReferencesMsg(err))
}
Expand Down
Loading