Merge pull request #199 from thaJeztah/18.09_backport_fix_panic_on_empty_dockerfile

[18.09 backport] fix panic on empty dockerfile
This commit is contained in:
Andrew Hsu 2019-06-18 09:49:05 -07:00 committed by GitHub
commit 70399c41d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 5 deletions

View file

@ -12,6 +12,7 @@ import (
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerignore"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/urlutil"
"github.com/moby/buildkit/frontend/dockerfile/parser"
@ -34,8 +35,9 @@ func Detect(config backend.BuildConfig) (remote builder.Source, dockerfile *pars
case remoteURL == ClientSessionRemote:
res, err := parser.Parse(config.Source)
if err != nil {
return nil, nil, err
return nil, nil, errdefs.InvalidParameter(err)
}
return nil, res, nil
case urlutil.IsGitURL(remoteURL):
remote, dockerfile, err = newGitRemote(remoteURL, dockerfilePath)
@ -106,7 +108,7 @@ func newURLRemote(url string, dockerfilePath string, progressReader func(in io.R
switch contentType {
case mimeTypes.TextPlain:
res, err := parser.Parse(progressReader(content))
return nil, res, err
return nil, res, errdefs.InvalidParameter(err)
default:
source, err := FromArchive(progressReader(content))
if err != nil {
@ -146,11 +148,17 @@ func readAndParseDockerfile(name string, rc io.Reader) (*parser.Result, error) {
br := bufio.NewReader(rc)
if _, err := br.Peek(1); err != nil {
if err == io.EOF {
return nil, errors.Errorf("the Dockerfile (%s) cannot be empty", name)
return nil, errdefs.InvalidParameter(errors.Errorf("the Dockerfile (%s) cannot be empty", name))
}
return nil, errors.Wrap(err, "unexpected error reading Dockerfile")
}
return parser.Parse(br)
dockerfile, err := parser.Parse(br)
if err != nil {
return nil, errdefs.InvalidParameter(errors.Wrapf(err, "failed to parse %s", name))
}
return dockerfile, nil
}
func openAt(remote builder.Source, path string) (driver.File, error) {

View file

@ -474,6 +474,61 @@ RUN for g in $(seq 0 8); do dd if=/dev/urandom of=rnd bs=1K count=1 seek=$((1024
assert.Check(t, is.Contains(out.String(), "Successfully built"))
}
func TestBuildWithEmptyDockerfile(t *testing.T) {
ctx := context.TODO()
defer setupTest(t)()
tests := []struct {
name string
dockerfile string
expectedErr string
}{
{
name: "empty-dockerfile",
dockerfile: "",
expectedErr: "cannot be empty",
},
{
name: "empty-lines-dockerfile",
dockerfile: `
`,
expectedErr: "file with no instructions",
},
{
name: "comment-only-dockerfile",
dockerfile: `# this is a comment`,
expectedErr: "file with no instructions",
},
}
apiclient := testEnv.APIClient()
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
buf := bytes.NewBuffer(nil)
w := tar.NewWriter(buf)
writeTarRecord(t, w, "Dockerfile", tc.dockerfile)
err := w.Close()
assert.NilError(t, err)
_, err = apiclient.ImageBuild(ctx,
buf,
types.ImageBuildOptions{
Remove: true,
ForceRemove: true,
})
assert.Check(t, is.Contains(err.Error(), tc.expectedErr))
})
}
}
func writeTarRecord(t *testing.T, w *tar.Writer, fn, contents string) {
err := w.WriteHeader(&tar.Header{
Name: fn,

View file

@ -26,7 +26,7 @@ github.com/imdario/mergo v0.3.6
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
# buildkit
github.com/moby/buildkit ed4da8b4a9661f278ae8433056ca37d0727c408b # docker-18.09 branch
github.com/moby/buildkit 05766c5c21a1e528eeb1c3522b2f05493fe9ac47 # docker-18.09 branch
github.com/tonistiigi/fsutil 2862f6bc5ac9b97124e552a5c108230b38a1b0ca
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7

View file

@ -275,6 +275,11 @@ func Parse(rwc io.Reader) (*Result, error) {
if len(warnings) > 0 {
warnings = append(warnings, "[WARNING]: Empty continuation lines will become errors in a future release.")
}
if root.StartLine < 0 {
return nil, errors.New("file with no instructions.")
}
return &Result{
AST: root,
Warnings: warnings,