mirror of
https://github.com/vbatts/tar-split.git
synced 2025-07-03 06:48:29 +00:00
archive/tar: fix issues with readGNUSparseMap1x0
Motivations: * Use of strconv.ParseInt does not properly treat integers as 64bit, preventing this function from working properly on 32bit machines. * Use of io.ReadFull does not properly detect truncated streams when the file suddenly ends on a block boundary. * The function blindly trusts user input for numEntries and allocates memory accordingly. * The function does not validate that numEntries is not negative, allowing a malicious sparse file to cause a panic during make. In general, this function was overly complicated for what it was accomplishing and it was hard to reason that it was free from bounds errors. Instead, it has been rewritten and relies on bytes.Buffer.ReadString to do the main work. So long as invariants about the number of '\n' in the buffer are maintained, it is much easier to see why this approach is correct. Change-Id: Ibb12c4126c26e0ea460ea063cd17af68e3cf609e Reviewed-on: https://go-review.googlesource.com/15174 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
7500c932c7
commit
b598ba3ee7
4 changed files with 254 additions and 143 deletions
|
@ -298,9 +298,7 @@ var untarTests = []*untarTest{
|
|||
},
|
||||
{
|
||||
file: "testdata/issue11169.tar",
|
||||
// TODO(dsnet): Currently the library does not detect that this file is
|
||||
// malformed. Instead it incorrectly believes that file just ends.
|
||||
// err: ErrHeader,
|
||||
err: ErrHeader,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -983,3 +981,55 @@ func TestReadHeaderOnly(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAXRecord(t *testing.T) {
|
||||
var medName = strings.Repeat("CD", 50)
|
||||
var longName = strings.Repeat("AB", 100)
|
||||
|
||||
var vectors = []struct {
|
||||
input string
|
||||
residual string
|
||||
outputKey string
|
||||
outputVal string
|
||||
ok bool
|
||||
}{
|
||||
{"6 k=v\n\n", "\n", "k", "v", true},
|
||||
{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
|
||||
{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
|
||||
{"110 path=" + medName + "\n", "", "path", medName, true},
|
||||
{"9 foo=ba\n", "", "foo", "ba", true},
|
||||
{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
|
||||
{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
|
||||
{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
|
||||
{"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
|
||||
{"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
|
||||
{"1 k=1\n", "1 k=1\n", "", "", false},
|
||||
{"6 k~1\n", "6 k~1\n", "", "", false},
|
||||
{"6_k=1\n", "6_k=1\n", "", "", false},
|
||||
{"6 k=1 ", "6 k=1 ", "", "", false},
|
||||
{"632 k=1\n", "632 k=1\n", "", "", false},
|
||||
{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
|
||||
{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
|
||||
{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
key, val, res, err := parsePAXRecord(v.input)
|
||||
ok := (err == nil)
|
||||
if v.ok != ok {
|
||||
if v.ok {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.input)
|
||||
} else {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.input)
|
||||
}
|
||||
}
|
||||
if ok && (key != v.outputKey || val != v.outputVal) {
|
||||
t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
|
||||
v.input, key, val, v.outputKey, v.outputVal)
|
||||
}
|
||||
if res != v.residual {
|
||||
t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
|
||||
v.input, res, v.residual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue