2026-07-16 16:22:45 +08:00
|
|
|
package installer
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"math"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var ErrInvalidLimits = errors.New("invalid ZIP extraction limits")
|
|
|
|
|
|
|
|
|
|
const (
|
2026-07-18 15:40:44 +08:00
|
|
|
DefaultMaxEntries = 10_000
|
|
|
|
|
DefaultMaxArchiveBytes = int64(4 * 1024 * 1024 * 1024)
|
|
|
|
|
DefaultMaxCentralDirectoryBytes = int64(64 * 1024 * 1024)
|
|
|
|
|
DefaultMaxUncompressedBytes = int64(4 * 1024 * 1024 * 1024)
|
|
|
|
|
DefaultMaxCompressionRatio = 200.0
|
2026-07-16 16:22:45 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Limits bounds archive metadata and decompressed output.
|
|
|
|
|
type Limits struct {
|
2026-07-18 15:40:44 +08:00
|
|
|
MaxEntries int
|
|
|
|
|
MaxArchiveBytes int64
|
|
|
|
|
MaxCentralDirectoryBytes int64
|
|
|
|
|
MaxUncompressedBytes int64
|
|
|
|
|
MaxCompressionRatio float64
|
2026-07-16 16:22:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DefaultLimits() Limits {
|
|
|
|
|
return Limits{
|
2026-07-18 15:40:44 +08:00
|
|
|
MaxEntries: DefaultMaxEntries,
|
|
|
|
|
MaxArchiveBytes: DefaultMaxArchiveBytes,
|
|
|
|
|
MaxCentralDirectoryBytes: DefaultMaxCentralDirectoryBytes,
|
|
|
|
|
MaxUncompressedBytes: DefaultMaxUncompressedBytes,
|
|
|
|
|
MaxCompressionRatio: DefaultMaxCompressionRatio,
|
2026-07-16 16:22:45 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (limits Limits) validate() error {
|
|
|
|
|
if limits.MaxEntries <= 0 {
|
|
|
|
|
return fmt.Errorf("%w: MaxEntries must be positive", ErrInvalidLimits)
|
|
|
|
|
}
|
2026-07-18 15:40:44 +08:00
|
|
|
if limits.MaxArchiveBytes <= 0 {
|
|
|
|
|
return fmt.Errorf("%w: MaxArchiveBytes must be positive", ErrInvalidLimits)
|
|
|
|
|
}
|
|
|
|
|
if limits.MaxCentralDirectoryBytes <= 0 {
|
|
|
|
|
return fmt.Errorf("%w: MaxCentralDirectoryBytes must be positive", ErrInvalidLimits)
|
|
|
|
|
}
|
|
|
|
|
if limits.MaxCentralDirectoryBytes > limits.MaxArchiveBytes {
|
|
|
|
|
return fmt.Errorf("%w: MaxCentralDirectoryBytes exceeds MaxArchiveBytes", ErrInvalidLimits)
|
|
|
|
|
}
|
2026-07-16 16:22:45 +08:00
|
|
|
if limits.MaxUncompressedBytes <= 0 {
|
|
|
|
|
return fmt.Errorf("%w: MaxUncompressedBytes must be positive", ErrInvalidLimits)
|
|
|
|
|
}
|
|
|
|
|
if limits.MaxCompressionRatio <= 0 ||
|
|
|
|
|
math.IsNaN(limits.MaxCompressionRatio) ||
|
|
|
|
|
math.IsInf(limits.MaxCompressionRatio, 0) {
|
|
|
|
|
return fmt.Errorf("%w: MaxCompressionRatio must be finite and positive", ErrInvalidLimits)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|