Repository: getkin/kin-openapi (go)

Issue:
Failure loading OpenAPI 3.0 spec when a ref to 'additionalProperties' exists
When trying to load an OpenAPI 3.0 file which includes a ref to "additionalProperties" the load panics

A minimal example:
```
openapi: 3.0.0
components:
  schemas:
    schema1:
      type: object
      additionalProperties:
        type: string
    schema2:
      type: object
      properties:
        prop:
          $ref: '#/components/schemas/schema1/additionalProperties'
```

Pull request:
fix drilling down struct looking for additionalProperties
Fixes #376 

Patch:
diff --git a/openapi3/loader.go b/openapi3/loader.go
index ff93182..95c6f15 100644
--- a/openapi3/loader.go
+++ b/openapi3/loader.go
@@ -305,6 +305,9 @@ func (loader *Loader) resolveComponent(
 	}
 	var cursor interface{}
 	if cursor, err = drill(doc); err != nil {
+		if path == nil {
+			return nil, err
+		}
 		var err2 error
 		data, err2 := loader.readURL(path)
 		if err2 != nil {
@@ -346,6 +349,14 @@ func (loader *Loader) resolveComponent(
 }
 
 func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
+	// Special case due to multijson
+	if s, ok := cursor.(*SchemaRef); ok && fieldName == "additionalProperties" {
+		if ap := s.Value.AdditionalProperties; ap != nil {
+			return ap, nil
+		}
+		return s.Value.AdditionalPropertiesAllowed, nil
+	}
+
 	switch val := reflect.Indirect(reflect.ValueOf(cursor)); val.Kind() {
 	case reflect.Map:
 		elementValue := val.MapIndex(reflect.ValueOf(fieldName))
@@ -372,6 +383,10 @@ func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
 			field := val.Type().Field(i)
 			tagValue := field.Tag.Get("yaml")
 			yamlKey := strings.Split(tagValue, ",")[0]
+			if yamlKey == "-" {
+				tagValue := field.Tag.Get("multijson")
+				yamlKey = strings.Split(tagValue, ",")[0]
+			}
 			if yamlKey == fieldName {
 				return val.Field(i).Interface(), nil
 			}
diff --git a/openapi3/schema.go b/openapi3/schema.go
index 8c59f3c..fe6098f 100644
--- a/openapi3/schema.go
+++ b/openapi3/schema.go
@@ -110,7 +110,7 @@ type Schema struct {
 	ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
 
 	// Object-related, here for struct compactness
-	AdditionalPropertiesAllowed *bool `json:"-" multijson:"additionalProperties,omitempty" yaml:"-"`
+	AdditionalPropertiesAllowed *bool `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"`
 	// Array-related, here for struct compactness
 	UniqueItems bool `json:"uniqueItems,omitempty" yaml:"uniqueItems,omitempty"`
 	// Number-related, here for struct compactness
@@ -145,7 +145,7 @@ type Schema struct {
 	Properties           Schemas        `json:"properties,omitempty" yaml:"properties,omitempty"`
 	MinProps             uint64         `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
 	MaxProps             *uint64        `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
-	AdditionalProperties *SchemaRef     `json:"-" multijson:"additionalProperties,omitempty" yaml:"-"`
+	AdditionalProperties *SchemaRef     `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"`
 	Discriminator        *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
 }
 


Test patch:
diff --git a/openapi3/issue376_test.go b/openapi3/issue376_test.go
new file mode 100644
index 0000000..c23ac24
--- /dev/null
+++ b/openapi3/issue376_test.go
@@ -0,0 +1,42 @@
+package openapi3
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIssue376(t *testing.T) {
+	spec := []byte(`
+openapi: 3.0.0
+components:
+  schemas:
+    schema1:
+      type: object
+      additionalProperties:
+        type: string
+    schema2:
+      type: object
+      properties:
+        prop:
+          $ref: '#/components/schemas/schema1/additionalProperties'
+paths: {}
+info:
+  title: An API
+  version: 1.2.3.4
+`)
+
+	loader := NewLoader()
+
+	doc, err := loader.LoadFromData(spec)
+	require.NoError(t, err)
+
+	err = doc.Validate(loader.Context)
+	require.NoError(t, err)
+
+	require.Equal(t, "An API", doc.Info.Title)
+	require.Equal(t, 2, len(doc.Components.Schemas))
+	require.Equal(t, 0, len(doc.Paths))
+
+	require.Equal(t, "string", doc.Components.Schemas["schema2"].Value.Properties["prop"].Value.Type)
+}