diff --git a/benchmarks_test.go b/benchmarks_test.go index 7f0fca7..ab10a0c 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -198,7 +198,7 @@ func BenchmarkMul(bench *testing.B) { result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { - u256(result.Mul(a, b)) + bigU256(result.Mul(a, b)) } } @@ -226,7 +226,7 @@ func BenchmarkMulOverflow(bench *testing.B) { result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { - u256(result.Mul(a, b)) + bigU256(result.Mul(a, b)) } } @@ -251,7 +251,7 @@ func BenchmarkSquare(bench *testing.B) { result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { - u256(result.Mul(a, a)) + bigU256(result.Mul(a, a)) } } @@ -563,9 +563,9 @@ func bigExp(result, base, exponent *big.Int) *big.Int { for _, word := range exponent.Bits() { for i := 0; i < wordBits; i++ { if word&1 == 1 { - u256(result.Mul(result, base)) + bigU256(result.Mul(result, base)) } - u256(base.Mul(base, base)) + bigU256(base.Mul(base, base)) word >>= 1 } } @@ -808,7 +808,7 @@ func benchmark_SdivLarge_Big(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - u256(bigSDiv(new(big.Int), a, b)) + bigU256(bigSDiv(new(big.Int), a, b)) } } diff --git a/binary_test.go b/binary_test.go index 9820ffb..57a7a55 100644 --- a/binary_test.go +++ b/binary_test.go @@ -22,6 +22,15 @@ type binaryOpEntry struct { bigFn bigDualArgFunc } +func lookupBinary(name string) binaryOpEntry { + for _, tc := range binaryOpFuncs { + if tc.name == name { + return tc + } + } + panic(fmt.Sprintf("%v not found", name)) +} + var binaryOpFuncs = []binaryOpEntry{ {"Add", (*Int).Add, (*big.Int).Add}, {"Sub", (*Int).Sub, (*big.Int).Sub}, @@ -52,8 +61,8 @@ var cmpOpFuncs = []struct { {"Eq", (*Int).Eq, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, {"Lt", (*Int).Lt, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, {"Gt", (*Int).Gt, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, - {"Slt", (*Int).Slt, func(a, b *big.Int) bool { return S256(a).Cmp(S256(b)) < 0 }}, - {"Sgt", (*Int).Sgt, func(a, b *big.Int) bool { return S256(a).Cmp(S256(b)) > 0 }}, + {"Slt", (*Int).Slt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) < 0 }}, + {"Sgt", (*Int).Sgt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) > 0 }}, {"CmpEq", func(a, b *Int) bool { return a.Cmp(b) == 0 }, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, {"CmpLt", func(a, b *Int) bool { return a.Cmp(b) < 0 }, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, {"CmpGt", func(a, b *Int) bool { return a.Cmp(b) > 0 }, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, @@ -61,15 +70,6 @@ var cmpOpFuncs = []struct { {"GtUint64", func(a, b *Int) bool { return a.GtUint64(b.Uint64()) }, func(a, b *big.Int) bool { return a.Cmp(new(big.Int).SetUint64(b.Uint64())) > 0 }}, } -func lookupBinary(name string) binaryOpEntry { - for _, tc := range binaryOpFuncs { - if tc.name == name { - return tc - } - } - panic(fmt.Sprintf("%v not found", name)) -} - func checkBinaryOperation(t *testing.T, opName string, op opDualArgFunc, bigOp bigDualArgFunc, x, y Int) { var ( b1 = x.ToBig() @@ -159,7 +159,7 @@ func bigLsh(z, x, y *big.Int) *big.Int { } func bigSRsh(z, x, y *big.Int) *big.Int { - return z.Rsh(S256(x), uint(y.Uint64()&0x1FF)) + return z.Rsh(bigS256(x), uint(y.Uint64()&0x1FF)) } func bigExtendSign(result, num, byteNum *big.Int) *big.Int { @@ -198,8 +198,8 @@ func bigSDiv(result, x, y *big.Int) *big.Int { if y.Sign() == 0 { return result.SetUint64(0) } - sx := S256(x) - sy := S256(y) + sx := bigS256(x) + sy := bigS256(y) n := new(big.Int) if sx.Sign() == sy.Sign() { @@ -218,15 +218,47 @@ func bigSMod(result, x, y *big.Int) *big.Int { return result.SetUint64(0) } - sx := S256(x) - sy := S256(y) + sx := bigS256(x) + sy := bigS256(y) neg := sx.Sign() < 0 result.Mod(sx.Abs(sx), sy.Abs(sy)) if neg { result.Neg(result) } - return u256(result) + return bigU256(result) +} + +// divModDiv wraps DivMod and returns quotient only +func divModDiv(z, x, y *Int) *Int { + var m Int + z.DivMod(x, y, &m) + return z +} + +// divModMod wraps DivMod and returns modulus only +func divModMod(z, x, y *Int) *Int { + new(Int).DivMod(x, y, z) + return z +} + +// udivremDiv wraps udivrem and returns quotient +func udivremDiv(z, x, y *Int) *Int { + var quot Int + if !y.IsZero() { + udivrem(quot[:], x[:], y) + } + return z.Set(") +} + +// udivremMod wraps udivrem and returns remainder +func udivremMod(z, x, y *Int) *Int { + if y.IsZero() { + return z.Clear() + } + var quot Int + rem := udivrem(quot[:], x[:], y) + return z.Set(&rem) } func checkCompareOperation(t *testing.T, opName string, op opCmpArgFunc, bigOp bigCmpArgFunc, x, y Int) { diff --git a/conversion_fuzz_test.go b/conversion_fuzz_test.go new file mode 100644 index 0000000..b73ba3c --- /dev/null +++ b/conversion_fuzz_test.go @@ -0,0 +1,53 @@ +package uint256 + +import ( + "fmt" + "math/big" + "testing" +) + +func testSetFromDecForFuzzing(tc string) error { + a := new(Int).SetAllOne() + err := a.SetFromDecimal(tc) + // If input is negative, we should eror + if len(tc) > 0 && tc[0] == '-' { + if err == nil { + return fmt.Errorf("want error on negative input") + } + return nil + } + // Need to compare with big.Int + bigA, ok := big.NewInt(0).SetString(tc, 10) + if !ok { + if err == nil { + return fmt.Errorf("want error") + } + return nil // both agree that input is bad + } + if bigA.BitLen() > 256 { + if err == nil { + return fmt.Errorf("want error (bitlen > 256)") + } + return nil + } + want := bigA.String() + have := a.Dec() + if want != have { + return fmt.Errorf("want %v, have %v", want, have) + } + if _, err := a.Value(); err != nil { + return fmt.Errorf("fail to Value() %s, got err %s", tc, err) + } + return nil +} + +func FuzzSetString(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + if len(data) > 512 { + return + } + if err := testSetFromDecForFuzzing(string(data)); err != nil { + t.Fatal(err) + } + }) +} diff --git a/oss-fuzz.sh b/oss-fuzz.sh index c49df47..79a404b 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -1,12 +1,49 @@ #!/bin/bash -eu +# This sets the -coverpgk for the coverage report when the corpus is executed through go test +coverpkg="github.com/holiman/uint256/..." + +(cd /src/ && git clone https://github.com/holiman/gofuzz-shim.git ) + +function coverbuild { + path=$1 + function=$2 + fuzzer=$3 + tags="" + + if [[ $# -eq 4 ]]; then + tags="-tags $4" + fi + cd $path + fuzzed_package=`pwd | rev | cut -d'/' -f 1 | rev` + cp /src/gofuzz-shim/coverage_runner_template.txt ./"${function,,}"_test.go + sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go + sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go + sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go + +cat << DOG > $OUT/$fuzzer +#/bin/sh + + cd $OUT/$path + go test -run Test${function}Corpus -v $tags -coverprofile \$1 -coverpkg $coverpkg + +DOG + + chmod +x $OUT/$fuzzer + #echo "Built script $OUT/$fuzzer" + #cat $OUT/$fuzzer + cd - +} + +repo=/src/uint256 + function compile_fuzzer() { package=$1 function=$2 fuzzer=$3 file=$4 - path=$GOPATH/src/$package + path=$repo echo "Building $fuzzer" cd $path @@ -34,10 +71,9 @@ function compile_fuzzer() { go install github.com/holiman/gofuzz-shim@latest -repo=$GOPATH/src/github.com/holiman/uint256 -compile_fuzzer github.com/holiman/uint256 FuzzUnaryOperations fuzzUnary $repo/unary_test.go -compile_fuzzer github.com/holiman/uint256 FuzzBinaryOperations fuzzBinary $repo/binary_test.go -compile_fuzzer github.com/holiman/uint256 FuzzCompareOperations fuzzCompare $repo/binary_test.go -compile_fuzzer github.com/holiman/uint256 FuzzTernaryOperations fuzzTernary $repo/ternary_test.go -compile_fuzzer github.com/holiman/uint256 FuzzSetString fuzzSetString $repo/uint256_test.go +compile_fuzzer github.com/holiman/uint256 FuzzUnaryOperations fuzzUnary $repo/unary_test.go,$repo/shared_test.go +compile_fuzzer github.com/holiman/uint256 FuzzBinaryOperations fuzzBinary $repo/binary_test.go,$repo/shared_test.go +compile_fuzzer github.com/holiman/uint256 FuzzCompareOperations fuzzCompare $repo/binary_test.go,$repo/shared_test.go +compile_fuzzer github.com/holiman/uint256 FuzzTernaryOperations fuzzTernary $repo/ternary_test.go,$repo/shared_test.go +compile_fuzzer github.com/holiman/uint256 FuzzSetString fuzzSetString $repo/conversion_fuzz_test.go,$repo/shared_test.go diff --git a/shared_test.go b/shared_test.go new file mode 100644 index 0000000..42a2519 --- /dev/null +++ b/shared_test.go @@ -0,0 +1,133 @@ +// uint256: Fixed size 256-bit math library +// Copyright 2018-2020 uint256 Authors +// SPDX-License-Identifier: BSD-3-Clause + +package uint256 + +import ( + "crypto/rand" + "math/big" +) + +// This file contains some utilities which the oss-fuzz fuzzer shares with the +// regular go-native tests. It is placed in a separate file, becaue the oss-fuzz +// clang-based fuzzing infrastructure requires some instrumentation. +// During this instrumentation, the file under test (e.g. unary_test.go) is modified, +// and the same modification needs to be performed with any other files that +// it requires (this file). + +var ( + bigtt256 = new(big.Int).Lsh(big.NewInt(1), 256) + bigtt255 = new(big.Int).Lsh(big.NewInt(1), 255) + bigtt256m1 = new(big.Int).Sub(bigtt256, big.NewInt(1)) + + unTestCases = []string{ + "0x0", + "0x1", + "0x80000000000000000000000000000000", + "0x80000000000000010000000000000000", + "0x80000000000000000000000000000001", + "0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", + "0x8000000000000000000000000000000000000000000000000000000000000000", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + } + + // A collection of interesting input values for binary operators (especially for division). + // No expected results as big.Int can be used as the source of truth. + binTestCases = [][2]string{ + {"0x0", "0x0"}, + {"0x1", "0x0"}, + {"0x1", "0x767676767676767676000000767676767676"}, + {"0x2", "0x0"}, + {"0x2", "0x1"}, + {"0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", "0xc76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9"}, + {"0x10000000000000000", "0x2"}, + {"0x7000000000000000", "0x8000000000000000"}, + {"0x8000000000000000", "0x8000000000000000"}, + {"0x8000000000000001", "0x8000000000000000"}, + {"0x80000000000000010000000000000000", "0x80000000000000000000000000000000"}, + {"0x80000000000000000000000000000000", "0x80000000000000000000000000000001"}, + {"0x478392145435897052", "0x111"}, + {"0x767676767676767676000000767676767676", "0x2900760076761e00020076760000000076767676000000"}, + {"0x12121212121212121212121212121212", "0x232323232323232323"}, + {"0xfffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00", "0xfffff716b61616160b0b0b2b0b230b000008010d0a2b00"}, + {"0x50beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00", "0x2000110000000d0a300e750a000000090a0a"}, + {"0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000", "0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a"}, + {"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "0x7"}, + {"0xf6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0", "0xb368d219438b7f3f"}, + {"0x0", "0x10900000000000000000000000000000000000000000000000000"}, + {"0x77676767676760000000000000001002e000000000000040000000e000000000", "0xfffc000000000000767676240000000000002b0576047"}, + {"0x767676767676000000000076000000000000005600000000000000000000", "0x767676767676000000000076000000760000"}, + {"0x8200000000000000000000000000000000000000000000000000000000000000", "0x8200000000000000fe000004000000ffff000000fffff700"}, + {"0xdac7fff9ffd9e1322626262626262600", "0xd021262626262626"}, + {"0x8000000000000001800000000000000080000000000000008000000000000000", "0x800000000000000080000000000000008000000000000000"}, + {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xe8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff"}, + {"0xc9700000000000000000023f00c00014ff000000000000000022300805", "0xc9700000000000000000023f00c00014ff002c000000000000223108"}, + {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db000001"}, + {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db0000d3"}, + {"0x1f000000000000000000000000000000200000000100000000000000000000", "0x100000000ffffffffffffffff0000000000002e000000"}, + {"0x7effffff80000000000000000000000000020000440000000000000000000001", "0x7effffff800000007effffff800000008000ff0000010000"}, + {"0x5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001", "0x2ffffffffffffffffffffffffffffffffff000000030000"}, + {"0x62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001", "0x2ffffffffffffffffffffffffffffffffff200000000000"}, + {"0x7effffff8000000000000000000000000000000000000000d900000000000001", "0x7effffff8000000000000000000000000000000000008001"}, + {"0x6400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a", "0x210000000000000022"}, + {"0x6d5adef08547abf7eb", "0x13590cab83b779e708b533b0eef3561483ddeefc841f5"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xffffffffffffffff7effffff800000007effffff800000008000ff0000010000"}, + {"0x1ce97e1ab91a", "0x66aa0a5319bcf5cb4"}, // regression test for udivrem() where len(x) < len(y) + } + + // A collection of interesting input values for ternary operators (addmod, mulmod). + ternTestCases = [][3]string{ + {"0x0", "0x0", "0x0"}, + {"0x1", "0x0", "0x0"}, + {"0x1", "0x1", "0x0"}, + {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x0"}, + {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0x3", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1"}, + {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000002"}, + {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000001"}, + {"0xffffffffffffffffffffffffffff000004020041fffffffffc00000060000020", "0xffffffffffffffffffffffffffffffe6000000ffffffe60000febebeffffffff", "0xffffffffffffffffffe6000000ffffffe60000febebeffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffff00ffffe6ff0000000000000060000020", "0xffffffffffffffffffffffffffffffffffe6000000ffff00e60000febebeffff", "0xffffffffffffffffffe6000000ffff00e60000fe0000ffff00e60000febebeff"}, + {"0xfffffffffffffffffffffffff600000000005af50100bebe000000004a00be0a", "0xffffffffffffffffffffffffffffeaffdfd9fffffffffffff5f60000000000ff", "0xffffffffffffffffffffffeaffdfd9fffffffffffffff60000000000ffffffff"}, + {"0x8000000000000001000000000000000000000000000000000000000000000000", "0x800000000000000100000000000000000000000000000000000000000000000b", "0x8000000000000000000000000000000000000000000000000000000000000000"}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000000"}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000"}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000100000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000001"}, + {"0x1", "0x1", "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"}, + {"0x1", "0x1", "0x1000000003030303030303030303030303030303030303030303030303030"}, + {"0x1", "0x1", "0x4000000000000000130303030303030303030303030303030303030303030"}, + {"0x1", "0x1", "0x8000000000000000000000000000000043030303000000000"}, + {"0x1", "0x1", "0x8000000000000000000000000000000003030303030303030"}, + } +) + +// bigU256 encodes as a 256 bit two's complement number. This operation is destructive. +func bigU256(x *big.Int) *big.Int { + return x.And(x, bigtt256m1) +} + +func bigS256(x *big.Int) *big.Int { + if x.Cmp(bigtt255) < 0 { + return x + } + return new(big.Int).Sub(x, bigtt256) +} + +func randNum() *Int { + //How many bits? 0-256 + nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) + //Max random value, a 130-bits integer, i.e 2^130 + max := new(big.Int) + max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) + b, _ := rand.Int(rand.Reader, max) + f, _ := FromBig(b) + return f +} diff --git a/uint256_test.go b/uint256_test.go index 03c5e6a..8b75c71 100644 --- a/uint256_test.go +++ b/uint256_test.go @@ -14,98 +14,6 @@ import ( "testing" ) -var ( - bigtt256 = new(big.Int).Lsh(big.NewInt(1), 256) - bigtt255 = new(big.Int).Lsh(big.NewInt(1), 255) - - unTestCases = []string{ - "0x0", - "0x1", - "0x80000000000000000000000000000000", - "0x80000000000000010000000000000000", - "0x80000000000000000000000000000001", - "0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", - "0x8000000000000000000000000000000000000000000000000000000000000000", - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - } - - // A collection of interesting input values for binary operators (especially for division). - // No expected results as big.Int can be used as the source of truth. - binTestCases = [][2]string{ - {"0x0", "0x0"}, - {"0x1", "0x0"}, - {"0x1", "0x767676767676767676000000767676767676"}, - {"0x2", "0x0"}, - {"0x2", "0x1"}, - {"0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", "0xc76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9"}, - {"0x10000000000000000", "0x2"}, - {"0x7000000000000000", "0x8000000000000000"}, - {"0x8000000000000000", "0x8000000000000000"}, - {"0x8000000000000001", "0x8000000000000000"}, - {"0x80000000000000010000000000000000", "0x80000000000000000000000000000000"}, - {"0x80000000000000000000000000000000", "0x80000000000000000000000000000001"}, - {"0x478392145435897052", "0x111"}, - {"0x767676767676767676000000767676767676", "0x2900760076761e00020076760000000076767676000000"}, - {"0x12121212121212121212121212121212", "0x232323232323232323"}, - {"0xfffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00", "0xfffff716b61616160b0b0b2b0b230b000008010d0a2b00"}, - {"0x50beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00", "0x2000110000000d0a300e750a000000090a0a"}, - {"0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000", "0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a"}, - {"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "0x7"}, - {"0xf6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0", "0xb368d219438b7f3f"}, - {"0x0", "0x10900000000000000000000000000000000000000000000000000"}, - {"0x77676767676760000000000000001002e000000000000040000000e000000000", "0xfffc000000000000767676240000000000002b0576047"}, - {"0x767676767676000000000076000000000000005600000000000000000000", "0x767676767676000000000076000000760000"}, - {"0x8200000000000000000000000000000000000000000000000000000000000000", "0x8200000000000000fe000004000000ffff000000fffff700"}, - {"0xdac7fff9ffd9e1322626262626262600", "0xd021262626262626"}, - {"0x8000000000000001800000000000000080000000000000008000000000000000", "0x800000000000000080000000000000008000000000000000"}, - {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xe8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff"}, - {"0xc9700000000000000000023f00c00014ff000000000000000022300805", "0xc9700000000000000000023f00c00014ff002c000000000000223108"}, - {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db000001"}, - {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db0000d3"}, - {"0x1f000000000000000000000000000000200000000100000000000000000000", "0x100000000ffffffffffffffff0000000000002e000000"}, - {"0x7effffff80000000000000000000000000020000440000000000000000000001", "0x7effffff800000007effffff800000008000ff0000010000"}, - {"0x5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001", "0x2ffffffffffffffffffffffffffffffffff000000030000"}, - {"0x62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001", "0x2ffffffffffffffffffffffffffffffffff200000000000"}, - {"0x7effffff8000000000000000000000000000000000000000d900000000000001", "0x7effffff8000000000000000000000000000000000008001"}, - {"0x6400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a", "0x210000000000000022"}, - {"0x6d5adef08547abf7eb", "0x13590cab83b779e708b533b0eef3561483ddeefc841f5"}, - {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xffffffffffffffff7effffff800000007effffff800000008000ff0000010000"}, - {"0x1ce97e1ab91a", "0x66aa0a5319bcf5cb4"}, // regression test for udivrem() where len(x) < len(y) - } - - // A collection of interesting input values for ternary operators (addmod, mulmod). - ternTestCases = [][3]string{ - {"0x0", "0x0", "0x0"}, - {"0x1", "0x0", "0x0"}, - {"0x1", "0x1", "0x0"}, - {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x0"}, - {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0x3", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, - {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2"}, - {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1"}, - {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000002"}, - {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000001"}, - {"0xffffffffffffffffffffffffffff000004020041fffffffffc00000060000020", "0xffffffffffffffffffffffffffffffe6000000ffffffe60000febebeffffffff", "0xffffffffffffffffffe6000000ffffffe60000febebeffffffffffffffffffff"}, - {"0xffffffffffffffffffffffffffffffff00ffffe6ff0000000000000060000020", "0xffffffffffffffffffffffffffffffffffe6000000ffff00e60000febebeffff", "0xffffffffffffffffffe6000000ffff00e60000fe0000ffff00e60000febebeff"}, - {"0xfffffffffffffffffffffffff600000000005af50100bebe000000004a00be0a", "0xffffffffffffffffffffffffffffeaffdfd9fffffffffffff5f60000000000ff", "0xffffffffffffffffffffffeaffdfd9fffffffffffffff60000000000ffffffff"}, - {"0x8000000000000001000000000000000000000000000000000000000000000000", "0x800000000000000100000000000000000000000000000000000000000000000b", "0x8000000000000000000000000000000000000000000000000000000000000000"}, - {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000000"}, - {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000"}, - {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000100000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000001"}, - {"0x1", "0x1", "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"}, - {"0x1", "0x1", "0x1000000003030303030303030303030303030303030303030303030303030"}, - {"0x1", "0x1", "0x4000000000000000130303030303030303030303030303030303030303030"}, - {"0x1", "0x1", "0x8000000000000000000000000000000043030303000000000"}, - {"0x1", "0x1", "0x8000000000000000000000000000000003030303030303030"}, - } -) - func hex2Bytes(str string) []byte { h, _ := hex.DecodeString(str) return h @@ -120,17 +28,6 @@ func checkOverflow(b *big.Int, f *Int, overflow bool) error { return nil } -func randNum() *Int { - //How many bits? 0-256 - nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) - //Max random value, a 130-bits integer, i.e 2^130 - max := new(big.Int) - max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) - b, _ := rand.Int(rand.Reader, max) - f, _ := FromBig(b) - return f -} - func randNums() (*big.Int, *Int) { //How many bits? 0-256 nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) @@ -209,38 +106,6 @@ func TestRandomMulOverflow(t *testing.T) { } } -// divModDiv wraps DivMod and returns quotient only -func divModDiv(z, x, y *Int) *Int { - var m Int - z.DivMod(x, y, &m) - return z -} - -// divModMod wraps DivMod and returns modulus only -func divModMod(z, x, y *Int) *Int { - new(Int).DivMod(x, y, z) - return z -} - -// udivremDiv wraps udivrem and returns quotient -func udivremDiv(z, x, y *Int) *Int { - var quot Int - if !y.IsZero() { - udivrem(quot[:], x[:], y) - } - return z.Set(") -} - -// udivremMod wraps udivrem and returns remainder -func udivremMod(z, x, y *Int) *Int { - if y.IsZero() { - return z.Clear() - } - var quot Int - rem := udivrem(quot[:], x[:], y) - return z.Set(&rem) -} - func set3Int(s1, s2, s3, d1, d2, d3 *Int) { d1.Set(s1) d2.Set(s2) @@ -596,18 +461,10 @@ func TestRandomMulDivOverflow(t *testing.T) { } } -func S256(x *big.Int) *big.Int { - if x.Cmp(bigtt255) < 0 { - return x - } else { - return new(big.Int).Sub(x, bigtt256) - } -} - func TestRandomAbs(t *testing.T) { for i := 0; i < 10000; i++ { b, f1 := randHighNums() - b2 := S256(big.NewInt(0).Set(b)) + b2 := bigS256(big.NewInt(0).Set(b)) b2.Abs(b2) f1a := new(Int).Abs(f1) @@ -757,7 +614,7 @@ func TestAddSubUint64(t *testing.T) { bigArg, _ := new(big.Int).SetString(tc.arg, 0) arg, _ := FromBig(bigArg) { // SubUint64 - want, _ := FromBig(u256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) + want, _ := FromBig(bigU256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) have := new(Int).SetAllOne().SubUint64(arg, tc.n) if !have.Eq(want) { t.Logf("args: %s, %d\n", tc.arg, tc.n) @@ -767,7 +624,7 @@ func TestAddSubUint64(t *testing.T) { } } { // AddUint64 - want, _ := FromBig(u256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) + want, _ := FromBig(bigU256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) have := new(Int).AddUint64(arg, tc.n) if !have.Eq(want) { t.Logf("args: %s, %d\n", tc.arg, tc.n) @@ -801,15 +658,6 @@ const ( wordBits = 32 << (uint64(^big.Word(0)) >> 63) ) -var ( - tt256m1 = new(big.Int).Sub(bigtt256, big.NewInt(1)) -) - -// u256 encodes as a 256 bit two's complement number. This operation is destructive. -func u256(x *big.Int) *big.Int { - return x.And(x, tt256m1) -} - // TestFixedExpReusedArgs tests the cases in Exp() where the arguments (including result) alias the same objects. func TestFixedExpReusedArgs(t *testing.T) { f2 := Int{2, 0, 0, 0} @@ -1108,49 +956,3 @@ func TestCmpBig(t *testing.T) { check(z, new(big.Int).Lsh(new(Int).Set(z).ToBig(), 256)) // z, z << 256 } } - -func testSetFromDecForFuzzing(tc string) error { - a := new(Int).SetAllOne() - err := a.SetFromDecimal(tc) - // If input is negative, we should eror - if len(tc) > 0 && tc[0] == '-' { - if err == nil { - return fmt.Errorf("want error on negative input") - } - return nil - } - // Need to compare with big.Int - bigA, ok := big.NewInt(0).SetString(tc, 10) - if !ok { - if err == nil { - return fmt.Errorf("want error") - } - return nil // both agree that input is bad - } - if bigA.BitLen() > 256 { - if err == nil { - return fmt.Errorf("want error (bitlen > 256)") - } - return nil - } - want := bigA.String() - have := a.Dec() - if want != have { - return fmt.Errorf("want %v, have %v", want, have) - } - if _, err := a.Value(); err != nil { - return fmt.Errorf("fail to Value() %s, got err %s", tc, err) - } - return nil -} - -func FuzzSetString(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - if len(data) > 512 { - return - } - if err := testSetFromDecForFuzzing(string(data)); err != nil { - t.Fatal(err) - } - }) -} diff --git a/unary_test.go b/unary_test.go index fe5a54b..4a1319a 100644 --- a/unary_test.go +++ b/unary_test.go @@ -26,7 +26,7 @@ var unaryOpFuncs = []struct { res.squared() return x.Set(res) }, func(b1, b2 *big.Int) *big.Int { return b1.Mul(b2, b2) }}, - {"Abs", (*Int).Abs, func(b1, b2 *big.Int) *big.Int { return b1.Abs(S256(b2)) }}, + {"Abs", (*Int).Abs, func(b1, b2 *big.Int) *big.Int { return b1.Abs(bigS256(b2)) }}, } func checkUnaryOperation(t *testing.T, opName string, op opUnaryArgFunc, bigOp bigUnaryArgFunc, x Int) {