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 { 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)

View file

@ -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{},