@@ -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.
131137type 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
424439func 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 ()
0 commit comments