@@ -11,12 +11,25 @@ import (
11
11
12
12
// untar is a shared helper for untarring an archive. The reader should provide
13
13
// an uncompressed view of the tar archive.
14
- func untar (input io.Reader , dst , src string , dir bool , umask os.FileMode ) error {
14
+ func untar (input io.Reader , dst , src string , dir bool , umask os.FileMode , fileSizeLimit int64 , filesLimit int ) error {
15
15
tarR := tar .NewReader (input )
16
16
done := false
17
17
dirHdrs := []* tar.Header {}
18
18
now := time .Now ()
19
+
20
+ var (
21
+ fileSize int64
22
+ filesCount int
23
+ )
24
+
19
25
for {
26
+ if filesLimit > 0 {
27
+ filesCount ++
28
+ if filesCount > filesLimit {
29
+ return fmt .Errorf ("tar archive contains too many files: %d > %d" , filesCount , filesLimit )
30
+ }
31
+ }
32
+
20
33
hdr , err := tarR .Next ()
21
34
if err == io .EOF {
22
35
if ! done {
@@ -45,7 +58,15 @@ func untar(input io.Reader, dst, src string, dir bool, umask os.FileMode) error
45
58
path = filepath .Join (path , hdr .Name )
46
59
}
47
60
48
- if hdr .FileInfo ().IsDir () {
61
+ fileInfo := hdr .FileInfo ()
62
+
63
+ fileSize += fileInfo .Size ()
64
+
65
+ if fileSizeLimit > 0 && fileSize > fileSizeLimit {
66
+ return fmt .Errorf ("tar archive larger than limit: %d" , fileSizeLimit )
67
+ }
68
+
69
+ if fileInfo .IsDir () {
49
70
if ! dir {
50
71
return fmt .Errorf ("expected a single file: %s" , src )
51
72
}
@@ -81,8 +102,8 @@ func untar(input io.Reader, dst, src string, dir bool, umask os.FileMode) error
81
102
// Mark that we're done so future in single file mode errors
82
103
done = true
83
104
84
- // Open the file for writing
85
- err = copyReader (path , tarR , hdr .FileInfo ().Mode (), umask )
105
+ // Size limit is tracked using the returned file info.
106
+ err = copyReader (path , tarR , hdr .FileInfo ().Mode (), umask , 0 )
86
107
if err != nil {
87
108
return err
88
109
}
@@ -127,7 +148,19 @@ func untar(input io.Reader, dst, src string, dir bool, umask os.FileMode) error
127
148
128
149
// TarDecompressor is an implementation of Decompressor that can
129
150
// unpack tar files.
130
- type TarDecompressor struct {}
151
+ type TarDecompressor struct {
152
+ // FileSizeLimit limits the total size of all
153
+ // decompressed files.
154
+ //
155
+ // The zero value means no limit.
156
+ FileSizeLimit int64
157
+
158
+ // FilesLimit limits the number of files that are
159
+ // allowed to be decompressed.
160
+ //
161
+ // The zero value means no limit.
162
+ FilesLimit int
163
+ }
131
164
132
165
func (d * TarDecompressor ) Decompress (dst , src string , dir bool , umask os.FileMode ) error {
133
166
// If we're going into a directory we should make that first
@@ -146,5 +179,5 @@ func (d *TarDecompressor) Decompress(dst, src string, dir bool, umask os.FileMod
146
179
}
147
180
defer f .Close ()
148
181
149
- return untar (f , dst , src , dir , umask )
182
+ return untar (f , dst , src , dir , umask , d . FileSizeLimit , d . FilesLimit )
150
183
}
0 commit comments