Skip to content

Commit 96663dd

Browse files
committed
exporter: add validation for platforms key value
Signed-off-by: Tonis Tiigi <[email protected]> (cherry picked from commit 432ece72ae124ce8a29ced6854a08206f09f3a73) (cherry picked from commit e4bd60baf77b4ec92aba60f568831fb3076fc158)
1 parent 481d9c4 commit 96663dd

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

client/client_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ func TestIntegration(t *testing.T) {
208208
testExportLocalNoPlatformSplitOverwrite,
209209
testValidateNullConfig,
210210
testValidateInvalidConfig,
211+
testValidatePlatformsEmpty,
212+
testValidatePlatformsInvalid,
211213
)
212214
}
213215

client/validation_test.go

+108
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/moby/buildkit/client/llb"
10+
"github.com/moby/buildkit/exporter/containerimage/exptypes"
1011
"github.com/moby/buildkit/frontend/gateway/client"
1112
"github.com/moby/buildkit/util/testutil/integration"
1213
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -96,3 +97,110 @@ func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) {
9697
require.Error(t, err)
9798
require.Contains(t, err.Error(), "invalid image config for export: missing os")
9899
}
100+
101+
func testValidatePlatformsEmpty(t *testing.T, sb integration.Sandbox) {
102+
requiresLinux(t)
103+
104+
ctx := sb.Context()
105+
106+
c, err := New(ctx, sb.Address())
107+
require.NoError(t, err)
108+
defer c.Close()
109+
110+
b := func(ctx context.Context, c client.Client) (*client.Result, error) {
111+
def, err := llb.Scratch().Marshal(ctx)
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
res, err := c.Solve(ctx, client.SolveRequest{
117+
Evaluate: true,
118+
Definition: def.ToPB(),
119+
})
120+
if err != nil {
121+
return nil, err
122+
}
123+
res.AddMeta("refs.platforms", []byte("null"))
124+
return res, nil
125+
}
126+
127+
_, err = c.Build(ctx, SolveOpt{
128+
Exports: []ExportEntry{
129+
{
130+
Type: ExporterOCI,
131+
Output: fixedWriteCloser(nopWriteCloser{io.Discard}),
132+
},
133+
},
134+
}, "", b, nil)
135+
require.Error(t, err)
136+
require.Contains(t, err.Error(), "invalid empty platforms index for exporter")
137+
}
138+
139+
func testValidatePlatformsInvalid(t *testing.T, sb integration.Sandbox) {
140+
requiresLinux(t)
141+
142+
ctx := sb.Context()
143+
144+
c, err := New(ctx, sb.Address())
145+
require.NoError(t, err)
146+
defer c.Close()
147+
148+
tcases := []struct {
149+
name string
150+
value []exptypes.Platform
151+
exp string
152+
}{
153+
{
154+
name: "emptyID",
155+
value: []exptypes.Platform{{}},
156+
exp: "invalid empty platform key for exporter",
157+
},
158+
{
159+
name: "missingOS",
160+
value: []exptypes.Platform{
161+
{
162+
ID: "foo",
163+
},
164+
},
165+
exp: "invalid platform value",
166+
},
167+
}
168+
169+
for _, tc := range tcases {
170+
t.Run(tc.name, func(t *testing.T) {
171+
b := func(ctx context.Context, c client.Client) (*client.Result, error) {
172+
def, err := llb.Scratch().Marshal(ctx)
173+
if err != nil {
174+
return nil, err
175+
}
176+
177+
res, err := c.Solve(ctx, client.SolveRequest{
178+
Evaluate: true,
179+
Definition: def.ToPB(),
180+
})
181+
if err != nil {
182+
return nil, err
183+
}
184+
185+
dt, err := json.Marshal(exptypes.Platforms{Platforms: tc.value})
186+
if err != nil {
187+
return nil, err
188+
}
189+
190+
res.AddMeta("refs.platforms", dt)
191+
return res, nil
192+
}
193+
194+
_, err = c.Build(ctx, SolveOpt{
195+
Exports: []ExportEntry{
196+
{
197+
Type: ExporterOCI,
198+
Output: fixedWriteCloser(nopWriteCloser{io.Discard}),
199+
},
200+
},
201+
}, "", b, nil)
202+
require.Error(t, err)
203+
require.Contains(t, err.Error(), tc.exp)
204+
})
205+
}
206+
}

exporter/containerimage/exptypes/parse.go

+14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
1717
return Platforms{}, errors.Wrapf(err, "failed to parse platforms passed to provenance processor")
1818
}
1919
}
20+
if len(ps.Platforms) == 0 {
21+
return Platforms{}, errors.Errorf("invalid empty platforms index for exporter")
22+
}
23+
for i, p := range ps.Platforms {
24+
if p.ID == "" {
25+
return Platforms{}, errors.Errorf("invalid empty platform key for exporter")
26+
}
27+
if p.Platform.OS == "" || p.Platform.Architecture == "" {
28+
return Platforms{}, errors.Errorf("invalid platform value %v for exporter", p.Platform)
29+
}
30+
ps.Platforms[i].Platform = platforms.Normalize(p.Platform)
31+
}
2032
return ps, nil
2133
}
2234

@@ -36,6 +48,8 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
3648
OSFeatures: img.OSFeatures,
3749
Variant: img.Variant,
3850
}
51+
} else if img.OS != "" || img.Architecture != "" {
52+
return Platforms{}, errors.Errorf("invalid image config: os and architecture must be specified together")
3953
}
4054
}
4155
p = platforms.Normalize(p)

0 commit comments

Comments
 (0)