Prevent asInt() from modifying stack data.
The stack data is normally sliced from the actual script and btcscript is not supposed to ever change the tx passed into it. Add a test (and fix the other leading zeros tests) to stop this happening again.
This commit is contained in:
parent
093ddbe193
commit
4e608c115f
2 changed files with 47 additions and 4 deletions
12
stack.go
12
stack.go
|
@ -19,10 +19,11 @@ func asInt(v []byte) *big.Int {
|
||||||
if msb&0x80 == 0x80 {
|
if msb&0x80 == 0x80 {
|
||||||
negative = true
|
negative = true
|
||||||
// remove sign bit
|
// remove sign bit
|
||||||
v[len(v)-1] &= 0x7f
|
msb &= 0x7f
|
||||||
}
|
}
|
||||||
|
start := 0
|
||||||
// trim leading 0 bytes
|
// trim leading 0 bytes
|
||||||
for ; msb == 0; msb = v[len(v)-1] {
|
for ; msb == 0; msb, start = v[len(v)-1], start+1 {
|
||||||
v = v[:len(v)-1]
|
v = v[:len(v)-1]
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
break
|
break
|
||||||
|
@ -31,7 +32,12 @@ func asInt(v []byte) *big.Int {
|
||||||
// reverse bytes with a copy since stack is immutable.
|
// reverse bytes with a copy since stack is immutable.
|
||||||
intArray := make([]byte, len(v))
|
intArray := make([]byte, len(v))
|
||||||
for i := range v {
|
for i := range v {
|
||||||
intArray[len(v)-i-1] = v[i]
|
// Mask off the sign bit without changing original array.
|
||||||
|
if i == 0 && start == 0 && negative {
|
||||||
|
intArray[len(v)-i -1] = v[i] & 0x7f
|
||||||
|
} else {
|
||||||
|
intArray[len(v)-i-1] = v[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
num := new(big.Int).SetBytes(intArray)
|
num := new(big.Int).SetBytes(intArray)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/conformal/btcscript"
|
"github.com/conformal/btcscript"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -220,13 +221,14 @@ var stackTests = []stackTest{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"popInt 1 leading 0",
|
"popInt 1 leading 0",
|
||||||
[][]byte{{0x00000001}},
|
[][]byte{{0x01, 0x00, 0x00, 0x00}},
|
||||||
func(stack *btcscript.Stack) error {
|
func(stack *btcscript.Stack) error {
|
||||||
v, err := stack.PopInt()
|
v, err := stack.PopInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if v.Cmp(big.NewInt(1)) != 0 {
|
if v.Cmp(big.NewInt(1)) != 0 {
|
||||||
|
fmt.Printf("%v != %v\n", v, big.NewInt(1))
|
||||||
return errors.New("1 != 1 on popInt")
|
return errors.New("1 != 1 on popInt")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -234,6 +236,41 @@ var stackTests = []stackTest{
|
||||||
nil,
|
nil,
|
||||||
[][]byte{},
|
[][]byte{},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"popInt -1 leading 0",
|
||||||
|
[][]byte{{0x01,0x00, 0x00, 0x80}},
|
||||||
|
func(stack *btcscript.Stack) error {
|
||||||
|
v, err := stack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if v.Cmp(big.NewInt(-1)) != 0 {
|
||||||
|
fmt.Printf("%v != %v\n", v, big.NewInt(-1))
|
||||||
|
return errors.New("-1 != -1 on popInt")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[][]byte{},
|
||||||
|
},
|
||||||
|
// Confirm that the asInt code doesn't modify the base data.
|
||||||
|
{
|
||||||
|
"peekint nomodify -1",
|
||||||
|
[][]byte{{0x01,0x00, 0x00, 0x80}},
|
||||||
|
func(stack *btcscript.Stack) error {
|
||||||
|
v, err := stack.PeekInt(0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if v.Cmp(big.NewInt(-1)) != 0 {
|
||||||
|
fmt.Printf("%v != %v\n", v, big.NewInt(-1))
|
||||||
|
return errors.New("-1 != -1 on popInt")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
[][]byte{{0x01,0x00, 0x00, 0x80}},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"PushInt 0",
|
"PushInt 0",
|
||||||
[][]byte{},
|
[][]byte{},
|
||||||
|
|
Loading…
Reference in a new issue