@@ -426,6 +426,72 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
426426#endif
427427}
428428
429+ #if defined(OSSL_DEBUG )
430+ #if !defined(LIBRESSL_VERSION_NUMBER ) && \
431+ (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG ) || \
432+ defined(CRYPTO_malloc_debug_init ))
433+ /*
434+ * call-seq:
435+ * OpenSSL.mem_check_start -> nil
436+ *
437+ * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
438+ * allocations. See also OpenSSL.print_mem_leaks.
439+ *
440+ * This is available only when built with a capable OpenSSL and --enable-debug
441+ * configure option.
442+ */
443+ static VALUE
444+ mem_check_start (VALUE self )
445+ {
446+ CRYPTO_mem_ctrl (CRYPTO_MEM_CHECK_ON );
447+ return Qnil ;
448+ }
449+
450+ /*
451+ * call-seq:
452+ * OpenSSL.print_mem_leaks -> true | false
453+ *
454+ * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
455+ * Prints detected memory leaks to standard error. This cleans the global state
456+ * up thus you cannot use any methods of the library after calling this.
457+ *
458+ * Returns true if leaks detected, false otherwise.
459+ *
460+ * This is available only when built with a capable OpenSSL and --enable-debug
461+ * configure option.
462+ *
463+ * === Example
464+ * OpenSSL.mem_check_start
465+ * NOT_GCED = OpenSSL::PKey::RSA.new(256)
466+ *
467+ * END {
468+ * GC.start
469+ * OpenSSL.print_mem_leaks # will print the leakage
470+ * }
471+ */
472+ static VALUE
473+ print_mem_leaks (VALUE self )
474+ {
475+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
476+ int ret ;
477+ #endif
478+
479+ BN_CTX_free (ossl_bn_ctx );
480+ ossl_bn_ctx = NULL ;
481+
482+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
483+ ret = CRYPTO_mem_leaks_fp (stderr );
484+ if (ret < 0 )
485+ ossl_raise (eOSSLError , "CRYPTO_mem_leaks_fp" );
486+ return ret ? Qfalse : Qtrue ;
487+ #else
488+ CRYPTO_mem_leaks_fp (stderr );
489+ return Qnil ;
490+ #endif
491+ }
492+ #endif
493+ #endif
494+
429495#if !defined(HAVE_OPENSSL_110_THREADING_API )
430496/**
431497 * Stores locks needed for OpenSSL thread safety
@@ -1114,15 +1180,40 @@ Init_openssl(void)
11141180 Init_ossl_ocsp ();
11151181 Init_ossl_engine ();
11161182 Init_ossl_asn1 ();
1117- }
11181183
11191184#if defined(OSSL_DEBUG )
1120- /*
1121- * Check if all symbols are OK with 'make LDSHARED=gcc all'
1122- */
1123- int
1124- main (int argc , char * argv [])
1125- {
1126- return 0 ;
1185+ /*
1186+ * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug
1187+ */
1188+ #if !defined(LIBRESSL_VERSION_NUMBER ) && \
1189+ (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG ) || \
1190+ defined(CRYPTO_malloc_debug_init ))
1191+ rb_define_module_function (mOSSL , "mem_check_start" , mem_check_start , 0 );
1192+ rb_define_module_function (mOSSL , "print_mem_leaks" , print_mem_leaks , 0 );
1193+
1194+ #if defined(CRYPTO_malloc_debug_init ) /* <= 1.0.2 */
1195+ CRYPTO_malloc_debug_init ();
1196+ #endif
1197+
1198+ #if defined(V_CRYPTO_MDEBUG_ALL ) /* <= 1.0.2 */
1199+ CRYPTO_set_mem_debug_options (V_CRYPTO_MDEBUG_ALL );
1200+ #endif
1201+
1202+ #if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */
1203+ {
1204+ int i ;
1205+ /*
1206+ * See crypto/ex_data.c; call def_get_class() immediately to avoid
1207+ * allocations. 15 is the maximum number that is used as the class index
1208+ * in OpenSSL 1.0.2.
1209+ */
1210+ for (i = 0 ; i <= 15 ; i ++ ) {
1211+ if (CRYPTO_get_ex_new_index (i , 0 , (void * )"ossl-mdebug-dummy" , 0 , 0 , 0 ) < 0 )
1212+ rb_raise (rb_eRuntimeError , "CRYPTO_get_ex_new_index for "
1213+ "class index %d failed" , i );
1214+ }
1215+ }
1216+ #endif
1217+ #endif
1218+ #endif
11271219}
1128- #endif /* OSSL_DEBUG */
0 commit comments