From 4f4cd5e63573da4d6edcc7d4213afaca67c19f88 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Mon, 23 Nov 2015 15:53:48 -0800 Subject: upgrading libs --- .../src/golang.org/x/crypto/bcrypt/base64.go | 35 ++ .../src/golang.org/x/crypto/bcrypt/bcrypt.go | 294 ++++++++++++++++ .../src/golang.org/x/crypto/bcrypt/bcrypt_test.go | 226 ++++++++++++ .../golang.org/x/image/font/basicfont/basicfont.go | 2 +- .../src/golang.org/x/image/font/basicfont/gen.go | 6 +- .../_workspace/src/golang.org/x/image/font/font.go | 2 +- .../x/image/font/plan9font/example_test.go | 6 +- .../golang.org/x/image/font/plan9font/plan9font.go | 4 +- .../src/golang.org/x/image/tiff/buffer_test.go | 36 ++ .../src/golang.org/x/image/tiff/reader.go | 2 +- .../src/golang.org/x/image/tiff/reader_test.go | 377 +++++++++++++++++++++ .../src/golang.org/x/image/tiff/writer_test.go | 95 ++++++ 12 files changed, 1074 insertions(+), 11 deletions(-) create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/bcrypt/base64.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt.go create mode 100644 Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go create mode 100644 Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go (limited to 'Godeps/_workspace/src/golang.org') diff --git a/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/base64.go b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/base64.go new file mode 100644 index 000000000..fc3116090 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/base64.go @@ -0,0 +1,35 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bcrypt + +import "encoding/base64" + +const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +var bcEncoding = base64.NewEncoding(alphabet) + +func base64Encode(src []byte) []byte { + n := bcEncoding.EncodedLen(len(src)) + dst := make([]byte, n) + bcEncoding.Encode(dst, src) + for dst[n-1] == '=' { + n-- + } + return dst[:n] +} + +func base64Decode(src []byte) ([]byte, error) { + numOfEquals := 4 - (len(src) % 4) + for i := 0; i < numOfEquals; i++ { + src = append(src, '=') + } + + dst := make([]byte, bcEncoding.DecodedLen(len(src))) + n, err := bcEncoding.Decode(dst, src) + if err != nil { + return nil, err + } + return dst[:n], nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt.go b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt.go new file mode 100644 index 000000000..aa50fdc61 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt.go @@ -0,0 +1,294 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing +// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf +package bcrypt + +// The code is a port of Provos and Mazières's C implementation. +import ( + "crypto/rand" + "crypto/subtle" + "errors" + "fmt" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/crypto/blowfish" + "io" + "strconv" +) + +const ( + MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword + MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword + DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword +) + +// The error returned from CompareHashAndPassword when a password and hash do +// not match. +var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") + +// The error returned from CompareHashAndPassword when a hash is too short to +// be a bcrypt hash. +var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") + +// The error returned from CompareHashAndPassword when a hash was created with +// a bcrypt algorithm newer than this implementation. +type HashVersionTooNewError byte + +func (hv HashVersionTooNewError) Error() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) +} + +// The error returned from CompareHashAndPassword when a hash starts with something other than '$' +type InvalidHashPrefixError byte + +func (ih InvalidHashPrefixError) Error() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) +} + +type InvalidCostError int + +func (ic InvalidCostError) Error() string { + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) +} + +const ( + majorVersion = '2' + minorVersion = 'a' + maxSaltSize = 16 + maxCryptedHashSize = 23 + encodedSaltSize = 22 + encodedHashSize = 31 + minHashSize = 59 +) + +// magicCipherData is an IV for the 64 Blowfish encryption calls in +// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. +var magicCipherData = []byte{ + 0x4f, 0x72, 0x70, 0x68, + 0x65, 0x61, 0x6e, 0x42, + 0x65, 0x68, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x53, + 0x63, 0x72, 0x79, 0x44, + 0x6f, 0x75, 0x62, 0x74, +} + +type hashed struct { + hash []byte + salt []byte + cost int // allowed range is MinCost to MaxCost + major byte + minor byte +} + +// GenerateFromPassword returns the bcrypt hash of the password at the given +// cost. If the cost given is less than MinCost, the cost will be set to +// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, +// to compare the returned hashed password with its cleartext version. +func GenerateFromPassword(password []byte, cost int) ([]byte, error) { + p, err := newFromPassword(password, cost) + if err != nil { + return nil, err + } + return p.Hash(), nil +} + +// CompareHashAndPassword compares a bcrypt hashed password with its possible +// plaintext equivalent. Returns nil on success, or an error on failure. +func CompareHashAndPassword(hashedPassword, password []byte) error { + p, err := newFromHash(hashedPassword) + if err != nil { + return err + } + + otherHash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return err + } + + otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} + if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { + return nil + } + + return ErrMismatchedHashAndPassword +} + +// Cost returns the hashing cost used to create the given hashed +// password. When, in the future, the hashing cost of a password system needs +// to be increased in order to adjust for greater computational power, this +// function allows one to establish which passwords need to be updated. +func Cost(hashedPassword []byte) (int, error) { + p, err := newFromHash(hashedPassword) + if err != nil { + return 0, err + } + return p.cost, nil +} + +func newFromPassword(password []byte, cost int) (*hashed, error) { + if cost < MinCost { + cost = DefaultCost + } + p := new(hashed) + p.major = majorVersion + p.minor = minorVersion + + err := checkCost(cost) + if err != nil { + return nil, err + } + p.cost = cost + + unencodedSalt := make([]byte, maxSaltSize) + _, err = io.ReadFull(rand.Reader, unencodedSalt) + if err != nil { + return nil, err + } + + p.salt = base64Encode(unencodedSalt) + hash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return nil, err + } + p.hash = hash + return p, err +} + +func newFromHash(hashedSecret []byte) (*hashed, error) { + if len(hashedSecret) < minHashSize { + return nil, ErrHashTooShort + } + p := new(hashed) + n, err := p.decodeVersion(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + n, err = p.decodeCost(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + + // The "+2" is here because we'll have to append at most 2 '=' to the salt + // when base64 decoding it in expensiveBlowfishSetup(). + p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) + copy(p.salt, hashedSecret[:encodedSaltSize]) + + hashedSecret = hashedSecret[encodedSaltSize:] + p.hash = make([]byte, len(hashedSecret)) + copy(p.hash, hashedSecret) + + return p, nil +} + +func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { + cipherData := make([]byte, len(magicCipherData)) + copy(cipherData, magicCipherData) + + c, err := expensiveBlowfishSetup(password, uint32(cost), salt) + if err != nil { + return nil, err + } + + for i := 0; i < 24; i += 8 { + for j := 0; j < 64; j++ { + c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) + } + } + + // Bug compatibility with C bcrypt implementations. We only encode 23 of + // the 24 bytes encrypted. + hsh := base64Encode(cipherData[:maxCryptedHashSize]) + return hsh, nil +} + +func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { + + csalt, err := base64Decode(salt) + if err != nil { + return nil, err + } + + // Bug compatibility with C bcrypt implementations. They use the trailing + // NULL in the key string during expansion. + ckey := append(key, 0) + + c, err := blowfish.NewSaltedCipher(ckey, csalt) + if err != nil { + return nil, err + } + + var i, rounds uint64 + rounds = 1 << cost + for i = 0; i < rounds; i++ { + blowfish.ExpandKey(ckey, c) + blowfish.ExpandKey(csalt, c) + } + + return c, nil +} + +func (p *hashed) Hash() []byte { + arr := make([]byte, 60) + arr[0] = '$' + arr[1] = p.major + n := 2 + if p.minor != 0 { + arr[2] = p.minor + n = 3 + } + arr[n] = '$' + n += 1 + copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) + n += 2 + arr[n] = '$' + n += 1 + copy(arr[n:], p.salt) + n += encodedSaltSize + copy(arr[n:], p.hash) + n += encodedHashSize + return arr[:n] +} + +func (p *hashed) decodeVersion(sbytes []byte) (int, error) { + if sbytes[0] != '$' { + return -1, InvalidHashPrefixError(sbytes[0]) + } + if sbytes[1] > majorVersion { + return -1, HashVersionTooNewError(sbytes[1]) + } + p.major = sbytes[1] + n := 3 + if sbytes[2] != '$' { + p.minor = sbytes[2] + n++ + } + return n, nil +} + +// sbytes should begin where decodeVersion left off. +func (p *hashed) decodeCost(sbytes []byte) (int, error) { + cost, err := strconv.Atoi(string(sbytes[0:2])) + if err != nil { + return -1, err + } + err = checkCost(cost) + if err != nil { + return -1, err + } + p.cost = cost + return 3, nil +} + +func (p *hashed) String() string { + return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) +} + +func checkCost(cost int) error { + if cost < MinCost || cost > MaxCost { + return InvalidCostError(cost) + } + return nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go new file mode 100644 index 000000000..f08a6f5b2 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go @@ -0,0 +1,226 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bcrypt + +import ( + "bytes" + "fmt" + "testing" +) + +func TestBcryptingIsEasy(t *testing.T) { + pass := []byte("mypassword") + hp, err := GenerateFromPassword(pass, 0) + if err != nil { + t.Fatalf("GenerateFromPassword error: %s", err) + } + + if CompareHashAndPassword(hp, pass) != nil { + t.Errorf("%v should hash %s correctly", hp, pass) + } + + notPass := "notthepass" + err = CompareHashAndPassword(hp, []byte(notPass)) + if err != ErrMismatchedHashAndPassword { + t.Errorf("%v and %s should be mismatched", hp, notPass) + } +} + +func TestBcryptingIsCorrect(t *testing.T) { + pass := []byte("allmine") + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") + expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") + + hash, err := bcrypt(pass, 10, salt) + if err != nil { + t.Fatalf("bcrypt blew up: %v", err) + } + if !bytes.HasSuffix(expectedHash, hash) { + t.Errorf("%v should be the suffix of %v", hash, expectedHash) + } + + h, err := newFromHash(expectedHash) + if err != nil { + t.Errorf("Unable to parse %s: %v", string(expectedHash), err) + } + + // This is not the safe way to compare these hashes. We do this only for + // testing clarity. Use bcrypt.CompareHashAndPassword() + if err == nil && !bytes.Equal(expectedHash, h.Hash()) { + t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) + } +} + +func TestVeryShortPasswords(t *testing.T) { + key := []byte("k") + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") + _, err := bcrypt(key, 10, salt) + if err != nil { + t.Errorf("One byte key resulted in error: %s", err) + } +} + +func TestTooLongPasswordsWork(t *testing.T) { + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") + // One byte over the usual 56 byte limit that blowfish has + tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") + tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") + hash, err := bcrypt(tooLongPass, 10, salt) + if err != nil { + t.Fatalf("bcrypt blew up on long password: %v", err) + } + if !bytes.HasSuffix(tooLongExpected, hash) { + t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) + } +} + +type InvalidHashTest struct { + err error + hash []byte +} + +var invalidTests = []InvalidHashTest{ + {ErrHashTooShort, []byte("$2a$10$fooo")}, + {ErrHashTooShort, []byte("$2a")}, + {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, + {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, + {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, +} + +func TestInvalidHashErrors(t *testing.T) { + check := func(name string, expected, err error) { + if err == nil { + t.Errorf("%s: Should have returned an error", name) + } + if err != nil && err != expected { + t.Errorf("%s gave err %v but should have given %v", name, err, expected) + } + } + for _, iht := range invalidTests { + _, err := newFromHash(iht.hash) + check("newFromHash", iht.err, err) + err = CompareHashAndPassword(iht.hash, []byte("anything")) + check("CompareHashAndPassword", iht.err, err) + } +} + +func TestUnpaddedBase64Encoding(t *testing.T) { + original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} + encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") + + encoded := base64Encode(original) + + if !bytes.Equal(encodedOriginal, encoded) { + t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) + } + + decoded, err := base64Decode(encodedOriginal) + if err != nil { + t.Fatalf("base64Decode blew up: %s", err) + } + + if !bytes.Equal(decoded, original) { + t.Errorf("Decoded %v should have equaled %v", decoded, original) + } +} + +func TestCost(t *testing.T) { + suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C" + for _, vers := range []string{"2a", "2"} { + for _, cost := range []int{4, 10} { + s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix) + h := []byte(s) + actual, err := Cost(h) + if err != nil { + t.Errorf("Cost, error: %s", err) + continue + } + if actual != cost { + t.Errorf("Cost, expected: %d, actual: %d", cost, actual) + } + } + } + _, err := Cost([]byte("$a$a$" + suffix)) + if err == nil { + t.Errorf("Cost, malformed but no error returned") + } +} + +func TestCostValidationInHash(t *testing.T) { + if testing.Short() { + return + } + + pass := []byte("mypassword") + + for c := 0; c < MinCost; c++ { + p, _ := newFromPassword(pass, c) + if p.cost != DefaultCost { + t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) + } + } + + p, _ := newFromPassword(pass, 14) + if p.cost != 14 { + t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) + } + + hp, _ := newFromHash(p.Hash()) + if p.cost != hp.cost { + t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) + } + + _, err := newFromPassword(pass, 32) + if err == nil { + t.Fatalf("newFromPassword: should return a cost error") + } + if err != InvalidCostError(32) { + t.Errorf("newFromPassword: should return cost error, got %#v", err) + } +} + +func TestCostReturnsWithLeadingZeroes(t *testing.T) { + hp, _ := newFromPassword([]byte("abcdefgh"), 7) + cost := hp.Hash()[4:7] + expected := []byte("07$") + + if !bytes.Equal(expected, cost) { + t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) + } +} + +func TestMinorNotRequired(t *testing.T) { + noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") + h, err := newFromHash(noMinorHash) + if err != nil { + t.Fatalf("No minor hash blew up: %s", err) + } + if h.minor != 0 { + t.Errorf("Should leave minor version at 0, but was %d", h.minor) + } + + if !bytes.Equal(noMinorHash, h.Hash()) { + t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) + } +} + +func BenchmarkEqual(b *testing.B) { + b.StopTimer() + passwd := []byte("somepasswordyoulike") + hash, _ := GenerateFromPassword(passwd, 10) + b.StartTimer() + for i := 0; i < b.N; i++ { + CompareHashAndPassword(hash, passwd) + } +} + +func BenchmarkGeneration(b *testing.B) { + b.StopTimer() + passwd := []byte("mylongpassword1234") + b.StartTimer() + for i := 0; i < b.N; i++ { + GenerateFromPassword(passwd, 10) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/image/font/basicfont/basicfont.go b/Godeps/_workspace/src/golang.org/x/image/font/basicfont/basicfont.go index 7eae19c8b..8875bd1cc 100644 --- a/Godeps/_workspace/src/golang.org/x/image/font/basicfont/basicfont.go +++ b/Godeps/_workspace/src/golang.org/x/image/font/basicfont/basicfont.go @@ -10,7 +10,7 @@ package basicfont import ( "image" - "golang.org/x/image/math/fixed" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/math/fixed" ) // Range maps a contiguous range of runes to vertically adjacent sub-images of diff --git a/Godeps/_workspace/src/golang.org/x/image/font/basicfont/gen.go b/Godeps/_workspace/src/golang.org/x/image/font/basicfont/gen.go index 67a21a74a..4efb03322 100644 --- a/Godeps/_workspace/src/golang.org/x/image/font/basicfont/gen.go +++ b/Godeps/_workspace/src/golang.org/x/image/font/basicfont/gen.go @@ -18,9 +18,9 @@ import ( "path" "path/filepath" - "golang.org/x/image/font" - "golang.org/x/image/font/plan9font" - "golang.org/x/image/math/fixed" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/font" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/font/plan9font" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/math/fixed" ) func main() { diff --git a/Godeps/_workspace/src/golang.org/x/image/font/font.go b/Godeps/_workspace/src/golang.org/x/image/font/font.go index de8802fcc..1eae5c7ab 100644 --- a/Godeps/_workspace/src/golang.org/x/image/font/font.go +++ b/Godeps/_workspace/src/golang.org/x/image/font/font.go @@ -14,7 +14,7 @@ import ( "image/draw" "io" - "golang.org/x/image/math/fixed" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/math/fixed" ) // TODO: who is responsible for caches (glyph images, glyph indices, kerns)? diff --git a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go index c1eacb230..1114fd7d2 100644 --- a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go +++ b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/example_test.go @@ -13,9 +13,9 @@ import ( "path" "path/filepath" - "golang.org/x/image/font" - "golang.org/x/image/font/plan9font" - "golang.org/x/image/math/fixed" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/font" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/font/plan9font" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/math/fixed" ) func ExampleParseFont() { diff --git a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go index 9c686b776..705258c3b 100644 --- a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go +++ b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go @@ -21,8 +21,8 @@ import ( "strconv" "strings" - "golang.org/x/image/font" - "golang.org/x/image/math/fixed" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/font" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/math/fixed" ) // fontchar describes one character glyph in a subfont. diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go new file mode 100644 index 000000000..e13afb361 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import ( + "io" + "strings" + "testing" +) + +var readAtTests = []struct { + n int + off int64 + s string + err error +}{ + {2, 0, "ab", nil}, + {6, 0, "abcdef", nil}, + {3, 3, "def", nil}, + {3, 5, "f", io.EOF}, + {3, 6, "", io.EOF}, +} + +func TestReadAt(t *testing.T) { + r := newReaderAt(strings.NewReader("abcdef")) + b := make([]byte, 10) + for _, test := range readAtTests { + n, err := r.ReadAt(b[:test.n], test.off) + s := string(b[:n]) + if s != test.s || err != test.err { + t.Errorf("buffer.ReadAt(<%v bytes>, %v): got %v, %q; want %v, %q", test.n, test.off, err, s, test.err, test.s) + } + } +} diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go b/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go index 714e3dda7..651fa8026 100644 --- a/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go +++ b/Godeps/_workspace/src/golang.org/x/image/tiff/reader.go @@ -17,7 +17,7 @@ import ( "io/ioutil" "math" - "golang.org/x/image/tiff/lzw" + "github.com/mattermost/platform/Godeps/_workspace/src/golang.org/x/image/tiff/lzw" ) // A FormatError reports that the input is not a valid TIFF image. diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go new file mode 100644 index 000000000..f5c02e697 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/tiff/reader_test.go @@ -0,0 +1,377 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "errors" + "image" + "io/ioutil" + "os" + "strings" + "testing" + + _ "image/png" +) + +const testdataDir = "../testdata/" + +// Read makes *buffer implements io.Reader, so that we can pass one to Decode. +func (*buffer) Read([]byte) (int, error) { + panic("unimplemented") +} + +func load(name string) (image.Image, error) { + f, err := os.Open(testdataDir + name) + if err != nil { + return nil, err + } + defer f.Close() + img, _, err := image.Decode(f) + if err != nil { + return nil, err + } + return img, nil +} + +// TestNoRPS tests decoding an image that has no RowsPerStrip tag. The tag is +// mandatory according to the spec but some software omits it in the case of a +// single strip. +func TestNoRPS(t *testing.T) { + _, err := load("no_rps.tiff") + if err != nil { + t.Fatal(err) + } +} + +// TestNoCompression tests decoding an image that has no Compression tag. This +// tag is mandatory, but most tools interpret a missing value as no +// compression. +func TestNoCompression(t *testing.T) { + _, err := load("no_compress.tiff") + if err != nil { + t.Fatal(err) + } +} + +// TestUnpackBits tests the decoding of PackBits-encoded data. +func TestUnpackBits(t *testing.T) { + var unpackBitsTests = []struct { + compressed string + uncompressed string + }{{ + // Example data from Wikipedia. + "\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa", + "\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + }} + for _, u := range unpackBitsTests { + buf, err := unpackBits(strings.NewReader(u.compressed)) + if err != nil { + t.Fatal(err) + } + if string(buf) != u.uncompressed { + t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf) + } + } +} + +func TestShortBlockData(t *testing.T) { + b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") + if err != nil { + t.Fatal(err) + } + // The bw-uncompressed.tiff image is a 153x55 bi-level image. This is 1 bit + // per pixel, or 20 bytes per row, times 55 rows, or 1100 bytes of pixel + // data. 1100 in hex is 0x44c, or "\x4c\x04" in little-endian. We replace + // that byte count (StripByteCounts-tagged data) by something less than + // that, so that there is not enough pixel data. + old := []byte{0x4c, 0x04} + new := []byte{0x01, 0x01} + i := bytes.Index(b, old) + if i < 0 { + t.Fatal(`could not find "\x4c\x04" byte count`) + } + if bytes.Contains(b[i+len(old):], old) { + t.Fatal(`too many occurrences of "\x4c\x04"`) + } + b[i+0] = new[0] + b[i+1] = new[1] + if _, err = Decode(bytes.NewReader(b)); err == nil { + t.Fatal("got nil error, want non-nil") + } +} + +func TestDecodeInvalidDataType(t *testing.T) { + b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff") + if err != nil { + t.Fatal(err) + } + + // off is the offset of the ImageWidth tag. It is the offset of the overall + // IFD block (0x00000454), plus 2 for the uint16 number of IFD entries, plus 12 + // to skip the first entry. + const off = 0x00000454 + 2 + 12*1 + + if v := binary.LittleEndian.Uint16(b[off : off+2]); v != tImageWidth { + t.Fatal(`could not find ImageWidth tag`) + } + binary.LittleEndian.PutUint16(b[off+2:], uint16(len(lengths))) // invalid datatype + + if _, err = Decode(bytes.NewReader(b)); err == nil { + t.Fatal("got nil error, want non-nil") + } +} + +func compare(t *testing.T, img0, img1 image.Image) { + b0 := img0.Bounds() + b1 := img1.Bounds() + if b0.Dx() != b1.Dx() || b0.Dy() != b1.Dy() { + t.Fatalf("wrong image size: want %s, got %s", b0, b1) + } + x1 := b1.Min.X - b0.Min.X + y1 := b1.Min.Y - b0.Min.Y + for y := b0.Min.Y; y < b0.Max.Y; y++ { + for x := b0.Min.X; x < b0.Max.X; x++ { + c0 := img0.At(x, y) + c1 := img1.At(x+x1, y+y1) + r0, g0, b0, a0 := c0.RGBA() + r1, g1, b1, a1 := c1.RGBA() + if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { + t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) + } + } + } +} + +// TestDecode tests that decoding a PNG image and a TIFF image result in the +// same pixel data. +func TestDecode(t *testing.T) { + img0, err := load("video-001.png") + if err != nil { + t.Fatal(err) + } + img1, err := load("video-001.tiff") + if err != nil { + t.Fatal(err) + } + img2, err := load("video-001-strip-64.tiff") + if err != nil { + t.Fatal(err) + } + img3, err := load("video-001-tile-64x64.tiff") + if err != nil { + t.Fatal(err) + } + img4, err := load("video-001-16bit.tiff") + if err != nil { + t.Fatal(err) + } + + compare(t, img0, img1) + compare(t, img0, img2) + compare(t, img0, img3) + compare(t, img0, img4) +} + +// TestDecodeLZW tests that decoding a PNG image and a LZW-compressed TIFF +// image result in the same pixel data. +func TestDecodeLZW(t *testing.T) { + img0, err := load("blue-purple-pink.png") + if err != nil { + t.Fatal(err) + } + img1, err := load("blue-purple-pink.lzwcompressed.tiff") + if err != nil { + t.Fatal(err) + } + + compare(t, img0, img1) +} + +// TestDecompress tests that decoding some TIFF images that use different +// compression formats result in the same pixel data. +func TestDecompress(t *testing.T) { + var decompressTests = []string{ + "bw-uncompressed.tiff", + "bw-deflate.tiff", + "bw-packbits.tiff", + } + var img0 image.Image + for _, name := range decompressTests { + img1, err := load(name) + if err != nil { + t.Fatalf("decoding %s: %v", name, err) + } + if img0 == nil { + img0 = img1 + continue + } + compare(t, img0, img1) + } +} + +func replace(src []byte, find, repl string) ([]byte, error) { + removeSpaces := func(r rune) rune { + if r != ' ' { + return r + } + return -1 + } + + f, err := hex.DecodeString(strings.Map(removeSpaces, find)) + if err != nil { + return nil, err + } + r, err := hex.DecodeString(strings.Map(removeSpaces, repl)) + if err != nil { + return nil, err + } + dst := bytes.Replace(src, f, r, 1) + if bytes.Equal(dst, src) { + return nil, errors.New("replacement failed") + } + return dst, nil +} + +// TestZeroBitsPerSample tests that an IFD with a bitsPerSample of 0 does not +// cause a crash. +// Issue 10711. +func TestZeroBitsPerSample(t *testing.T) { + b0, err := ioutil.ReadFile(testdataDir + "bw-deflate.tiff") + if err != nil { + t.Fatal(err) + } + + // Mutate the loaded image to have the problem. + // 02 01: tag number (tBitsPerSample) + // 03 00: data type (short, or uint16) + // 01 00 00 00: count + // ?? 00 00 00: value (1 -> 0) + b1, err := replace(b0, + "02 01 03 00 01 00 00 00 01 00 00 00", + "02 01 03 00 01 00 00 00 00 00 00 00", + ) + if err != nil { + t.Fatal(err) + } + + _, err = Decode(bytes.NewReader(b1)) + if err == nil { + t.Fatal("Decode with 0 bits per sample: got nil error, want non-nil") + } +} + +// TestTileTooBig tests that we do not panic when a tile is too big compared to +// the data available. +// Issue 10712 +func TestTileTooBig(t *testing.T) { + b0, err := ioutil.ReadFile(testdataDir + "video-001-tile-64x64.tiff") + if err != nil { + t.Fatal(err) + } + + // Mutate the loaded image to have the problem. + // + // 42 01: tag number (tTileWidth) + // 03 00: data type (short, or uint16) + // 01 00 00 00: count + // xx 00 00 00: value (0x40 -> 0x44: a wider tile consumes more data + // than is available) + b1, err := replace(b0, + "42 01 03 00 01 00 00 00 40 00 00 00", + "42 01 03 00 01 00 00 00 44 00 00 00", + ) + if err != nil { + t.Fatal(err) + } + + // Turn off the predictor, which makes it possible to hit the + // place with the defect. Without this patch to the image, we run + // out of data too early, and do not hit the part of the code where + // the original panic was. + // + // 3d 01: tag number (tPredictor) + // 03 00: data type (short, or uint16) + // 01 00 00 00: count + // xx 00 00 00: value (2 -> 1: 2 = horizontal, 1 = none) + b2, err := replace(b1, + "3d 01 03 00 01 00 00 00 02 00 00 00", + "3d 01 03 00 01 00 00 00 01 00 00 00", + ) + if err != nil { + t.Fatal(err) + } + + _, err = Decode(bytes.NewReader(b2)) + if err == nil { + t.Fatal("did not expect nil error") + } +} + +// TestZeroSizedImages tests that decoding does not panic when image dimensions +// are zero, and returns a zero-sized image instead. +// Issue 10393. +func TestZeroSizedImages(t *testing.T) { + testsizes := []struct { + w, h int + }{ + {0, 0}, + {1, 0}, + {0, 1}, + {1, 1}, + } + for _, r := range testsizes { + img := image.NewRGBA(image.Rect(0, 0, r.w, r.h)) + var buf bytes.Buffer + if err := Encode(&buf, img, nil); err != nil { + t.Errorf("encode w=%d h=%d: %v", r.w, r.h, err) + continue + } + if _, err := Decode(&buf); err != nil { + t.Errorf("decode w=%d h=%d: %v", r.w, r.h, err) + } + } +} + +// TestLargeIFDEntry tests that a large IFD entry does not cause Decode to +// panic. +// Issue 10596. +func TestLargeIFDEntry(t *testing.T) { + testdata := "II*\x00\x08\x00\x00\x00\f\x000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "00000000000000\x17\x01\x04\x00\x01\x00" + + "\x00\xc0000000000000000000" + + "00000000000000000000" + + "00000000000000000000" + + "000000" + _, err := Decode(strings.NewReader(testdata)) + if err == nil { + t.Fatal("Decode with large IFD entry: got nil error, want non-nil") + } +} + +// benchmarkDecode benchmarks the decoding of an image. +func benchmarkDecode(b *testing.B, filename string) { + b.StopTimer() + contents, err := ioutil.ReadFile(testdataDir + filename) + if err != nil { + b.Fatal(err) + } + r := &buffer{buf: contents} + b.StartTimer() + for i := 0; i < b.N; i++ { + _, err := Decode(r) + if err != nil { + b.Fatal("Decode:", err) + } + } +} + +func BenchmarkDecodeCompressed(b *testing.B) { benchmarkDecode(b, "video-001.tiff") } +func BenchmarkDecodeUncompressed(b *testing.B) { benchmarkDecode(b, "video-001-uncompressed.tiff") } diff --git a/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go b/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go new file mode 100644 index 000000000..c8fb7bf37 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/image/tiff/writer_test.go @@ -0,0 +1,95 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tiff + +import ( + "bytes" + "image" + "io/ioutil" + "os" + "testing" +) + +var roundtripTests = []struct { + filename string + opts *Options +}{ + {"video-001.tiff", nil}, + {"video-001-16bit.tiff", nil}, + {"video-001-gray.tiff", nil}, + {"video-001-gray-16bit.tiff", nil}, + {"video-001-paletted.tiff", nil}, + {"bw-packbits.tiff", nil}, + {"video-001.tiff", &Options{Predictor: true}}, + {"video-001.tiff", &Options{Compression: Deflate}}, + {"video-001.tiff", &Options{Predictor: true, Compression: Deflate}}, +} + +func openImage(filename string) (image.Image, error) { + f, err := os.Open(testdataDir + filename) + if err != nil { + return nil, err + } + defer f.Close() + return Decode(f) +} + +func TestRoundtrip(t *testing.T) { + for _, rt := range roundtripTests { + img, err := openImage(rt.filename) + if err != nil { + t.Fatal(err) + } + out := new(bytes.Buffer) + err = Encode(out, img, rt.opts) + if err != nil { + t.Fatal(err) + } + + img2, err := Decode(&buffer{buf: out.Bytes()}) + if err != nil { + t.Fatal(err) + } + compare(t, img, img2) + } +} + +// TestRoundtrip2 tests that encoding and decoding an image whose +// origin is not (0, 0) gives the same thing. +func TestRoundtrip2(t *testing.T) { + m0 := image.NewRGBA(image.Rect(3, 4, 9, 8)) + for i := range m0.Pix { + m0.Pix[i] = byte(i) + } + out := new(bytes.Buffer) + if err := Encode(out, m0, nil); err != nil { + t.Fatal(err) + } + m1, err := Decode(&buffer{buf: out.Bytes()}) + if err != nil { + t.Fatal(err) + } + compare(t, m0, m1) +} + +func benchmarkEncode(b *testing.B, name string, pixelSize int) { + img, err := openImage(name) + if err != nil { + b.Fatal(err) + } + s := img.Bounds().Size() + b.SetBytes(int64(s.X * s.Y * pixelSize)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Encode(ioutil.Discard, img, nil) + } +} + +func BenchmarkEncode(b *testing.B) { benchmarkEncode(b, "video-001.tiff", 4) } +func BenchmarkEncodePaletted(b *testing.B) { benchmarkEncode(b, "video-001-paletted.tiff", 1) } +func BenchmarkEncodeGray(b *testing.B) { benchmarkEncode(b, "video-001-gray.tiff", 1) } +func BenchmarkEncodeGray16(b *testing.B) { benchmarkEncode(b, "video-001-gray-16bit.tiff", 2) } +func BenchmarkEncodeRGBA(b *testing.B) { benchmarkEncode(b, "video-001.tiff", 4) } +func BenchmarkEncodeRGBA64(b *testing.B) { benchmarkEncode(b, "video-001-16bit.tiff", 8) } -- cgit v1.2.3-1-g7c22