Skip to content

Commit 19ba1f8

Browse files
Compile pattern on validate (#375)
Co-authored-by: Pierre Fenoll <[email protected]>
1 parent d308378 commit 19ba1f8

File tree

4 files changed

+58
-8
lines changed

4 files changed

+58
-8
lines changed

.github/workflows/go.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ jobs:
6565
run: git --no-pager diff && [[ $(git --no-pager diff --name-only | wc -l) = 0 ]]
6666

6767
- run: go test ./...
68+
- run: go test -v -run TestRaceyPatternSchema -race ./...
69+
env:
70+
CGO_ENABLED: '1'
6871
- run: |
6972
cd openapi3/testdata
7073
go get -u -v github.com/getkin/kin-openapi

openapi3/race_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package openapi3_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/getkin/kin-openapi/openapi3"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestRaceyPatternSchema(t *testing.T) {
12+
schema := openapi3.Schema{
13+
Pattern: "^test|for|race|condition$",
14+
Type: "string",
15+
}
16+
17+
err := schema.Validate(context.Background())
18+
require.NoError(t, err)
19+
20+
visit := func() {
21+
err := schema.VisitJSONString("test")
22+
require.NoError(t, err)
23+
}
24+
25+
go visit()
26+
visit()
27+
}

openapi3/schema.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,11 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
676676
}
677677
}
678678
}
679+
if schema.Pattern != "" {
680+
if err = schema.compilePattern(); err != nil {
681+
return err
682+
}
683+
}
679684
case "array":
680685
if schema.Items == nil {
681686
return errors.New("when schema type is 'array', schema 'items' must be non-null")
@@ -1138,15 +1143,9 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value
11381143
}
11391144

11401145
// "pattern"
1141-
if pattern := schema.Pattern; pattern != "" && schema.compiledPattern == nil {
1146+
if schema.Pattern != "" && schema.compiledPattern == nil {
11421147
var err error
1143-
if schema.compiledPattern, err = regexp.Compile(pattern); err != nil {
1144-
err = &SchemaError{
1145-
Value: value,
1146-
Schema: schema,
1147-
SchemaField: "pattern",
1148-
Reason: fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
1149-
}
1148+
if err = schema.compilePattern(); err != nil {
11501149
if !settings.multiError {
11511150
return err
11521151
}
@@ -1460,6 +1459,17 @@ func (schema *Schema) expectedType(settings *schemaValidationSettings, typ strin
14601459
}
14611460
}
14621461

1462+
func (schema *Schema) compilePattern() (err error) {
1463+
if schema.compiledPattern, err = regexp.Compile(schema.Pattern); err != nil {
1464+
return &SchemaError{
1465+
Schema: schema,
1466+
SchemaField: "pattern",
1467+
Reason: fmt.Sprintf("cannot compile pattern %q: %v", schema.Pattern, err),
1468+
}
1469+
}
1470+
return nil
1471+
}
1472+
14631473
type SchemaError struct {
14641474
Value interface{}
14651475
reversePath []string

openapi3/schema_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,3 +1219,13 @@ components:
12191219
require.NotEqual(t, errSchema, err)
12201220
require.Contains(t, err.Error(), `Error at "/ownerName": Doesn't match schema "not"`)
12211221
}
1222+
1223+
func TestValidationFailsOnInvalidPattern(t *testing.T) {
1224+
schema := Schema{
1225+
Pattern: "[",
1226+
Type: "string",
1227+
}
1228+
1229+
var err = schema.Validate(context.Background())
1230+
require.Error(t, err)
1231+
}

0 commit comments

Comments
 (0)