in zip/zip.go [386:474]
func checkZip(m module.Version, f *os.File) (*zip.Reader, CheckedFiles, error) {
// Make sure the module path and version are valid.
if vers := module.CanonicalVersion(m.Version); vers != m.Version {
return nil, CheckedFiles{}, fmt.Errorf("version %q is not canonical (should be %q)", m.Version, vers)
}
if err := module.Check(m.Path, m.Version); err != nil {
return nil, CheckedFiles{}, err
}
// Check the total file size.
info, err := f.Stat()
if err != nil {
return nil, CheckedFiles{}, err
}
zipSize := info.Size()
if zipSize > MaxZipFile {
cf := CheckedFiles{SizeError: fmt.Errorf("module zip file is too large (%d bytes; limit is %d bytes)", zipSize, MaxZipFile)}
return nil, cf, cf.Err()
}
// Check for valid file names, collisions.
var cf CheckedFiles
addError := func(zf *zip.File, err error) {
cf.Invalid = append(cf.Invalid, FileError{Path: zf.Name, Err: err})
}
z, err := zip.NewReader(f, zipSize)
if err != nil {
return nil, CheckedFiles{}, err
}
prefix := fmt.Sprintf("%s@%s/", m.Path, m.Version)
collisions := make(collisionChecker)
var size int64
for _, zf := range z.File {
if !strings.HasPrefix(zf.Name, prefix) {
addError(zf, fmt.Errorf("path does not have prefix %q", prefix))
continue
}
name := zf.Name[len(prefix):]
if name == "" {
continue
}
isDir := strings.HasSuffix(name, "/")
if isDir {
name = name[:len(name)-1]
}
if path.Clean(name) != name {
addError(zf, errPathNotClean)
continue
}
if err := module.CheckFilePath(name); err != nil {
addError(zf, err)
continue
}
if err := collisions.check(name, isDir); err != nil {
addError(zf, err)
continue
}
if isDir {
continue
}
if base := path.Base(name); strings.EqualFold(base, "go.mod") {
if base != name {
addError(zf, fmt.Errorf("go.mod file not in module root directory"))
continue
}
if name != "go.mod" {
addError(zf, errGoModCase)
continue
}
}
sz := int64(zf.UncompressedSize64)
if sz >= 0 && MaxZipFile-size >= sz {
size += sz
} else if cf.SizeError == nil {
cf.SizeError = fmt.Errorf("total uncompressed size of module contents too large (max size is %d bytes)", MaxZipFile)
}
if name == "go.mod" && sz > MaxGoMod {
addError(zf, fmt.Errorf("go.mod file too large (max size is %d bytes)", MaxGoMod))
continue
}
if name == "LICENSE" && sz > MaxLICENSE {
addError(zf, fmt.Errorf("LICENSE file too large (max size is %d bytes)", MaxLICENSE))
continue
}
cf.Valid = append(cf.Valid, zf.Name)
}
return z, cf, cf.Err()
}