diff --git a/client/client_test.go b/client/client_test.go index 4bdc9c1c9..bfb457624 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -43,6 +43,7 @@ func TestClientIntegration(t *testing.T) { testWhiteoutParentDir, testDuplicateWhiteouts, testSchema1Image, + testMountWithNoSource, }) } @@ -705,6 +706,37 @@ func testSchema1Image(t *testing.T, sb integration.Sandbox) { checkAllReleasable(t, c, sb, true) } +// #319 +func testMountWithNoSource(t *testing.T, sb integration.Sandbox) { + t.Parallel() + c, err := New(sb.Address()) + require.NoError(t, err) + defer c.Close() + + busybox := llb.Image("docker.io/library/busybox:latest") + st := llb.Scratch() + + var nilState llb.State + + // This should never actually be run, but we want to succeed + // if it was, because we expect an error below, or a daemon + // panic if the issue has regressed. + run := busybox.Run( + llb.Args([]string{"/bin/true"}), + llb.AddMount("/nil", nilState, llb.SourcePath("/"), llb.Readonly)) + + st = run.AddMount("/mnt", st) + + def, err := st.Marshal() + require.NoError(t, err) + + err = c.Solve(context.TODO(), def, SolveOpt{}, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "has no input") + + checkAllReleasable(t, c, sb, true) +} + func requiresLinux(t *testing.T) { if runtime.GOOS != "linux" { t.Skipf("unsupported GOOS: %s", runtime.GOOS) diff --git a/executor/oci/spec_unix.go b/executor/oci/spec_unix.go index 028e88892..ba7aa79d9 100644 --- a/executor/oci/spec_unix.go +++ b/executor/oci/spec_unix.go @@ -50,6 +50,9 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou sm := &submounts{} for _, m := range mounts { + if m.Src == nil { + return nil, nil, errors.Errorf("mount %s has no source", m.Dest) + } mounts, err := m.Src.Mount(ctx, m.Readonly) if err != nil { sm.cleanup() diff --git a/solver/llbop/exec.go b/solver/llbop/exec.go index 2b3fc2908..2e38924e0 100644 --- a/solver/llbop/exec.go +++ b/solver/llbop/exec.go @@ -95,6 +95,11 @@ func (e *execOp) Run(ctx context.Context, inputs []solver.Ref) ([]solver.Ref, er mountable = active } } + + if mountable == nil { + return nil, errors.Errorf("mount %s has no input", m.Dest) + } + if m.Dest == pb.RootMount { root = mountable } else {