summaryrefslogtreecommitdiff
path: root/runconfig
diff options
context:
space:
mode:
authorSebastiaan van Stijn <github@gone.nl>2022-04-08 23:27:50 +0200
committerSebastiaan van Stijn <github@gone.nl>2022-04-11 21:44:45 +0200
commitb6d58d749c6d671f0dc19a88b948b772272e145d (patch)
tree9c0600be9bd5f31c9548fa779cf1f048023e7d2c /runconfig
parentff5f70e55f8cd303efbaee3eafda9dfe86a3da36 (diff)
downloaddocker-b6d58d749c6d671f0dc19a88b948b772272e145d.tar.gz
runconfig: ContainerDecoder(): fix handling of invalid JSON
Implement similar logic as is used in httputils.ReadJSON(). Before this patch, endpoints using the ContainerDecoder would incorrectly return a 500 (internal server error) status. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Diffstat (limited to 'runconfig')
-rw-r--r--runconfig/config.go17
-rw-r--r--runconfig/config_test.go37
-rw-r--r--runconfig/hostconfig.go3
3 files changed, 37 insertions, 20 deletions
diff --git a/runconfig/config.go b/runconfig/config.go
index 1b71b2042f..b25d1a8aa3 100644
--- a/runconfig/config.go
+++ b/runconfig/config.go
@@ -40,7 +40,7 @@ func (r ContainerDecoder) DecodeHostConfig(src io.Reader) (*container.HostConfig
// it's your business to do so
func decodeContainerConfig(src io.Reader, si *sysinfo.SysInfo) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
var w ContainerConfigWrapper
- if err := json.NewDecoder(src).Decode(&w); err != nil {
+ if err := loadJSON(src, &w); err != nil {
return nil, nil, nil, err
}
@@ -72,3 +72,18 @@ func decodeContainerConfig(src io.Reader, si *sysinfo.SysInfo) (*container.Confi
}
return w.Config, hc, w.NetworkingConfig, nil
}
+
+// loadJSON is similar to api/server/httputils.ReadJSON()
+func loadJSON(src io.Reader, out interface{}) error {
+ dec := json.NewDecoder(src)
+ if err := dec.Decode(&out); err != nil {
+ if err == io.EOF {
+ return validationError("invalid JSON: got EOF while reading request body")
+ }
+ return validationError("invalid JSON: " + err.Error())
+ }
+ if dec.More() {
+ return validationError("unexpected content after JSON")
+ }
+ return nil
+}
diff --git a/runconfig/config_test.go b/runconfig/config_test.go
index 5325f5a754..bbadcce297 100644
--- a/runconfig/config_test.go
+++ b/runconfig/config_test.go
@@ -42,27 +42,30 @@ func TestDecodeContainerConfig(t *testing.T) {
}
for _, f := range fixtures {
- b, err := os.ReadFile(f.file)
- if err != nil {
- t.Fatal(err)
- }
+ f := f
+ t.Run(f.file, func(t *testing.T) {
+ b, err := os.ReadFile(f.file)
+ if err != nil {
+ t.Fatal(err)
+ }
- c, h, _, err := decodeContainerConfig(bytes.NewReader(b), sysinfo.New())
- if err != nil {
- t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err))
- }
+ c, h, _, err := decodeContainerConfig(bytes.NewReader(b), sysinfo.New())
+ if err != nil {
+ t.Fatal(err)
+ }
- if c.Image != image {
- t.Fatalf("Expected %s image, found %s\n", image, c.Image)
- }
+ if c.Image != image {
+ t.Fatalf("Expected %s image, found %s", image, c.Image)
+ }
- if len(c.Entrypoint) != len(f.entrypoint) {
- t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint)
- }
+ if len(c.Entrypoint) != len(f.entrypoint) {
+ t.Fatalf("Expected %v, found %v", f.entrypoint, c.Entrypoint)
+ }
- if h != nil && h.Memory != 1000 {
- t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory)
- }
+ if h != nil && h.Memory != 1000 {
+ t.Fatalf("Expected memory to be 1000, found %d", h.Memory)
+ }
+ })
}
}
diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go
index 1d6266d5f7..9603a94eca 100644
--- a/runconfig/hostconfig.go
+++ b/runconfig/hostconfig.go
@@ -1,7 +1,6 @@
package runconfig // import "github.com/docker/docker/runconfig"
import (
- "encoding/json"
"io"
"strings"
@@ -12,7 +11,7 @@ import (
// It assumes the content of the reader will be JSON, and decodes it.
func decodeHostConfig(src io.Reader) (*container.HostConfig, error) {
var w ContainerConfigWrapper
- if err := json.NewDecoder(src).Decode(&w); err != nil {
+ if err := loadJSON(src, &w); err != nil {
return nil, err
}
return w.getHostConfig(), nil