Skip to content

Commit

Permalink
Compile pattern on validate (#375)
Browse files Browse the repository at this point in the history
Co-authored-by: Pierre Fenoll <[email protected]>
  • Loading branch information
alexanderbolgov-ef and fenollp authored Jun 24, 2021
1 parent d308378 commit 19ba1f8
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ jobs:
run: git --no-pager diff && [[ $(git --no-pager diff --name-only | wc -l) = 0 ]]

- run: go test ./...
- run: go test -v -run TestRaceyPatternSchema -race ./...
env:
CGO_ENABLED: '1'
- run: |
cd openapi3/testdata
go get -u -v github.com/getkin/kin-openapi
Expand Down
27 changes: 27 additions & 0 deletions openapi3/race_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package openapi3_test

import (
"context"
"testing"

"github.com/getkin/kin-openapi/openapi3"
"github.com/stretchr/testify/require"
)

func TestRaceyPatternSchema(t *testing.T) {
schema := openapi3.Schema{
Pattern: "^test|for|race|condition$",
Type: "string",
}

err := schema.Validate(context.Background())
require.NoError(t, err)

visit := func() {
err := schema.VisitJSONString("test")
require.NoError(t, err)
}

go visit()
visit()
}
26 changes: 18 additions & 8 deletions openapi3/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,11 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
}
}
}
if schema.Pattern != "" {
if err = schema.compilePattern(); err != nil {
return err
}
}
case "array":
if schema.Items == nil {
return errors.New("when schema type is 'array', schema 'items' must be non-null")
Expand Down Expand Up @@ -1138,15 +1143,9 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value
}

// "pattern"
if pattern := schema.Pattern; pattern != "" && schema.compiledPattern == nil {
if schema.Pattern != "" && schema.compiledPattern == nil {
var err error
if schema.compiledPattern, err = regexp.Compile(pattern); err != nil {
err = &SchemaError{
Value: value,
Schema: schema,
SchemaField: "pattern",
Reason: fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
}
if err = schema.compilePattern(); err != nil {
if !settings.multiError {
return err
}
Expand Down Expand Up @@ -1460,6 +1459,17 @@ func (schema *Schema) expectedType(settings *schemaValidationSettings, typ strin
}
}

func (schema *Schema) compilePattern() (err error) {
if schema.compiledPattern, err = regexp.Compile(schema.Pattern); err != nil {
return &SchemaError{
Schema: schema,
SchemaField: "pattern",
Reason: fmt.Sprintf("cannot compile pattern %q: %v", schema.Pattern, err),
}
}
return nil
}

type SchemaError struct {
Value interface{}
reversePath []string
Expand Down
10 changes: 10 additions & 0 deletions openapi3/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1219,3 +1219,13 @@ components:
require.NotEqual(t, errSchema, err)
require.Contains(t, err.Error(), `Error at "/ownerName": Doesn't match schema "not"`)
}

func TestValidationFailsOnInvalidPattern(t *testing.T) {
schema := Schema{
Pattern: "[",
Type: "string",
}

var err = schema.Validate(context.Background())
require.Error(t, err)
}

0 comments on commit 19ba1f8

Please sign in to comment.