Skip to content

Commit c615a79

Browse files
committed
Add some limits to os-features
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 3a284c1 commit c615a79

2 files changed

Lines changed: 31 additions & 7 deletions

File tree

platforms.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ var (
127127
osRe = regexp.MustCompile(`^([A-Za-z0-9_-]+)(?:\(([A-Za-z0-9_.%-]*)((?:\+[A-Za-z0-9_.%-]+)*)\))?$`)
128128
)
129129

130+
const (
131+
maxFeatures = 16
132+
maxFeatureLen = 64
133+
maxOSOptionsLen = 256
134+
)
135+
130136
// Platform is a type alias for convenience, so there is no need to import image-spec package everywhere.
131137
type Platform = specs.Platform
132138

@@ -352,13 +358,22 @@ func parseOSFeatures(s string) ([]string, error) {
352358
if s == "" {
353359
return nil, nil
354360
}
361+
if len(s) > maxOSOptionsLen {
362+
return nil, fmt.Errorf("os features too long: %w", errInvalidArgument)
363+
}
355364

356-
var features []string
365+
features := make([]string, 0, min(strings.Count(s, "+")+1, maxFeatures))
357366
for raw := range strings.SplitSeq(s, "+") {
358367
raw = strings.TrimSpace(raw)
359368
if raw == "" {
360369
return nil, fmt.Errorf("empty os feature: %w", errInvalidArgument)
361370
}
371+
if len(features) == maxFeatures {
372+
return nil, fmt.Errorf("too many os features: %w", errInvalidArgument)
373+
}
374+
if len(raw) > maxFeatureLen {
375+
return nil, fmt.Errorf("os feature too long: %w", errInvalidArgument)
376+
}
362377
feature, err := decodeOSOption(raw)
363378
if err != nil {
364379
return nil, fmt.Errorf("invalid os feature %q: %w", raw, err)
@@ -422,7 +437,7 @@ func FormatAll(platform specs.Platform) string {
422437
}
423438

424439
func formatOSFeatures(features []string) string {
425-
if len(features) == 0 {
440+
if len(features) == 0 || len(features) > maxFeatures {
426441
return ""
427442
}
428443

@@ -434,15 +449,28 @@ func formatOSFeatures(features []string) string {
434449
var wrote bool
435450
var prev string
436451
for _, f := range features {
452+
if len(f) > maxFeatureLen {
453+
// invalid
454+
return ""
455+
}
437456
if f == "" || f == prev {
438457
// skip empty and duplicate values
439458
continue
440459
}
441460
prev = f
461+
462+
encoded := encodeOSOption(f)
463+
if b.Len()+len(encoded) > maxOSOptionsLen {
464+
return ""
465+
}
466+
442467
if wrote {
468+
if b.Len()+1 > maxOSOptionsLen {
469+
return ""
470+
}
443471
b.WriteByte('+')
444472
}
445-
b.WriteString(encodeOSOption(f))
473+
b.WriteString(encoded)
446474
wrote = true
447475
}
448476
return b.String()

platforms_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,6 @@ func FuzzPlatformsParse(f *testing.F) {
605605
}
606606

607607
func BenchmarkParseOSOptions(b *testing.B) {
608-
maxFeatures := 16
609-
610608
benchmarks := []struct {
611609
doc string
612610
input string
@@ -641,8 +639,6 @@ func BenchmarkParseOSOptions(b *testing.B) {
641639
}
642640

643641
func BenchmarkFormatAllOSFeatures(b *testing.B) {
644-
maxFeatures := 16
645-
646642
benchmarks := []struct {
647643
doc string
648644
platform specs.Platform

0 commit comments

Comments
 (0)