Skip to content

Commit 80518e2

Browse files
committed
dockerfile: fix invalid usage of json.NewDecoder
Unmarshal is faster and uses less memory anyway for small static values. This allowed invalid RUN commands in JSON format to pass when skipping bogus content and metadata commands to set the partial JSON value and skip the rest. Signed-off-by: Tonis Tiigi <[email protected]>
1 parent a08a9b6 commit 80518e2

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

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)