Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tar: remove strconv dependency for tar checksum octal numbers #536

Merged
merged 1 commit into from
May 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions internal/magic/archive.go
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ package magic
import (
"bytes"
"encoding/binary"
"strconv"
)

var (
@@ -110,37 +109,35 @@ func Tar(raw []byte, _ uint32) bool {
}

// Get the checksum recorded into the file.
recsum, err := tarParseOctal(raw[148:156])
if err != nil {
recsum := tarParseOctal(raw[148:156])
if recsum == -1 {
return false
}
sum1, sum2 := tarChksum(raw)
return recsum == sum1 || recsum == sum2
}

// tarParseOctal converts octal string to decimal int.
func tarParseOctal(b []byte) (int64, error) {
func tarParseOctal(b []byte) int64 {
// Because unused fields are filled with NULs, we need to skip leading NULs.
// Fields may also be padded with spaces or NULs.
// So we remove leading and trailing NULs and spaces to be sure.
b = bytes.Trim(b, " \x00")

if len(b) == 0 {
return 0, nil
return -1
}
x, err := strconv.ParseUint(tarParseString(b), 8, 64)
if err != nil {
return 0, err
}
return int64(x), nil
}

// tarParseString converts a NUL ended bytes slice to a string.
func tarParseString(b []byte) string {
if i := bytes.IndexByte(b, 0); i >= 0 {
return string(b[:i])
ret := int64(0)
for _, b := range b {
if b == 0 {
break
}
if !(b >= '0' && b <= '7') {
return -1
}
ret = (ret << 3) | int64(b-'0')
}
return string(b)
return ret
}

// tarChksum computes the checksum for the header block b.
35 changes: 13 additions & 22 deletions internal/magic/archive_test.go
Original file line number Diff line number Diff line change
@@ -6,32 +6,23 @@ func TestTarParseOctal(t *testing.T) {
tests := []struct {
in string
want int64
ok bool
}{
{"0000000\x00", 0, true},
{" \x0000000\x00", 0, true},
{" \x0000003\x00", 3, true},
{"00000000227\x00", 0227, true},
{"032033\x00 ", 032033, true},
{"320330\x00 ", 0320330, true},
{"0000660\x00 ", 0660, true},
{"\x00 0000660\x00 ", 0660, true},
{"0123456789abcdef", 0, false},
{"0123456789\x00abcdef", 0, false},
{"01234567\x0089abcdef", 342391, true},
{"0123\x7e\x5f\x264123", 0, false},
{"0000000\x00", 0},
{" \x0000000\x00", 0},
{" \x0000003\x00", 3},
{"00000000227\x00", 0227},
{"032033\x00 ", 032033},
{"320330\x00 ", 0320330},
{"0000660\x00 ", 0660},
{"\x00 0000660\x00 ", 0660},
{"0123456789abcdef", -1},
{"0123456789\x00abcdef", -1},
{"01234567\x0089abcdef", 01234567},
{"0123\x7e\x5f\x264123", -1},
}

for _, tt := range tests {
got, err := tarParseOctal([]byte(tt.in))
ok := err == nil
if ok != tt.ok {
if tt.ok {
t.Errorf("parseOctal(%q): got parsing failure, want success", tt.in)
} else {
t.Errorf("parseOctal(%q): got parsing success, want failure", tt.in)
}
}
got := tarParseOctal([]byte(tt.in))
if got != tt.want {
t.Errorf("parseOctal(%q): got %d, want %d", tt.in, got, tt.want)
}