Skip to content

Commit

Permalink
feat: add ReadFileWithSizeLimit and use it on x/wasm (#696)
Browse files Browse the repository at this point in the history
* Add `ReadFileWithSizeLimit` and use it on `x/wasm`

* Update CHANGELOG.md

* Refactor internal/os into x/wasm

* Revert "Refactor internal/os into x/wasm"

This reverts commit 200df68.

* Use `ReadFileWithSizeLimit` on `x/distribution`

* Modify to one liner
  • Loading branch information
tnasu committed Oct 11, 2022
1 parent 1a3eabd commit df29ba8
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (refactor) [\#685](https://github.com/line/lbm-sdk/pull/685) remove x/foundation UpdateValidatorAuthsProposal
* (x/foundation) [\#686](https://github.com/line/lbm-sdk/pull/686) remove `Minthreshold` and `MinPercentage` from x/foundation config
* (x/foundation) [\#693](https://github.com/line/lbm-sdk/pull/693) add pool to the state of x/foundation
* (x/wasm,distribution) [\#696](https://github.com/line/lbm-sdk/pull/696) x/wasm,distribution - add checking a file size before reading it
* (x/foundation) [\#698](https://github.com/line/lbm-sdk/pull/698) update x/group relevant logic in x/foundation

### Bug Fixes
Expand Down
58 changes: 58 additions & 0 deletions internal/os/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package os

import (
"fmt"
"io"
"os"
)

// ReadFileWithSizeLimit expanded os.ReadFile for checking the file size before reading it
func ReadFileWithSizeLimit(name string, sizeLimit int64) ([]byte, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer func() {
err := f.Close()
if err != nil {
fmt.Printf("Cannot close the file: %s\n", name)
}
}()

var size int
if info, err := f.Stat(); err == nil {
size64 := info.Size()
// Check the file size
if size64 > sizeLimit {
return nil, fmt.Errorf("the file is too large: %s, size limit over > %d", name, sizeLimit)
}
if int64(int(size64)) == size64 {
size = int(size64)
}
}
size++ // one byte for final read at EOF

// If a file claims a small size, read at least 512 bytes.
// In particular, files in Linux's /proc claim size 0 but
// then do not work right if read in small pieces,
// so an initial read of 1 byte would not work correctly.
if size < 512 {
size = 512
}

data := make([]byte, 0, size)
for {
if len(data) >= cap(data) {
d := append(data[:cap(data)], 0)
data = d[:len(data)]
}
n, err := f.Read(data[len(data):cap(data)])
data = data[:len(data)+n]
if err != nil {
if err == io.EOF {
err = nil
}
return data, err
}
}
}
42 changes: 42 additions & 0 deletions internal/os/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package os

import (
"os"
"reflect"
"testing"

"github.com/stretchr/testify/require"
)

func TestReadFileWithSizeLimit(t *testing.T) {
filename := "file.go"
file, err := os.ReadFile(filename)
require.NoError(t, err)

type args struct {
name string
sizeLimit int64
}
tests := []struct {
name string
args args
want []byte
wantErr bool
}{
{"cannot open error", args{"", 0}, nil, true},
{"size limit over error", args{filename, 0}, nil, true},
{"simple reading file success", args{filename, 100000}, file, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ReadFileWithSizeLimit(tt.args.name, tt.args.sizeLimit)
if (err != nil) != tt.wantErr {
t.Errorf("ReadFileWithSizeLimit() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ReadFileWithSizeLimit() got = %v, want %v", got, tt.want)
}
})
}
}
8 changes: 5 additions & 3 deletions x/distribution/client/cli/utils.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package cli

import (
"os"

"github.com/line/lbm-sdk/codec"
"github.com/line/lbm-sdk/internal/os"
"github.com/line/lbm-sdk/x/distribution/types"
)

// ParseCommunityPoolSpendProposalWithDeposit reads and parses a CommunityPoolSpendProposalWithDeposit from a file.
func ParseCommunityPoolSpendProposalWithDeposit(cdc codec.JSONCodec, proposalFile string) (types.CommunityPoolSpendProposalWithDeposit, error) {
proposal := types.CommunityPoolSpendProposalWithDeposit{}

contents, err := os.ReadFile(proposalFile)
// 2M size limit is enough for a proposal.
// Check the proposals:
// https://hubble.figment.io/cosmos/chains/cosmoshub-4/governance
contents, err := os.ReadFileWithSizeLimit(proposalFile, 2*1024*1024)
if err != nil {
return proposal, err
}
Expand Down
7 changes: 4 additions & 3 deletions x/wasm/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package cli
import (
"errors"
"fmt"
"os"
"strconv"

"github.com/line/lbm-sdk/internal/os"

"github.com/spf13/cobra"
flag "github.com/spf13/pflag"

Expand Down Expand Up @@ -82,7 +83,7 @@ func StoreCodeCmd() *cobra.Command {
}

func parseStoreCodeArgs(file string, sender sdk.AccAddress, flags *flag.FlagSet) (types.MsgStoreCode, error) {
wasm, err := os.ReadFile(file)
wasm, err := os.ReadFileWithSizeLimit(file, int64(types.MaxWasmSize))
if err != nil {
return types.MsgStoreCode{}, err
}
Expand Down Expand Up @@ -264,7 +265,7 @@ func StoreCodeAndInstantiateContractCmd() *cobra.Command {
}

func parseStoreCodeAndInstantiateContractArgs(file string, initMsg string, sender sdk.AccAddress, flags *flag.FlagSet) (lbmtypes.MsgStoreCodeAndInstantiateContract, error) {
wasm, err := os.ReadFile(file)
wasm, err := os.ReadFileWithSizeLimit(file, int64(types.MaxWasmSize))
if err != nil {
return lbmtypes.MsgStoreCodeAndInstantiateContract{}, err
}
Expand Down

0 comments on commit df29ba8

Please sign in to comment.