merge revision(s) 55047: [Backport #12441]

* ext/openssl/ossl_bn.c (try_convert_to_bnptr): Extracted from
	  GetBNPtr(). This doesn't raise exception but returns NULL on error.
	  (GetBNPtr): Raise TypeError if conversion fails.
	  (ossl_bn_eq): Implement BN#==.
	  (ossl_bn_eql): #eql? should not raise TypeError even if the argument
	  is not compatible with BN.
	  (ossl_bn_hash): Implement BN#hash.

	* ext/openssl/ossl_bn.c (Init_ossl_bn): Define #== and #hash.

	* test/openssl/test_bn.rb: Test BN#eql?, #== and #hash


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@55937 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
usa 2016-08-16 11:55:03 +00:00
parent b76d7afffc
commit a1af71552f
4 changed files with 108 additions and 15 deletions

View file

@ -1,3 +1,17 @@
Tue Aug 16 20:40:36 2016 Kazuki Yamaguchi <k@rhe.jp>
* ext/openssl/ossl_bn.c (try_convert_to_bnptr): Extracted from
GetBNPtr(). This doesn't raise exception but returns NULL on error.
(GetBNPtr): Raise TypeError if conversion fails.
(ossl_bn_eq): Implement BN#==.
(ossl_bn_eql): #eql? should not raise TypeError even if the argument
is not compatible with BN.
(ossl_bn_hash): Implement BN#hash.
* ext/openssl/ossl_bn.c (Init_ossl_bn): Define #== and #hash.
* test/openssl/test_bn.rb: Test BN#eql?, #== and #hash
Tue Aug 16 20:34:22 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> Tue Aug 16 20:34:22 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* transcode.c (str_transcode0): scrub in the given encoding when * transcode.c (str_transcode0): scrub in the given encoding when

View file

@ -73,8 +73,8 @@ ossl_bn_new(const BIGNUM *bn)
return obj; return obj;
} }
BIGNUM * static BIGNUM *
GetBNPtr(VALUE obj) try_convert_to_bnptr(VALUE obj)
{ {
BIGNUM *bn = NULL; BIGNUM *bn = NULL;
@ -89,14 +89,20 @@ GetBNPtr(VALUE obj)
} }
WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */ WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */
break; break;
case T_NIL:
break;
default:
ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
} }
return bn; return bn;
} }
BIGNUM *
GetBNPtr(VALUE obj)
{
BIGNUM *bn = try_convert_to_bnptr(obj);
if (!bn)
ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
return bn;
}
/* /*
* Private * Private
*/ */
@ -708,15 +714,79 @@ ossl_bn_copy(VALUE self, VALUE other)
BIGNUM_CMP(cmp) BIGNUM_CMP(cmp)
BIGNUM_CMP(ucmp) BIGNUM_CMP(ucmp)
/*
* call-seq:
* bn == obj => true or false
*
* Returns +true+ only if +obj+ has the same value as +bn+. Contrast this
* with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN.
*/
static VALUE static VALUE
ossl_bn_eql(VALUE self, VALUE other) ossl_bn_eq(VALUE self, VALUE other)
{ {
if (ossl_bn_cmp(self, other) == INT2FIX(0)) { BIGNUM *bn1, *bn2;
GetBN(self, bn1);
/* BNPtr may raise, so we can't use here */
bn2 = try_convert_to_bnptr(other);
if (bn2 && !BN_cmp(bn1, bn2)) {
return Qtrue; return Qtrue;
} }
return Qfalse; return Qfalse;
} }
/*
* call-seq:
* bn.eql?(obj) => true or false
*
* Returns <code>true</code> only if <i>obj</i> is a
* <code>OpenSSL::BN</code> with the same value as <i>big</i>. Contrast this
* with OpenSSL::BN#==, which performs type conversions.
*/
static VALUE
ossl_bn_eql(VALUE self, VALUE other)
{
BIGNUM *bn1, *bn2;
if (!rb_obj_is_kind_of(other, cBN))
return Qfalse;
GetBN(self, bn1);
GetBN(other, bn2);
return BN_cmp(bn1, bn2) ? Qfalse : Qtrue;
}
/*
* call-seq:
* bn.hash => Integer
*
* Returns a hash code for this object.
*
* See also Object#hash.
*/
static VALUE
ossl_bn_hash(VALUE self)
{
BIGNUM *bn;
VALUE hash;
unsigned char *buf;
int len;
GetBN(self, bn);
len = BN_num_bytes(bn);
buf = xmalloc(len);
if (BN_bn2bin(bn, buf) != len) {
xfree(buf);
ossl_raise(eBNError, NULL);
}
hash = INT2FIX(rb_memhash(buf, len));
xfree(buf);
return hash;
}
/* /*
* call-seq: * call-seq:
* bn.prime? => true | false * bn.prime? => true | false
@ -844,8 +914,9 @@ Init_ossl_bn(void)
rb_define_alias(cBN, "<=>", "cmp"); rb_define_alias(cBN, "<=>", "cmp");
rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
rb_define_method(cBN, "eql?", ossl_bn_eql, 1); rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
rb_define_alias(cBN, "==", "eql?"); rb_define_method(cBN, "hash", ossl_bn_hash, 0);
rb_define_alias(cBN, "===", "eql?"); rb_define_method(cBN, "==", ossl_bn_eq, 1);
rb_define_alias(cBN, "===", "==");
rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
rb_define_method(cBN, "one?", ossl_bn_is_one, 0); rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
/* is_word */ /* is_word */

View file

@ -42,10 +42,18 @@ class OpenSSL::TestBN < Test::Unit::TestCase
assert_equal(true, OpenSSL::BN.new((2 ** 127 - 1).to_s(16), 16).prime?(1)) assert_equal(true, OpenSSL::BN.new((2 ** 127 - 1).to_s(16), 16).prime?(1))
end end
def test_cmp_nil def test_cmp
bn = OpenSSL::BN.new('1') bn1 = OpenSSL::BN.new('1')
assert_equal(false, bn == nil) bn2 = OpenSSL::BN.new('1')
assert_equal(true, bn != nil) bn3 = OpenSSL::BN.new('2')
assert_equal(false, bn1 == nil)
assert_equal(true, bn1 != nil)
assert_equal(true, bn1 == bn2)
assert_equal(false, bn1 == bn3)
assert_equal(true, bn1.eql?(bn2))
assert_equal(false, bn1.eql?(bn3))
assert_equal(bn1.hash, bn2.hash)
assert_not_equal(bn3.hash, bn1.hash)
end end
end end

View file

@ -1,6 +1,6 @@
#define RUBY_VERSION "2.2.6" #define RUBY_VERSION "2.2.6"
#define RUBY_RELEASE_DATE "2016-08-16" #define RUBY_RELEASE_DATE "2016-08-16"
#define RUBY_PATCHLEVEL 363 #define RUBY_PATCHLEVEL 364
#define RUBY_RELEASE_YEAR 2016 #define RUBY_RELEASE_YEAR 2016
#define RUBY_RELEASE_MONTH 8 #define RUBY_RELEASE_MONTH 8