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:
Owain G. Ainsworth 2013-10-09 23:59:23 +01:00
parent 093ddbe193
commit 4e608c115f
2 changed files with 47 additions and 4 deletions

View file

@ -19,10 +19,11 @@ func asInt(v []byte) *big.Int {
if msb&0x80 == 0x80 {
negative = true
// remove sign bit
v[len(v)-1] &= 0x7f
msb &= 0x7f
}
start := 0
// 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]
if len(v) == 0 {
break
@ -31,7 +32,12 @@ func asInt(v []byte) *big.Int {
// reverse bytes with a copy since stack is immutable.
intArray := make([]byte, len(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)

View file

@ -8,6 +8,7 @@ import (
"bytes"
"errors"
"github.com/conformal/btcscript"
"fmt"
"math/big"
"testing"
)
@ -220,13 +221,14 @@ var stackTests = []stackTest{
},
{
"popInt 1 leading 0",
[][]byte{{0x00000001}},
[][]byte{{0x01, 0x00, 0x00, 0x00}},
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
@ -234,6 +236,41 @@ var stackTests = []stackTest{
nil,
[][]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",
[][]byte{},