easy way to unzip file with golang

后端 未结 8 761
情话喂你
情话喂你 2021-02-01 03:45

is there a easy way to unzip file with golang ?

right now my code is:

func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err !         


        
8条回答
  •  生来不讨喜
    2021-02-01 04:13

    While working on the query for catching ZipSlip vulnerabilities in Go on LGTM.com (of which I am a developer), I noticed code similar to the accepted answer in several projects, e.g. rclone.

    As @woogoo has pointed out, this code is vulnerable to ZipSlip, so I believe the answer should be updated to something like the following (code taken from rclone fix):

    func Unzip(src, dest string) error {
        dest = filepath.Clean(dest) + string(os.PathSeparator)
    
        r, err := zip.OpenReader(src)
        if err != nil {
            return err
        }
        defer func() {
            if err := r.Close(); err != nil {
                panic(err)
            }
        }()
    
        os.MkdirAll(dest, 0755)
    
        // Closure to address file descriptors issue with all the deferred .Close() methods
        extractAndWriteFile := func(f *zip.File) error {
            path := filepath.Join(dest, f.Name)
            // Check for ZipSlip: https://snyk.io/research/zip-slip-vulnerability
            if !strings.HasPrefix(path, dest) {
                return fmt.Errorf("%s: illegal file path", path)
            }
    
            rc, err := f.Open()
            if err != nil {
                return err
            }
            defer func() {
                if err := rc.Close(); err != nil {
                    panic(err)
                }
            }()
    
            if f.FileInfo().IsDir() {
                os.MkdirAll(path, f.Mode())
            } else {
                os.MkdirAll(filepath.Dir(path), f.Mode())
                f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
                if err != nil {
                    return err
                }
                defer func() {
                    if err := f.Close(); err != nil {
                        panic(err)
                    }
                }()
    
                _, err = io.Copy(f, rc)
                if err != nil {
                    return err
                }
            }
            return nil
        }
    
        for _, f := range r.File {
            err := extractAndWriteFile(f)
            if err != nil {
                return err
            }
        }
    
        return nil
    }
    

提交回复
热议问题