Skip to content
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
6 changes: 5 additions & 1 deletion price/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"math/bits"
"regexp"
"strconv"
"strings"

"github.com/stellar/go-stellar-sdk/xdr"
)
Expand All @@ -23,7 +24,7 @@ var (
// to `big.Rat.SetString` triggering long calculations.
// Note: {1,20} because the biggest amount you can use in Stellar is:
// len("922337203685.4775807") = 20.
validAmountSimple = regexp.MustCompile("^-?[.0-9]{1,20}$")
validAmountSimple = regexp.MustCompile("^[.0-9]{1,20}$")
// ErrDivisionByZero is returned when a price operation would result in a division by 0
ErrDivisionByZero = errors.New("division by 0")
// ErrOverflow is returned when a price operation would result in an integer overflow
Expand Down Expand Up @@ -52,6 +53,9 @@ func MustParse(v string) xdr.Price {
// continuedFraction calculates and returns the best rational approximation of
// the given real number.
func continuedFraction(price string) (xdrPrice xdr.Price, err error) {
if strings.HasPrefix(price, "-") {
return xdrPrice, ErrNoNegatives
}
if !validAmountSimple.MatchString(price) {
return xdrPrice, fmt.Errorf("invalid price format: %s", price)
}
Expand Down
35 changes: 35 additions & 0 deletions price/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,41 @@ func TestParse(t *testing.T) {
}
}

func TestParseRejectsNegatives(t *testing.T) {
inputs := []string{
"-1",
"-0.5",
"-0",
"-0.0",
"-2147483647",
"-2147483648",
// These wrap on the int64 -> int32 narrowing and used to come back
// as valid positive prices.
"-2147483649",
"-2147483647.9",
"-4294967295",
"-4294967296",
}
for _, in := range inputs {
_, err := Parse(in)
assert.ErrorIs(t, err, ErrNoNegatives, "input %q", in)
}
}

// Every price Parse returns without error must also pass xdr.Price.Validate.
func TestParseOutputIsValid(t *testing.T) {
for _, v := range Tests {
if !v.V {
continue
}
o, err := Parse(v.S)
if !assert.NoError(t, err, "input %q", v.S) {
continue
}
assert.NoError(t, o.Validate(), "input %q", v.S)
}
}

func TestStringFromFloat64(t *testing.T) {

tests := map[float64]string{
Expand Down
Loading