@@ -414,6 +414,72 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
414414#endif
415415}
416416
417+ #if defined(OSSL_DEBUG )
418+ #if !defined(LIBRESSL_VERSION_NUMBER ) && \
419+ (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG ) || \
420+ defined(CRYPTO_malloc_debug_init ))
421+ /*
422+ * call-seq:
423+ * OpenSSL.mem_check_start -> nil
424+ *
425+ * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
426+ * allocations. See also OpenSSL.print_mem_leaks.
427+ *
428+ * This is available only when built with a capable OpenSSL and --enable-debug
429+ * configure option.
430+ */
431+ static VALUE
432+ mem_check_start (VALUE self )
433+ {
434+ CRYPTO_mem_ctrl (CRYPTO_MEM_CHECK_ON );
435+ return Qnil ;
436+ }
437+
438+ /*
439+ * call-seq:
440+ * OpenSSL.print_mem_leaks -> true | false
441+ *
442+ * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
443+ * Prints detected memory leaks to standard error. This cleans the global state
444+ * up thus you cannot use any methods of the library after calling this.
445+ *
446+ * Returns true if leaks detected, false otherwise.
447+ *
448+ * This is available only when built with a capable OpenSSL and --enable-debug
449+ * configure option.
450+ *
451+ * === Example
452+ * OpenSSL.mem_check_start
453+ * NOT_GCED = OpenSSL::PKey::RSA.new(256)
454+ *
455+ * END {
456+ * GC.start
457+ * OpenSSL.print_mem_leaks # will print the leakage
458+ * }
459+ */
460+ static VALUE
461+ print_mem_leaks (VALUE self )
462+ {
463+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
464+ int ret ;
465+ #endif
466+
467+ BN_CTX_free (ossl_bn_ctx );
468+ ossl_bn_ctx = NULL ;
469+
470+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
471+ ret = CRYPTO_mem_leaks_fp (stderr );
472+ if (ret < 0 )
473+ ossl_raise (eOSSLError , "CRYPTO_mem_leaks_fp" );
474+ return ret ? Qfalse : Qtrue ;
475+ #else
476+ CRYPTO_mem_leaks_fp (stderr );
477+ return Qnil ;
478+ #endif
479+ }
480+ #endif
481+ #endif
482+
417483#if !defined(HAVE_OPENSSL_110_THREADING_API )
418484/**
419485 * 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