aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/archive
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-11-21 07:03:38 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-11-21 07:03:38 +0000
commitfabcaa8df3d6eb852b87821ef090d31d222870b7 (patch)
tree72455aea0286937aa08cc141e5efc800e4626577 /libgo/go/archive
parenta51fb17f48428e7cfc96a72a9f9f87901363bb6b (diff)
downloadgcc-fabcaa8df3d6eb852b87821ef090d31d222870b7.zip
gcc-fabcaa8df3d6eb852b87821ef090d31d222870b7.tar.gz
gcc-fabcaa8df3d6eb852b87821ef090d31d222870b7.tar.bz2
libgo: Update to current version of master library.
From-SVN: r193688
Diffstat (limited to 'libgo/go/archive')
-rw-r--r--libgo/go/archive/tar/reader.go12
-rw-r--r--libgo/go/archive/tar/tar_test.go44
-rw-r--r--libgo/go/archive/tar/writer.go39
-rw-r--r--libgo/go/archive/zip/reader.go9
-rw-r--r--libgo/go/archive/zip/writer.go2
-rw-r--r--libgo/go/archive/zip/zip_test.go82
6 files changed, 173 insertions, 15 deletions
diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go
index 1b40af8..ad825c6 100644
--- a/libgo/go/archive/tar/reader.go
+++ b/libgo/go/archive/tar/reader.go
@@ -72,6 +72,18 @@ func cString(b []byte) string {
}
func (tr *Reader) octal(b []byte) int64 {
+ // Check for binary format first.
+ if len(b) > 0 && b[0]&0x80 != 0 {
+ var x int64
+ for i, c := range b {
+ if i == 0 {
+ c &= 0x7f // ignore signal bit in first byte
+ }
+ x = x<<8 | int64(c)
+ }
+ return x
+ }
+
// Removing leading spaces.
for len(b) > 0 && b[0] == ' ' {
b = b[1:]
diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go
index 0adc179..7b190b6 100644
--- a/libgo/go/archive/tar/tar_test.go
+++ b/libgo/go/archive/tar/tar_test.go
@@ -5,7 +5,10 @@
package tar
import (
+ "bytes"
+ "io/ioutil"
"os"
+ "reflect"
"testing"
"time"
)
@@ -54,3 +57,44 @@ func (symlink) Mode() os.FileMode { return os.ModeSymlink }
func (symlink) ModTime() time.Time { return time.Time{} }
func (symlink) IsDir() bool { return false }
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",
+ Uid: 1 << 21, // too big for 8 octal digits
+ 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)
+ }
+}
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index a9c8fdb..5af504b 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -12,6 +12,7 @@ import (
"fmt"
"io"
"strconv"
+ "time"
)
var (
@@ -110,6 +111,12 @@ func (tw *Writer) numeric(b []byte, x int64) {
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 calls Flush if it is not the first header.
// Calling after a Close will return ErrWriteAfterClose.
@@ -133,19 +140,25 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
// TODO(dsymonds): handle names longer than 100 chars
copy(s.next(100), []byte(hdr.Name))
- 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.Gid)) // 116:124
- tw.numeric(s.next(12), hdr.Size) // 124:136
- tw.numeric(s.next(12), hdr.ModTime.Unix()) // 136:148
- s.next(8) // chksum (148:156)
- s.next(1)[0] = hdr.Typeflag // 156:157
- tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
- copy(s.next(8), []byte("ustar\x0000")) // 257:265
- tw.cString(s.next(32), hdr.Uname) // 265:297
- tw.cString(s.next(32), hdr.Gname) // 297:329
- tw.numeric(s.next(8), hdr.Devmajor) // 329:337
- tw.numeric(s.next(8), hdr.Devminor) // 337:345
+ // 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.numeric(s.next(8), int64(hdr.Uid)) // 108:116
+ tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
+ tw.numeric(s.next(12), hdr.Size) // 124:136
+ tw.numeric(s.next(12), modTime) // 136:148
+ s.next(8) // chksum (148:156)
+ s.next(1)[0] = hdr.Typeflag // 156:157
+ tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
+ copy(s.next(8), []byte("ustar\x0000")) // 257:265
+ tw.cString(s.next(32), hdr.Uname) // 265:297
+ tw.cString(s.next(32), hdr.Gname) // 297:329
+ tw.numeric(s.next(8), hdr.Devmajor) // 329:337
+ tw.numeric(s.next(8), hdr.Devminor) // 337:345
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
if tw.usedBinary {
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index a6b049e..c10f29a 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -238,9 +238,12 @@ func readDirectoryHeader(f *File, r io.Reader) error {
if len(f.Extra) > 0 {
b := readBuf(f.Extra)
- for len(b) > 0 {
+ for len(b) >= 4 { // need at least tag and size
tag := b.uint16()
size := b.uint16()
+ if int(size) > len(b) {
+ return ErrFormat
+ }
if tag == zip64ExtraId {
// update directory values from the zip64 extra block
eb := readBuf(b)
@@ -256,6 +259,10 @@ func readDirectoryHeader(f *File, r io.Reader) error {
}
b = b[size:]
}
+ // Should have consumed the whole header.
+ if len(b) != 0 {
+ return ErrFormat
+ }
}
return nil
}
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index 50d8394..4c696e1 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -174,7 +174,7 @@ func (w *Writer) Create(name string) (io.Writer, error) {
}
// CreateHeader adds a file to the zip file using the provided FileHeader
-// for the file metadata.
+// for the file metadata.
// It returns a Writer to which the file contents should be written.
// The file's contents must be written to the io.Writer before the next
// call to Create, CreateHeader, or Close.
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index 1d229d0..0a18798 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -173,3 +173,85 @@ func TestZip64(t *testing.T) {
t.Errorf("UncompressedSize64 %d, want %d", got, want)
}
}
+
+func testInvalidHeader(h *FileHeader, t *testing.T) {
+ var buf bytes.Buffer
+ z := NewWriter(&buf)
+
+ f, err := z.CreateHeader(h)
+ if err != nil {
+ t.Fatalf("error creating header: %v", err)
+ }
+ if _, err := f.Write([]byte("hi")); err != nil {
+ t.Fatalf("error writing content: %v", err)
+ }
+ if err := z.Close(); err != nil {
+ t.Fatalf("error closing zip writer: %v", err)
+ }
+
+ b := buf.Bytes()
+ if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat {
+ t.Fatalf("got %v, expected ErrFormat", err)
+ }
+}
+
+func testValidHeader(h *FileHeader, t *testing.T) {
+ var buf bytes.Buffer
+ z := NewWriter(&buf)
+
+ f, err := z.CreateHeader(h)
+ if err != nil {
+ t.Fatalf("error creating header: %v", err)
+ }
+ if _, err := f.Write([]byte("hi")); err != nil {
+ t.Fatalf("error writing content: %v", err)
+ }
+ if err := z.Close(); err != nil {
+ t.Fatalf("error closing zip writer: %v", err)
+ }
+
+ b := buf.Bytes()
+ if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != nil {
+ t.Fatalf("got %v, expected nil", err)
+ }
+}
+
+// Issue 4302.
+func TestHeaderInvalidTagAndSize(t *testing.T) {
+ const timeFormat = "20060102T150405.000.txt"
+
+ ts := time.Now()
+ filename := ts.Format(timeFormat)
+
+ h := FileHeader{
+ Name: filename,
+ Method: Deflate,
+ Extra: []byte(ts.Format(time.RFC3339Nano)), // missing tag and len
+ }
+ h.SetModTime(ts)
+
+ testInvalidHeader(&h, t)
+}
+
+func TestHeaderTooShort(t *testing.T) {
+ h := FileHeader{
+ Name: "foo.txt",
+ Method: Deflate,
+ Extra: []byte{zip64ExtraId}, // missing size
+ }
+ testInvalidHeader(&h, t)
+}
+
+// Issue 4393. It is valid to have an extra data header
+// which contains no body.
+func TestZeroLengthHeader(t *testing.T) {
+ h := FileHeader{
+ Name: "extadata.txt",
+ Method: Deflate,
+ Extra: []byte{
+ 85, 84, 5, 0, 3, 154, 144, 195, 77, // tag 21589 size 5
+ 85, 120, 0, 0, // tag 30805 size 0
+ },
+ }
+ testValidHeader(&h, t)
+}