Commit 066c79a8 authored by Natanael Copa's avatar Natanael Copa

community/rethinkdb: use upstream patch for openssl 1.1 support

patch is from https://github.com/rethinkdb/rethinkdb/commit/3156820e058cd410078a4c39d5a2a85f6b714c07
parent 374787a4
......@@ -2,7 +2,7 @@
# Maintainer: Daniel Treadwell <daniel@djt.id.au>
pkgname=rethinkdb
pkgver=2.3.6
pkgrel=8
pkgrel=9
pkgdesc="Distributed powerful and scalable NoSQL database"
url="https://www.rethinkdb.com"
arch="x86_64 ppc64le s390x"
......@@ -85,7 +85,7 @@ doc() {
sha512sums="653177750f7439fa1d61a121e488d578be1eab90f87c7d17ad52b9793d8543f22bbe98f8d501c2ab2d7048c65118096430fe7bde945d87c7a3228905af801af2 rethinkdb-2.3.6.tgz
9ff727feedc7a9f58e7bf8554dc26e32ebca259b2d5d75ff0d064f5aea7a54c9c94fab16b83a3bc4039d4ae6d6d805d7b129ab9d5f762186d0388adeeff6e67c libressl-all.patch
30a74f731d235aa9d914ad84ac939541c5c7c4e9b9c3a6f5e1511d8c6bd2f94c78ae603ff22d00b246992b205470ffc763faa93f19667f56a3226ef230d8ac35 openssl-1.1-all.patch
967d53a8729a01fbc67529b906fd3a62543f7f71a0086cce1128b19c90757c08ebc72cc94e8ef6b98d4adfeb33b4d214519217240b49da57da6375ff42e6ba17 openssl-1.1-all.patch
63e9b4c145617a91d00c78c980937c4f4dc010c7bc4a8db8d7ecaad47dbecd0333fcaadbfe0251dee50f44494e802db5322d8cc0096cf614f44fd4069e82f8ac enable-build-ppc64le.patch
04f6e00242ce025ba116e3dae1bf9ccd887901d9d0700faa006b72c4a1c5bd94996a9062db32b11ed0cd6a96af1f11786746ba446d288f6d921f6d93c2158cae enable-build-s390x.patch
c5a7905c116a2bf7af5ce5f8e6536c61e06ee9ac7cbead0358396e0989141890908eab694f4a88f0dcaf9f4ddcefe751dc7a949cbb4c870d87f61e720ef3b45a paxmark-x86_64.patch
......
server.cc change my original work.
s2 exactfloat changes based to upstream changes from https://github.com/google/s2geometry
From 3156820e058cd410078a4c39d5a2a85f6b714c07 Mon Sep 17 00:00:00 2001
From: Sam Hughes <sam@samuelhughes.com>
Date: Mon, 19 Jun 2017 20:27:15 -0700
Subject: [PATCH] Make BIGNUM functions in geo code avoid removed SSL API's
diff -ru rethinkdb-2.3.6.orig/src/client_protocol/server.cc rethinkdb-2.3.6/src/client_protocol/server.cc
--- rethinkdb-2.3.6.orig/src/client_protocol/server.cc 1970-01-01 02:00:01.000000000 +0200
+++ rethinkdb-2.3.6/src/client_protocol/server.cc 2019-01-02 10:25:11.885832550 +0200
@@ -174,12 +174,9 @@
- BIGNUM functions now avoid accessing ->d and ->top
- Allocates EVP_MD_CTX on the heap
- Adds the unittest BignumTest
---
src/client_protocol/server.cc | 9 +-
.../geo/s2/util/math/exactfloat/exactfloat.cc | 130 +++++++++---------
.../geo/s2/util/math/exactfloat/exactfloat.h | 27 ++--
src/unittest/bignum_test.cc | 59 ++++++++
4 files changed, 147 insertions(+), 78 deletions(-)
create mode 100644 src/unittest/bignum_test.cc
diff --git a/src/client_protocol/server.cc b/src/client_protocol/server.cc
index 4b9c4299f06..ccce61ca297 100644
--- a/src/client_protocol/server.cc
+++ b/src/client_protocol/server.cc
@@ -174,12 +174,13 @@ void http_conn_cache_t::on_ring() {
}
size_t http_conn_cache_t::sha_hasher_t::operator()(const conn_key_t &x) const {
- EVP_MD_CTX c;
- EVP_DigestInit(&c, EVP_sha256());
- EVP_DigestUpdate(&c, x.data(), x.size());
+ EVP_MD_CTX *c = EVP_MD_CTX_create();
+ EVP_DigestInit(c, EVP_sha256());
+ EVP_DigestUpdate(c, x.data(), x.size());
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_size = 0;
- EVP_DigestFinal(&c, digest, &digest_size);
+ EVP_Digest(x.data(), x.size(), digest, &digest_size, EVP_sha256(), NULL);
+ EVP_DigestFinal(c, digest, &digest_size);
+ EVP_MD_CTX_destroy(c);
rassert(digest_size >= sizeof(size_t));
size_t res = 0;
memcpy(&res, digest, std::min(sizeof(size_t), static_cast<size_t>(digest_size)));
diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc rethinkdb-2.3.6/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc
--- rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc 1970-01-01 02:00:01.000000000 +0200
+++ rethinkdb-2.3.6/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc 2019-01-02 11:02:41.502810906 +0200
@@ -86,6 +86,8 @@
#endif
diff --git a/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc b/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc
index 1f3c5c7a85f..383d040f55c 100644
--- a/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc
+++ b/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc
@@ -60,7 +60,7 @@ bool bn_is_negative_func(const BIGNUM* bn) {
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
// Count the number of low-order zero bits in the given BIGNUM (ignoring its
// sign). Returns 0 if the argument is zero.
static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
@@ -104,8 +106,35 @@
return count;
}
// Set a BIGNUM to the given unsigned 64-bit value.
-inline static void BN_ext_set_uint64(BIGNUM* bn, uint64 v) {
+void BN_ext_set_uint64(BIGNUM* bn, uint64 v) {
#if BN_BITS2 == 64
CHECK(BN_set_word(bn, v));
#else
@@ -73,39 +73,38 @@ inline static void BN_ext_set_uint64(BIGNUM* bn, uint64 v) {
+#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
// Return the absolute value of a BIGNUM as a 64-bit unsigned integer.
// Requires that BIGNUM fits into 64 bits.
-inline static uint64 BN_ext_get_uint64(const BIGNUM* bn) {
- DCHECK_LE(BN_num_bytes(bn), static_cast<int>(sizeof(uint64)));
-#if BN_BITS2 == 64
- return BN_get_word(bn);
-#else
- COMPILE_ASSERT(BN_BITS2 == 32, at_least_32_bit_openssl_build_needed);
- if (bn->top == 0) return 0;
- if (bn->top == 1) return BN_get_word(bn);
- DCHECK_EQ(bn->top, 2);
- return (static_cast<uint64>(bn->d[1]) << 32) + bn->d[0];
-#endif
+uint64 BN_ext_get_uint64(const BIGNUM* bn) {
+ int num_bytes = BN_num_bytes(bn);
+ DCHECK_LE(num_bytes, 8);
+
+static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
+ // In OpenSSL >= 1.1, BIGNUM is an opaque type, so d and top
+ // cannot be accessed. The bytes must be copied out at a ~25%
+ // performance penalty.
+ int size = BN_num_bytes(bn);
+ unsigned char bytes[size];
+ // "le" indicates little endian.
+ CHECK_EQ(BN_bn2lebinpad(bn, bytes, size), size);
+ std::unique_ptr<unsigned char[]> buf(new unsigned char[num_bytes]);
+ int res = BN_bn2bin(bn, buf.get());
+ DCHECK_EQ(num_bytes, res);
+
+ int count = 0;
+ for (unsigned char c : bytes) {
+ if (c == 0) {
+ count += 8;
+ } else {
+ for (; (c & 1) == 0; c >>= 1) {
+ ++count;
+ }
+ break;
+ }
+ uint64_t ret = 0;
+ for (int i = 0; i < res; ++i) {
+ ret = ret * 256;
+ ret += buf[i];
+ }
+ return count;
+}
+
+
+#endif
+
ExactFloat::ExactFloat(double v) {
+ return ret;
}
// Count the number of low-order zero bits in the given BIGNUM (ignoring its
// sign). Returns 0 if the argument is zero.
-static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
- int count = 0;
- for (int i = 0; i < bn->top; ++i) {
- BN_ULONG w = bn->d[i];
- if (w == 0) {
- count += 8 * sizeof(BN_ULONG);
- } else {
- for (; (w & 1) == 0; w >>= 1) {
- ++count;
+int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
+ int num_bytes = BN_num_bytes(bn);
+ for (int i = 0; i < num_bytes * 8; ++i) {
+ if (BN_is_bit_set(bn, i)) {
+ return i;
}
- break;
- }
}
- return count;
+ // They're all zero. What now? Just going to treat this as if BN_num_bytes had been
+ // zero in any case.
+ return 0;
}
-ExactFloat::ExactFloat(double v) {
- BN_init(&bn_);
+ExactFloat::ExactFloat(double v) : bn_(make_BN_new()) {
sign_ = signbit(v) ? -1 : 1;
if (std::isnan(v)) {
set_nan();
@@ -121,18 +150,17 @@
@@ -121,27 +120,26 @@ ExactFloat::ExactFloat(double v) {
int expl;
double f = frexp(fabs(v), &expl);
uint64 m = static_cast<uint64>(ldexp(f, kDoubleMantissaBits));
......@@ -78,8 +126,9 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
}
}
ExactFloat::ExactFloat(int v) {
-ExactFloat::ExactFloat(int v) {
- BN_init(&bn_);
+ExactFloat::ExactFloat(int v) : bn_(make_BN_new()) {
sign_ = (v >= 0) ? 1 : -1;
// Note that this works even for INT_MIN because the parameter type for
// BN_set_word() is unsigned.
......@@ -88,17 +137,19 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
bn_exp_ = 0;
Canonicalize();
}
@@ -140,8 +168,7 @@
ExactFloat::ExactFloat(const ExactFloat& b)
: sign_(b.sign_),
bn_exp_(b.bn_exp_) {
- bn_exp_(b.bn_exp_) {
- BN_init(&bn_);
- BN_copy(&bn_, &b.bn_);
+ bn_exp_(b.bn_exp_),
+ bn_(make_BN_new()) {
+ BN_copy(bn_.get(), b.bn_.get());
}
ExactFloat ExactFloat::SignedZero(int sign) {
@@ -163,30 +190,30 @@
@@ -163,30 +161,30 @@ ExactFloat ExactFloat::NaN() {
}
int ExactFloat::prec() const {
......@@ -134,7 +185,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
}
double ExactFloat::ToDouble() const {
@@ -200,13 +227,13 @@
@@ -200,13 +198,13 @@ double ExactFloat::ToDouble() const {
}
double ExactFloat::ToDoubleHelper() const {
......@@ -150,7 +201,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
// We rely on ldexp() to handle overflow and underflow. (It will return a
// signed zero or infinity if the result is too small or too large.)
return sign_ * ldexp(static_cast<double>(d_mantissa), bn_exp_);
@@ -257,11 +284,11 @@
@@ -257,11 +255,11 @@ ExactFloat ExactFloat::RoundToPowerOf2(int bit_exp, RoundingMode mode) const {
// Never increment.
} else if (mode == kRoundTiesAwayFromZero) {
// Increment if the highest discarded bit is 1.
......@@ -164,7 +215,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
increment = true;
} else {
DCHECK_EQ(mode, kRoundTiesToEven);
@@ -271,16 +298,16 @@
@@ -271,16 +269,16 @@ ExactFloat ExactFloat::RoundToPowerOf2(int bit_exp, RoundingMode mode) const {
// 0/10* -> Don't increment (fraction = 1/2, kept part even)
// 1/10* -> Increment (fraction = 1/2, kept part odd)
// ./1.*1.* -> Increment (fraction > 1/2)
......@@ -186,7 +237,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
}
r.sign_ = sign_;
r.Canonicalize();
@@ -387,7 +414,7 @@
@@ -387,7 +385,7 @@ int ExactFloat::GetDecimalDigits(int max_digits, std::string* digits) const {
int bn_exp10;
if (bn_exp_ >= 0) {
// The easy case: bn = bn_ * (2 ** bn_exp_)), bn_exp10 = 0.
......@@ -195,7 +246,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
bn_exp10 = 0;
} else {
// Set bn = bn_ * (5 ** -bn_exp_) and bn_exp10 = bn_exp_. This is
@@ -397,7 +424,7 @@
@@ -397,7 +395,7 @@ int ExactFloat::GetDecimalDigits(int max_digits, std::string* digits) const {
CHECK(BN_set_word(bn, 5));
BN_CTX* ctx = BN_CTX_new();
CHECK(BN_exp(bn, bn, power, ctx));
......@@ -204,7 +255,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
BN_CTX_free(ctx);
BN_free(power);
bn_exp10 = bn_exp_;
@@ -453,7 +480,7 @@
@@ -453,7 +451,7 @@ ExactFloat& ExactFloat::operator=(const ExactFloat& b) {
if (this != &b) {
sign_ = b.sign_;
bn_exp_ = b.bn_exp_;
......@@ -213,7 +264,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
}
return *this;
}
@@ -500,24 +527,24 @@
@@ -500,24 +498,24 @@ ExactFloat ExactFloat::SignedSum(int a_sign, const ExactFloat* a,
// Shift "a" if necessary so that both values have the same bn_exp_.
ExactFloat r;
if (a->bn_exp_ > b->bn_exp_) {
......@@ -244,7 +295,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
} else {
// They were equal, or the magnitude of "a" was larger.
r.sign_ = a_sign;
@@ -533,16 +560,16 @@
@@ -533,16 +531,16 @@ void ExactFloat::Canonicalize() {
// Underflow/overflow occurs if exp() is not in [kMinExp, kMaxExp].
// We also convert a zero mantissa to signed zero.
int my_exp = exp();
......@@ -266,7 +317,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
bn_exp_ += shift;
}
}
@@ -575,7 +602,7 @@
@@ -575,7 +573,7 @@ ExactFloat operator*(const ExactFloat& a, const ExactFloat& b) {
r.sign_ = result_sign;
r.bn_exp_ = a.bn_exp_ + b.bn_exp_;
BN_CTX* ctx = BN_CTX_new();
......@@ -275,7 +326,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
BN_CTX_free(ctx);
r.Canonicalize();
return r;
@@ -594,14 +621,14 @@
@@ -594,14 +592,14 @@ bool operator==(const ExactFloat& a, const ExactFloat& b) {
// Otherwise, the signs and mantissas must match. Note that non-normal
// values such as infinity have a mantissa of zero.
......@@ -293,7 +344,7 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
}
bool ExactFloat::UnsignedLess(const ExactFloat& b) const {
@@ -692,7 +719,7 @@
@@ -692,7 +690,7 @@ T ExactFloat::ToInteger(RoundingMode mode) const {
if (!r.is_inf()) {
// If the unsigned value has more than 63 bits it is always clamped.
if (r.exp() < 64) {
......@@ -302,75 +353,139 @@ diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exact
if (r.sign_ < 0) value = -value;
return max(kMinValue, min(kMaxValue, value));
}
diff -ru rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h rethinkdb-2.3.6/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h
--- rethinkdb-2.3.6.orig/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h 1970-01-01 02:00:01.000000000 +0200
+++ rethinkdb-2.3.6/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h 2019-01-02 10:49:43.488914196 +0200
@@ -174,7 +174,7 @@
diff --git a/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h b/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h
index b91290799c6..2c472778fda 100644
--- a/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h
+++ b/src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h
@@ -96,8 +96,9 @@
// The destructor is not virtual for efficiency reasons. Therefore no
// subclass should declare additional fields that require destruction.
- inline ~ExactFloat();
+ inline ~ExactFloat() = default;
#include <math.h>
#include <limits.h>
-#include <iostream>
/////////////////////////////////////////////////////////////////////
// Constants
@@ -485,6 +485,38 @@
friend ExactFloat logb(const ExactFloat& a);
+#include <iostream>
+#include <memory>
#include <string>
protected:
+ // OpenSSL >= 1.1 does not have BN_init, and does not support stack-
+ // allocated BIGNUMS. We use BN_init when possible, but BN_new otherwise.
+ // If the performance penalty is too high, an object pool can be added
+ // in the future.
+#if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x10100000L
+ // BoringSSL and OpenSSL < 1.1 support stack allocated BIGNUMs and BN_init.
+ class BigNum {
+ public:
+ BigNum() { BN_init(&bn_); }
+ // Prevent accidental, expensive, copying.
+ BigNum(const BigNum&) = delete;
+ BigNum& operator=(const BigNum&) = delete;
+ ~BigNum() { BN_free(&bn_); }
+ BIGNUM* get() { return &bn_; }
+ const BIGNUM* get() const { return &bn_; }
+ private:
+ BIGNUM bn_;
+ };
+#else
+ class BigNum {
+ public:
+ BigNum() : bn_(BN_new()) {}
+ BigNum(const BigNum&) = delete;
+ BigNum& operator=(const BigNum&) = delete;
+ ~BigNum() { BN_free(bn_); }
+ BIGNUM* get() { return bn_; }
+ const BIGNUM* get() const { return bn_; }
+ private:
+ BIGNUM* bn_;
+ };
+#endif
#include <openssl/bn.h>
@@ -107,6 +108,10 @@
namespace geo {
+struct BIGNUM_deleter {
+ void operator()(BIGNUM *b) { BN_free(b); }
+};
+
// Non-normal numbers are represented using special exponent values and a
// mantissa of zero. Do not change these values; methods such as
// is_normal() make assumptions about their ordering. Non-normal numbers
@@ -499,7 +531,7 @@
class ExactFloat {
public:
// The following limits are imposed by OpenSSL.
@@ -499,7 +504,7 @@ class ExactFloat {
// - bn_exp_ is the base-2 exponent applied to bn_.
int32 sign_;
int32 bn_exp_;
- BIGNUM bn_;
+ BigNum bn_;
+ std::unique_ptr<BIGNUM, BIGNUM_deleter> bn_;
// A standard IEEE "double" has a 53-bit mantissa consisting of a 52-bit
// fraction plus an implicit leading "1" bit.
@@ -559,11 +591,6 @@
@@ -555,16 +560,18 @@ class ExactFloat {
static ExactFloat Unimplemented();
};
+inline std::unique_ptr<BIGNUM, BIGNUM_deleter> make_BN_new() {
+ std::unique_ptr<BIGNUM, BIGNUM_deleter> ret(BN_new(), BIGNUM_deleter{});
+ guarantee(ret.get() != nullptr);
+ return ret;
+}
+
/////////////////////////////////////////////////////////////////////////
// Implementation details follow:
inline ExactFloat::ExactFloat() : sign_(1), bn_exp_(kExpZero) {
-inline ExactFloat::ExactFloat() : sign_(1), bn_exp_(kExpZero) {
- BN_init(&bn_);
-}
-
+inline ExactFloat::ExactFloat() : sign_(1), bn_exp_(kExpZero), bn_(make_BN_new()) {}
-inline ExactFloat::~ExactFloat() {
- BN_free(&bn_);
}
-}
+inline ExactFloat::~ExactFloat() {}
inline bool ExactFloat::is_zero() const { return bn_exp_ == kExpZero; }
inline bool ExactFloat::is_inf() const { return bn_exp_ == kExpInfinity; }
@@ -601,6 +608,10 @@ inline ExactFloat ExactFloat::CopyWithSign(int sign) const {
return r;
}
+void BN_ext_set_uint64(BIGNUM *bn, uint64 v);
+uint64 BN_ext_get_uint64(const BIGNUM *bn);
+int BN_ext_count_low_zero_bits(const BIGNUM *bn);
+
} // namespace geo
#endif // UTIL_MATH_EXACTFLOAT_EXACTFLOAT_H_
diff --git a/src/unittest/bignum_test.cc b/src/unittest/bignum_test.cc
new file mode 100644
index 00000000000..2aba6456103
--- /dev/null
+++ b/src/unittest/bignum_test.cc
@@ -0,0 +1,59 @@
+#include "unittest/gtest.hpp"
+
+#include "rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.h"
+
+namespace unittest {
+
+TEST(BignumTest, TestGetUint64) {
+ std::unique_ptr<BIGNUM, geo::BIGNUM_deleter> bn = geo::make_BN_new();
+
+ uint64_t x = geo::BN_ext_get_uint64(bn.get());
+ ASSERT_EQ(0, x);
+
+ uint64_t values[4] = { 1, (1ull << 32) - 1, (1ull << 32), uint64_t(-1) };
+ for (int i = 0; i < 4; ++i) {
+ geo::BN_ext_set_uint64(bn.get(), values[i]);
+ ASSERT_EQ(values[i], geo::BN_ext_get_uint64(bn.get()));
+ }
+}
+
+TEST(BignumTest, TestCountLowZeroBits) {
+ std::unique_ptr<BIGNUM, geo::BIGNUM_deleter> bn = geo::make_BN_new();
+ int n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(0, n);
+
+ geo::BN_ext_set_uint64(bn.get(), 1);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(0, n);
+
+ geo::BN_ext_set_uint64(bn.get(), 2);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(1, n);
+
+ geo::BN_ext_set_uint64(bn.get(), 128);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(7, n);
+
+ geo::BN_ext_set_uint64(bn.get(), 256);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(8, n);
+
+ geo::BN_ext_set_uint64(bn.get(), 257);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(0, n);
+
+ for (int i = 0; i < 64; i++) {
+ geo::BN_ext_set_uint64(bn.get(), (1ull << i));
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(i, n);
+ }
+
+ geo::BN_ext_set_uint64(bn.get(), (1ull << 63));
+ BN_CTX *ctx = BN_CTX_new();
+ BN_mul(bn.get(), bn.get(), bn.get(), ctx);
+ BN_CTX_free(ctx);
+ n = geo::BN_ext_count_low_zero_bits(bn.get());
+ ASSERT_EQ(126, n);
+}
+
+} // namespace unittest
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment