mirror of
https://github.com/golang/go
synced 2024-11-20 10:04:45 -07:00
archive/tar: avoid writing ModTime that is out of range.
Update #4358 Still to do: support binary numeric format in Reader. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6818101
This commit is contained in:
parent
7c0cbbfa18
commit
0ac317817b
@ -5,7 +5,10 @@
|
|||||||
package tar
|
package tar
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -54,3 +57,43 @@ func (symlink) Mode() os.FileMode { return os.ModeSymlink }
|
|||||||
func (symlink) ModTime() time.Time { return time.Time{} }
|
func (symlink) ModTime() time.Time { return time.Time{} }
|
||||||
func (symlink) IsDir() bool { return false }
|
func (symlink) IsDir() bool { return false }
|
||||||
func (symlink) Sys() interface{} { return nil }
|
func (symlink) Sys() interface{} { return nil }
|
||||||
|
|
||||||
|
func TestRoundTrip(t *testing.T) {
|
||||||
|
data := []byte("some file contents")
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
tw := NewWriter(&b)
|
||||||
|
hdr := &Header{
|
||||||
|
Name: "file.txt",
|
||||||
|
Size: int64(len(data)),
|
||||||
|
ModTime: time.Now(),
|
||||||
|
}
|
||||||
|
// tar only supports second precision.
|
||||||
|
hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
|
||||||
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
|
t.Fatalf("tw.WriteHeader: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := tw.Write(data); err != nil {
|
||||||
|
t.Fatalf("tw.Write: %v", err)
|
||||||
|
}
|
||||||
|
if err := tw.Close(); err != nil {
|
||||||
|
t.Fatalf("tw.Close: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read it back.
|
||||||
|
tr := NewReader(&b)
|
||||||
|
rHdr, err := tr.Next()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("tr.Next: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(rHdr, hdr) {
|
||||||
|
t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
|
||||||
|
}
|
||||||
|
rData, err := ioutil.ReadAll(tr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Read: %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(rData, data) {
|
||||||
|
t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -110,6 +111,12 @@ func (tw *Writer) numeric(b []byte, x int64) {
|
|||||||
b[0] |= 0x80 // highest bit indicates binary format
|
b[0] |= 0x80 // highest bit indicates binary format
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
minTime = time.Unix(0, 0)
|
||||||
|
// There is room for 11 octal digits (33 bits) of mtime.
|
||||||
|
maxTime = minTime.Add((1<<33 - 1) * time.Second)
|
||||||
|
)
|
||||||
|
|
||||||
// WriteHeader writes hdr and prepares to accept the file's contents.
|
// WriteHeader writes hdr and prepares to accept the file's contents.
|
||||||
// WriteHeader calls Flush if it is not the first header.
|
// WriteHeader calls Flush if it is not the first header.
|
||||||
// Calling after a Close will return ErrWriteAfterClose.
|
// Calling after a Close will return ErrWriteAfterClose.
|
||||||
@ -133,11 +140,17 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
|
|||||||
// TODO(dsymonds): handle names longer than 100 chars
|
// TODO(dsymonds): handle names longer than 100 chars
|
||||||
copy(s.next(100), []byte(hdr.Name))
|
copy(s.next(100), []byte(hdr.Name))
|
||||||
|
|
||||||
|
// Handle out of range ModTime carefully.
|
||||||
|
var modTime int64
|
||||||
|
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
|
||||||
|
modTime = hdr.ModTime.Unix()
|
||||||
|
}
|
||||||
|
|
||||||
tw.octal(s.next(8), hdr.Mode) // 100:108
|
tw.octal(s.next(8), hdr.Mode) // 100:108
|
||||||
tw.numeric(s.next(8), int64(hdr.Uid)) // 108:116
|
tw.numeric(s.next(8), int64(hdr.Uid)) // 108:116
|
||||||
tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
|
tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
|
||||||
tw.numeric(s.next(12), hdr.Size) // 124:136
|
tw.numeric(s.next(12), hdr.Size) // 124:136
|
||||||
tw.numeric(s.next(12), hdr.ModTime.Unix()) // 136:148
|
tw.numeric(s.next(12), modTime) // 136:148
|
||||||
s.next(8) // chksum (148:156)
|
s.next(8) // chksum (148:156)
|
||||||
s.next(1)[0] = hdr.Typeflag // 156:157
|
s.next(1)[0] = hdr.Typeflag // 156:157
|
||||||
tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
|
tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
|
||||||
|
Loading…
Reference in New Issue
Block a user