Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase coverage in AVM code. Bug fix in account fields of tx_field #2840

Merged
merged 1 commit into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions data/transactions/logic/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -3342,6 +3342,21 @@ func opTxBegin(cx *EvalContext) {
}
}

// availableAccount is used instead of accountReference for more recent opcodes
// that don't need (or want!) to allow low numbers to represent the account at
// that index in Accounts array.
func (cx *EvalContext) availableAccount(sv stackValue) (basics.Address, error) {
if sv.argType() != StackBytes {
return basics.Address{}, fmt.Errorf("not an address")
}

addr, _, err := cx.accountReference(sv)
return addr, err
}

// availableAsset is used instead of asaReference for more recent opcodes that
// don't need (or want!) to allow low numbers to represent the asset at that
// index in ForeignAssets array.
func (cx *EvalContext) availableAsset(sv stackValue) (basics.AssetIndex, error) {
aid, err := sv.uint()
if err != nil {
Expand All @@ -3366,6 +3381,9 @@ func opTxField(cx *EvalContext) {
sv := cx.stack[last]
switch field {
case Type:
if sv.Bytes == nil {
cx.err = fmt.Errorf("Type arg not a byte array")
}
cx.subtxn.Txn.Type = protocol.TxType(sv.Bytes)
case TypeEnum:
var i uint64
Expand All @@ -3375,7 +3393,7 @@ func opTxField(cx *EvalContext) {
}

case Sender:
cx.subtxn.Txn.Sender, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.Sender, cx.err = cx.availableAccount(sv)
case Fee:
cx.subtxn.Txn.Fee.Raw, cx.err = sv.uint()
// FirstValid, LastValid unsettable: no motivation
Expand All @@ -3388,22 +3406,22 @@ func opTxField(cx *EvalContext) {
// KeyReg not allowed yet, so no fields settable

case Receiver:
cx.subtxn.Txn.Receiver, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.Receiver, cx.err = cx.availableAccount(sv)
case Amount:
cx.subtxn.Txn.Amount.Raw, cx.err = sv.uint()
case CloseRemainderTo:
cx.subtxn.Txn.CloseRemainderTo, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.CloseRemainderTo, cx.err = cx.availableAccount(sv)

case XferAsset:
cx.subtxn.Txn.XferAsset, cx.err = cx.availableAsset(sv)
case AssetAmount:
cx.subtxn.Txn.AssetAmount, cx.err = sv.uint()
case AssetSender:
cx.subtxn.Txn.AssetSender, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.AssetSender, cx.err = cx.availableAccount(sv)
case AssetReceiver:
cx.subtxn.Txn.AssetReceiver, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.AssetReceiver, cx.err = cx.availableAccount(sv)
case AssetCloseTo:
cx.subtxn.Txn.AssetCloseTo, _, cx.err = cx.accountReference(sv)
cx.subtxn.Txn.AssetCloseTo, cx.err = cx.availableAccount(sv)

// acfg likely next

Expand Down
24 changes: 24 additions & 0 deletions data/transactions/logic/evalAppTxn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func TestActionTypes(t *testing.T) {
testApp(t, "tx_begin; tx_submit; int 1;", ep, "Invalid inner transaction type")
// bad type
testApp(t, "tx_begin; byte \"pya\"; tx_field Type; tx_submit; int 1;", ep, "Invalid inner transaction type")
// mixed up the int form for the byte form
testApp(t, obfuscate("tx_begin; int pay; tx_field Type; tx_submit; int 1;"), ep, "Type arg not a byte array")
// or vice versa
testApp(t, obfuscate("tx_begin; byte \"pay\"; tx_field TypeEnum; tx_submit; int 1;"), ep, "not a uint64")

// good types, not alllowed yet
testApp(t, "tx_begin; byte \"keyreg\"; tx_field Type; tx_submit; int 1;", ep, "Invalid inner transaction type")
Expand Down Expand Up @@ -57,6 +61,26 @@ func TestActionTypes(t *testing.T) {
testApp(t, "tx_begin; int pay; tx_field TypeEnum; tx_submit; int 1;", ep)
}

func TestFieldTypes(t *testing.T) {
ep, _ := makeSampleEnv()
testApp(t, "tx_begin; byte \"pay\"; tx_field Sender;", ep, "not an address")
testApp(t, obfuscate("tx_begin; int 7; tx_field Receiver;"), ep, "not an address")
testApp(t, "tx_begin; byte \"\"; tx_field CloseRemainderTo;", ep, "not an address")
testApp(t, "tx_begin; byte \"\"; tx_field AssetSender;", ep, "not an address")
// can't really tell if it's an addres, so 32 bytes gets further
testApp(t, "tx_begin; byte \"01234567890123456789012345678901\"; tx_field AssetReceiver;",
ep, "invalid Account reference")
// but a b32 string rep is not an account
testApp(t, "tx_begin; byte \"GAYTEMZUGU3DOOBZGAYTEMZUGU3DOOBZGAYTEMZUGU3DOOBZGAYZIZD42E\"; tx_field AssetCloseTo;",
ep, "not an address")

testApp(t, obfuscate("tx_begin; byte \"pay\"; tx_field Fee;"), ep, "not a uint64")
testApp(t, obfuscate("tx_begin; byte 0x01; tx_field Amount;"), ep, "not a uint64")
testApp(t, obfuscate("tx_begin; byte 0x01; tx_field XferAsset;"), ep, "not a uint64")
testApp(t, obfuscate("tx_begin; byte 0x01; tx_field AssetAmount;"), ep, "not a uint64")

}

func TestAppPay(t *testing.T) {
pay := `
tx_begin
Expand Down
15 changes: 15 additions & 0 deletions data/transactions/logic/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4573,17 +4573,21 @@ func TestShifts(t *testing.T) {
partitiontest.PartitionTest(t)

t.Parallel()
testAccepts(t, "int 1; int 0; shl; int 1; ==", 4)
testAccepts(t, "int 1; int 1; shl; int 2; ==", 4)
testAccepts(t, "int 1; int 2; shl; int 4; ==", 4)
testAccepts(t, "int 3; int 2; shl; int 12; ==", 4)
testAccepts(t, "int 2; int 63; shl; int 0; ==", 4)

testAccepts(t, "int 3; int 0; shr; int 3; ==", 4)
testAccepts(t, "int 1; int 1; shr; int 0; ==", 4)
testAccepts(t, "int 1; int 2; shr; int 0; ==", 4)
testAccepts(t, "int 3; int 1; shr; int 1; ==", 4)
testAccepts(t, "int 96; int 3; shr; int 12; ==", 4)
testAccepts(t, "int 8756675; int 63; shr; int 0; ==", 4)

testPanics(t, "int 8756675; int 64; shr; int 0; ==", 4)
testPanics(t, "int 8756675; int 64; shl; int 0; ==", 4)
}

func TestSqrt(t *testing.T) {
Expand Down Expand Up @@ -4623,6 +4627,10 @@ func TestExp(t *testing.T) {
testAccepts(t, "int 3; int 1; exp; int 3; ==", 4)
testAccepts(t, "int 96; int 3; exp; int 884736; ==", 4)
testPanics(t, "int 96; int 15; exp; int 884736; >", 4)

// These seem the same but check different code paths
testPanics(t, "int 2; int 64; exp; pop; int 1", 4)
testPanics(t, "int 4; int 32; exp; pop; int 1", 4)
}

func TestExpw(t *testing.T) {
Expand All @@ -4639,6 +4647,10 @@ func TestExpw(t *testing.T) {
testPanics(t, "int 64; int 22; expw; pop; pop; int 1", 4) // (2^6)^22 = 2^132

testAccepts(t, "int 97; int 15; expw; int 10271255586529954209; ==; assert; int 34328615749; ==;", 4)

testPanics(t, "int 2; int 128; expw; pop; pop; int 1", 4) // 2^128 is too big
// looks the same, but different code path
testPanics(t, "int 4; int 64; expw; pop; pop; int 1", 4) // 2^128 is too big
}

func TestBitLen(t *testing.T) {
Expand Down Expand Up @@ -4744,6 +4756,9 @@ func TestBytesBits(t *testing.T) {

testAccepts(t, "int 3; bzero; byte 0x000000; ==", 4)
testAccepts(t, "int 33; bzero; byte 0x000000000000000000000000000000000000000000000000000000000000000000; ==", 4)

testAccepts(t, "int 4096; bzero; len; int 4096; ==", 4)
testPanics(t, "int 4097; bzero; len; int 4097; ==", 4)
}

func TestBytesConversions(t *testing.T) {
Expand Down