From 940cc2420c64965e7f7b363cd8a9f3b7f10c84ec Mon Sep 17 00:00:00 2001 From: Go-Go-Farther Date: Mon, 20 Jun 2022 13:54:53 +0800 Subject: [PATCH] =?UTF-8?q?bugfix:=20=E4=BF=AE=E5=A4=8Dzip=E7=9A=84slip?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E9=98=B2=E6=AD=A2=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=81=B6=E6=84=8Fzip=EF=BC=8C=E5=A2=9E=E5=BC=BA=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E5=AE=89=E5=85=A8=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/BookModel.go | 2 ++ utils/ziptil/ziptil.go | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/models/BookModel.go b/models/BookModel.go index a64c6733..8d8aee47 100644 --- a/models/BookModel.go +++ b/models/BookModel.go @@ -699,6 +699,8 @@ func (book *Book) ImportBook(zipPath string, lang string) error { } //如果加压缩失败 if err := ziptil.Unzip(zipPath, tempPath); err != nil { + logs.Error("CAll ziptil.Unzip error, zipPath: %s, tempPath: %s, err: %v", + zipPath, tempPath, err) return err } //当导入结束后,删除临时文件 diff --git a/utils/ziptil/ziptil.go b/utils/ziptil/ziptil.go index f08c02bb..89be0771 100644 --- a/utils/ziptil/ziptil.go +++ b/utils/ziptil/ziptil.go @@ -2,6 +2,7 @@ package ziptil import ( "archive/zip" + "fmt" "io" "os" "path/filepath" @@ -13,7 +14,7 @@ import ( //@param dest 需要解压到的目录 //@return err 返回错误 func Unzip(zipFile, dest string) (err error) { - dest = strings.TrimSuffix(dest, "/") + "/" + dest = strings.TrimSuffix(dest, "/") + "/" // Make sure suffix with "/". // 打开一个zip格式文件 r, err := zip.OpenReader(zipFile) if err != nil { @@ -22,10 +23,26 @@ func Unzip(zipFile, dest string) (err error) { defer r.Close() // 迭代压缩文件中的文件,打印出文件中的内容 for _, f := range r.File { - if !f.FileInfo().IsDir() { //非目录,且不包含__MACOSX - if folder := dest + filepath.Dir(f.Name); !strings.Contains(folder, "__MACOSX") { - os.MkdirAll(folder, 0777) - if fcreate, err := os.Create(dest + strings.TrimPrefix(f.Name, "./")); err == nil { + if !f.FileInfo().IsDir() { + path := filepath.Join(dest, f.Name) + + // logs.Debug("file name: ", f.Name, ",dest:", dest, + // ",absolute path: ", filepath.Join(dest, f.Name), + // ",absolute dir: ", filepath.Dir(path), + // ",relative dir: ", filepath.Dir(f.Name)) + + if dir := filepath.Dir(path); !strings.Contains(dir, "__MACOSX") { + // This branch : 非目录,且不包含__MACOSX目录 + + /* Resolve the Zip Slip problem.(Solution: The decompressed file must be in the DEST directory.) + References: https://github.com/golang/go/issues/25849 + https://github.com/mholt/archiver/blob/e4ef56d48eb029648b0e895bb0b6a393ef0829c3/archiver.go#L110-L119 */ + if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { + return fmt.Errorf("illegal file path: %s", path) + } + + os.MkdirAll(dir, 0777) + if fcreate, err := os.Create(path); err == nil { if rc, err := f.Open(); err == nil { io.Copy(fcreate, rc) rc.Close() //不要用defer来关闭,如果文件太多的话,会报too many open files 的错误