Skip to content

Commit 1f3eab8

Browse files
authored
Merge pull request moby#5107 from tonistiigi/json-decoder-fix
fix incorrect usage of json.NewDecoder
2 parents 74c6f57 + f8bc2e0 commit 1f3eab8

File tree

5 files changed

+92
-2
lines changed

5 files changed

+92
-2
lines changed

cache/remotecache/s3/s3.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ func (s3Client *s3Client) getManifest(ctx context.Context, key string, config *v
408408
if err := decoder.Decode(config); err != nil {
409409
return false, errors.WithStack(err)
410410
}
411+
if _, err := decoder.Token(); !errors.Is(err, io.EOF) {
412+
return false, errors.Errorf("unexpected data after JSON object")
413+
}
411414

412415
return true, nil
413416
}

executor/runcexecutor/executor.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,9 +422,13 @@ func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.Pro
422422
defer f.Close()
423423

424424
spec := &specs.Spec{}
425-
if err := json.NewDecoder(f).Decode(spec); err != nil {
425+
dec := json.NewDecoder(f)
426+
if err := dec.Decode(spec); err != nil {
426427
return err
427428
}
429+
if _, err := dec.Token(); !errors.Is(err, io.EOF) {
430+
return errors.Errorf("unexpected data after JSON spec object")
431+
}
428432

429433
if process.Meta.User != "" {
430434
uid, gid, sgids, err := oci.GetUser(state.Rootfs, process.Meta.User)

exporter/attestation/unbundle.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package attestation
33
import (
44
"context"
55
"encoding/json"
6+
"io"
67
"os"
78
"path"
89
"strings"
@@ -141,6 +142,9 @@ func unbundle(root string, bundle exporter.Attestation) ([]exporter.Attestation,
141142
if err := dec.Decode(&stmt); err != nil {
142143
return nil, errors.Wrap(err, "cannot decode in-toto statement")
143144
}
145+
if _, err := dec.Token(); !errors.Is(err, io.EOF) {
146+
return nil, errors.New("in-toto statement is not a single JSON object")
147+
}
144148
if bundle.InToto.PredicateType != "" && stmt.PredicateType != bundle.InToto.PredicateType {
145149
return nil, errors.Errorf("bundle entry %s does not match required predicate type %s", stmt.PredicateType, bundle.InToto.PredicateType)
146150
}

frontend/dockerfile/dockerfile_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ var allTests = integration.TestFuncs(
185185
testFrontendDeduplicateSources,
186186
testDuplicateLayersProvenance,
187187
testSourcePolicyWithNamedContext,
188+
testInvalidJSONCommands,
188189
)
189190

190191
// Tests that depend on the `security.*` entitlements
@@ -2053,6 +2054,84 @@ ENTRYPOINT my entrypoint
20532054
require.Equal(t, []string{"ls", "my entrypoint"}, ociimg.Config.Entrypoint)
20542055
}
20552056

2057+
func testInvalidJSONCommands(t *testing.T, sb integration.Sandbox) {
2058+
integration.SkipOnPlatform(t, "windows")
2059+
f := getFrontend(t, sb)
2060+
2061+
dockerfile := []byte(`
2062+
FROM alpine
2063+
RUN ["echo", "hello"]this is invalid
2064+
`)
2065+
2066+
dir := integration.Tmpdir(
2067+
t,
2068+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
2069+
)
2070+
2071+
c, err := client.New(sb.Context(), sb.Address())
2072+
require.NoError(t, err)
2073+
defer c.Close()
2074+
2075+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
2076+
LocalMounts: map[string]fsutil.FS{
2077+
dockerui.DefaultLocalNameDockerfile: dir,
2078+
dockerui.DefaultLocalNameContext: dir,
2079+
},
2080+
}, nil)
2081+
require.Error(t, err)
2082+
require.Contains(t, err.Error(), "this is invalid")
2083+
2084+
workers.CheckFeatureCompat(t, sb,
2085+
workers.FeatureDirectPush,
2086+
)
2087+
2088+
registry, err := sb.NewRegistry()
2089+
if errors.Is(err, integration.ErrRequirements) {
2090+
t.Skip(err.Error())
2091+
}
2092+
require.NoError(t, err)
2093+
2094+
target := registry + "/buildkit/testexportdf:multi"
2095+
2096+
dockerfile = []byte(`
2097+
FROM alpine
2098+
ENTRYPOINT []random string
2099+
`)
2100+
2101+
dir = integration.Tmpdir(
2102+
t,
2103+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
2104+
)
2105+
2106+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
2107+
Exports: []client.ExportEntry{
2108+
{
2109+
Type: client.ExporterImage,
2110+
Attrs: map[string]string{
2111+
"name": target,
2112+
"push": "true",
2113+
},
2114+
},
2115+
},
2116+
LocalMounts: map[string]fsutil.FS{
2117+
dockerui.DefaultLocalNameDockerfile: dir,
2118+
dockerui.DefaultLocalNameContext: dir,
2119+
},
2120+
}, nil)
2121+
require.NoError(t, err)
2122+
2123+
desc, provider, err := contentutil.ProviderFromRef(target)
2124+
require.NoError(t, err)
2125+
2126+
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
2127+
require.NoError(t, err)
2128+
2129+
require.Len(t, imgs.Images, 1)
2130+
img := imgs.Images[0].Img
2131+
2132+
require.Equal(t, []string{"/bin/sh", "-c", "[]random string"}, img.Config.Entrypoint)
2133+
}
2134+
20562135
func testPullScratch(t *testing.T, sb integration.Sandbox) {
20572136
integration.SkipOnPlatform(t, "windows")
20582137
f := getFrontend(t, sb)

frontend/dockerfile/parser/line_parsers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func parseJSON(rest string) (*Node, map[string]bool, error) {
282282
}
283283

284284
var myJSON []interface{}
285-
if err := json.NewDecoder(strings.NewReader(rest)).Decode(&myJSON); err != nil {
285+
if err := json.Unmarshal([]byte(rest), &myJSON); err != nil {
286286
return nil, nil, err
287287
}
288288

0 commit comments

Comments
 (0)