diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-11-15 17:11:48 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2016-11-15 17:11:48 +0900 |
commit | fd0c4344c1210cc5fee359b59705e3ab4a7b5459 (patch) | |
tree | efc01e1d8f09bc7f15aa6eece8de6660ddadb685 /ext/openssl | |
parent | 072d53ecf9844d4080d7fffdf5ef9434d0a9ab82 (diff) | |
download | ruby-openssl-fd0c4344c1210cc5fee359b59705e3ab4a7b5459.tar.gz |
digest: don't allocate EVP_MD_CTX at OpenSSL::Digest object allocation
Delay allocation of EVP_MD_CTX until #initialize or #initialize_copy is
called. This fixes segfault that can occur if OpenSSL::Digest#name is
called before the actual initialization.
Diffstat (limited to 'ext/openssl')
-rw-r--r-- | ext/openssl/ossl_digest.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index 44d96183..fdafda00 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -80,10 +80,13 @@ ossl_digest_new(const EVP_MD *md) EVP_MD_CTX *ctx; ret = ossl_digest_alloc(cDigest); - GetDigest(ret, ctx); - if (EVP_DigestInit_ex(ctx, md, NULL) != 1) { - ossl_raise(eDigestError, "Digest initialization failed."); - } + ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); + RTYPEDDATA_DATA(ret) = ctx; + + if (!EVP_DigestInit_ex(ctx, md, NULL)) + ossl_raise(eDigestError, "Digest initialization failed"); return ret; } @@ -94,13 +97,7 @@ ossl_digest_new(const EVP_MD *md) static VALUE ossl_digest_alloc(VALUE klass) { - VALUE obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, 0); - EVP_MD_CTX *ctx = EVP_MD_CTX_create(); - if (ctx == NULL) - ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed"); - RTYPEDDATA_DATA(obj) = ctx; - - return obj; + return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0); } VALUE ossl_digest_update(VALUE, VALUE); @@ -133,11 +130,16 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self) md = GetDigestPtr(type); if (!NIL_P(data)) StringValue(data); - GetDigest(self, ctx); - if (EVP_DigestInit_ex(ctx, md, NULL) != 1) { - ossl_raise(eDigestError, "Digest initialization failed."); + TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx); + if (!ctx) { + RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new(); + if (!ctx) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); } + if (!EVP_DigestInit_ex(ctx, md, NULL)) + ossl_raise(eDigestError, "Digest initialization failed"); + if (!NIL_P(data)) return ossl_digest_update(self, data); return self; } @@ -150,7 +152,12 @@ ossl_digest_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; - GetDigest(self, ctx1); + TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1); + if (!ctx1) { + RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new(); + if (!ctx1) + ossl_raise(eDigestError, "EVP_MD_CTX_new"); + } SafeGetDigest(other, ctx2); if (!EVP_MD_CTX_copy(ctx1, ctx2)) { |