mirror of https://github.com/certusone/wasmd.git
54 lines
1.2 KiB
Go
54 lines
1.2 KiB
Go
package keeper
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"io"
|
|
"io/ioutil"
|
|
|
|
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
|
)
|
|
|
|
// magic bytes to identify gzip.
|
|
// See https://www.ietf.org/rfc/rfc1952.txt
|
|
// and https://github.com/golang/go/blob/master/src/net/http/sniff.go#L186
|
|
var gzipIdent = []byte("\x1F\x8B\x08")
|
|
|
|
// uncompress returns gzip uncompressed content or given src when not gzip.
|
|
func uncompress(src []byte, limit uint64) ([]byte, error) {
|
|
switch n := uint64(len(src)); {
|
|
case n < 3:
|
|
return src, nil
|
|
case n > limit:
|
|
return nil, types.ErrLimit
|
|
}
|
|
if !bytes.Equal(gzipIdent, src[0:3]) {
|
|
return src, nil
|
|
}
|
|
zr, err := gzip.NewReader(bytes.NewReader(src))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
zr.Multistream(false)
|
|
defer zr.Close()
|
|
return ioutil.ReadAll(LimitReader(zr, int64(limit)))
|
|
}
|
|
|
|
// LimitReader returns a Reader that reads from r
|
|
// but stops with types.ErrLimit after n bytes.
|
|
// The underlying implementation is a *io.LimitedReader.
|
|
func LimitReader(r io.Reader, n int64) io.Reader {
|
|
return &LimitedReader{r: &io.LimitedReader{R: r, N: n}}
|
|
}
|
|
|
|
type LimitedReader struct {
|
|
r *io.LimitedReader
|
|
}
|
|
|
|
func (l *LimitedReader) Read(p []byte) (n int, err error) {
|
|
if l.r.N <= 0 {
|
|
return 0, types.ErrLimit
|
|
}
|
|
return l.r.Read(p)
|
|
}
|