fix: reject invalid 'm' suffix in byte size parsing

Rename parseQuantityOrInt64 to parseByteSizeOrInt64 and improve error
handling for invalid byte size quantities. Now properly rejects 'm'
(milli) suffix with a helpful message suggesting IEC values (Ki, Mi, Gi).

Also fixes misleading "too large" error for sub-byte quantities.

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
pull/30743/head
Benoit Tigeot 2 months ago
parent 34799006ee
commit 892bdf95a9
No known key found for this signature in database
GPG Key ID: 8E6D4FC8AEBDA62C

@ -222,9 +222,9 @@ func envFloat32Or(name string, def float32) float32 {
return float32(ret)
}
// parseQuantityOrInt64 parses a string as either a Kubernetes Quantity or plain int64.
// Returns the parsed value and an error if parsing fails.
func parseQuantityOrInt64(s string) (int64, error) {
// parseByteSizeOrInt64 parses a string as either a Kubernetes Quantity or plain int64,
// specifically for byte sizes. Returns the parsed value in bytes
func parseByteSizeOrInt64(s string) (int64, error) {
s = strings.TrimSpace(s)
// Try parsing as Kubernetes Quantity first
@ -233,10 +233,19 @@ func parseQuantityOrInt64(s string) (int64, error) {
return v, nil
}
f := q.AsApproximateFloat64()
if f > 0 && f < float64(^uint64(0)>>1) {
return int64(f), nil
// Reject quantities that evaluate to less than 1 byte (e.g. "1m" -> 0.001)
// because file sizes must be whole bytes. Treat those as parsing errors.
if f < 1 {
// Provide a helpful message if the user tried to use "m" (milli) suffix
if strings.HasSuffix(strings.ToLower(s), "m") && !strings.HasSuffix(s, "M") {
return 0, fmt.Errorf("quantity %q uses 'm' (milli) suffix which represents 0.001; please use IEC values like Ki, Mi, Gi", s)
}
return 0, fmt.Errorf("quantity %q is too small (less than 1 byte)", s)
}
return 0, fmt.Errorf("quantity %q is too large to fit in int64", s)
if f >= float64(^uint64(0)>>1) {
return 0, fmt.Errorf("quantity %q is too large to fit in int64", s)
}
return int64(f), nil
}
// Fallback to plain int64
@ -257,7 +266,7 @@ func envInt64OrQuantityBytes(name string, def int64) int64 {
return def
}
v, err := parseQuantityOrInt64(envVal)
v, err := parseByteSizeOrInt64(envVal)
if err != nil {
defQuantity := resource.NewQuantity(def, resource.BinarySI)
slog.Warn(err.Error() + fmt.Sprintf(": using default %s", defQuantity.String()))
@ -278,7 +287,7 @@ func NewQuantityBytesValue(p *int64) *QuantityBytesValue {
// Set parses the input string as either a Kubernetes Quantity or plain int64
func (q *QuantityBytesValue) Set(s string) error {
v, err := parseQuantityOrInt64(s)
v, err := parseByteSizeOrInt64(s)
if err != nil {
return err
}

@ -325,6 +325,27 @@ func TestEnvInt64OrQuantityBytes(t *testing.T) {
def: 100,
expected: 100, // Returns default but prints error about uppercase requirement
},
{
name: "suffix Mb rejected",
env: envName,
val: "1000Mb",
def: 100,
expected: 100, // Returns default but prints error about 'Mb' being invalid
},
{
name: "suffix mo rejected",
env: envName,
val: "1000mo",
def: 100,
expected: 100, // Returns default but prints error about 'mo' being invalid
},
{
name: "suffix m rejected (milli)",
env: envName,
val: "10m",
def: 100,
expected: 100, // Returns default but prints error about 'm' being invalid
},
{
name: "whitespace trimmed",
env: envName,
@ -391,6 +412,16 @@ func TestQuantityBytesValue(t *testing.T) {
input: "not-a-number",
expectError: true,
},
{
name: "Mb suffix rejected",
input: "1Mb",
expectError: true,
},
{
name: "m suffix rejected",
input: "1m",
expectError: true,
},
}
for _, tt := range tests {

Loading…
Cancel
Save