Commit 7b8f9b1c1c for openssl.org
commit 7b8f9b1c1c1944e8c748ce7160ffa5a3968d73e3
Author: Alexandr Nedvedicky <sashan@openssl.org>
Date: Mon Feb 9 12:28:01 2026 +0100
Update NOTES-VALGRIND.md to document valgrind compaints on reachable
memory blocks
Co-authored-by: Matt Caswell <matt@openssl.org>
Co-authored-by: Tomáš Mráz <tm@t8m.info>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Wed Feb 11 19:40:10 2026
(Merged from https://github.com/openssl/openssl/pull/29966)
diff --git a/NOTES-VALGRIND.md b/NOTES-VALGRIND.md
index 96f0df1d19..cd82d01fdc 100644
--- a/NOTES-VALGRIND.md
+++ b/NOTES-VALGRIND.md
@@ -70,3 +70,76 @@ with the `VERBOSE` or `VF` or `VFP` options to gather additional information.
$ make test VERBOSE=1 TESTS=test_test EXE_SHELL="$(/bin/pwd)/util/wrap.pl \
valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0"
+
+Still reachable memory
+======================
+
+OpenSSL 4.0 no longer arms `OPENSSL_cleanup()` function as an `atexit(3)`
+handler. So, unless the application explicitly calls `OPENSSL_cleanup()`, valgrind and
+similar memory leak detectors may report `still reachable` memory blocks
+as memory leaks. An example of a valgrind report reads as follows:
+
+ # valgrind ./pkeyread -f pem -k dh 8
+ ==280439== Memcheck, a memory error detector
+ ==280439== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
+ ==280439== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info
+ ==280439== Command: ./pkeyread -f pem -k dh 8
+ ==280439==
+ Average time per pem(dh) call: 506329.113924us
+ ==280439==
+ ==280439== HEAP SUMMARY:
+ ==280439== in use at exit: 239,521 bytes in 4,137 blocks
+ ==280439== total heap usage: 21,841 allocs, 17,704 frees, 4,089,104 bytes allocated
+ ==280439==
+ ==280439== LEAK SUMMARY:
+ ==280439== definitely lost: 0 bytes in 0 blocks
+ ==280439== indirectly lost: 0 bytes in 0 blocks
+ ==280439== possibly lost: 0 bytes in 0 blocks
+ ==280439== still reachable: 239,521 bytes in 4,137 blocks
+ ==280439== suppressed: 0 bytes in 0 blocks
+ ==280439== Rerun with --leak-check=full to see details of leaked memory
+ ==280439==
+ ==280439== For lists of detected and suppressed errors, rerun with: -s
+ ==280439== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+
+The valgrind output above reports there are 239,521 of reachable memory
+when process exits. That memory is not regarded as a true memory leak
+as the OS will reclaim that memory on process exit, rendering calls to libc
+`free()` within `OPENSSL_cleanup()` useless. Also calling `OPENSSL_cleanup()`
+is discouraged when libcrypto is being linked with process to satisfy more
+than one dependency paths. If it is the case then calling `OPENSSL_cleanup()`
+may lead to spurious application crashes during exit.
+
+If memory leaks caused by _still reachable memory_ are still an issue,
+then preferred way is to suppress those reports using the suppression
+file [1] instead of changing exiting code by adding a call to `OPENSSL_cleanup()`.
+The suppression file for OpenSSL is shipped within the OpenSSL sources and
+can be found at`$OPENSSL_SRCS/util/valgrind.suppressions` where `OPENSSL_SRCS`
+is an environment variable containing path to the OpenSSL source
+tree. To use it, just add `--suppressions` option to the valgrind command:
+`valgrind --suppressions="$OPENSSL_SRCS/util/valgrind.suppression" ...`
+For `pkeyread` the command and output reads as follows:
+
+ # valgrind --suppressions=$OPENSSL_SRCS/util/valgrind.suppression ./pkeyread -f pem -k dh 8
+ ==280896== Memcheck, a memory error detector
+ ==280896== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
+ ==280896== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info
+ ==280896== Command: ./pkeyread -f pem -k dh 8
+ ==280896==
+ Average time per pem(dh) call: 476190.476190us
+ ==280896==
+ ==280896== HEAP SUMMARY:
+ ==280896== in use at exit: 239,521 bytes in 4,137 blocks
+ ==280896== total heap usage: 22,816 allocs, 18,679 frees, 4,325,714 bytes allocated
+ ==280896==
+ ==280896== LEAK SUMMARY:
+ ==280896== definitely lost: 0 bytes in 0 blocks
+ ==280896== indirectly lost: 0 bytes in 0 blocks
+ ==280896== possibly lost: 0 bytes in 0 blocks
+ ==280896== still reachable: 0 bytes in 0 blocks
+ ==280896== suppressed: 239,521 bytes in 4,137 blocks
+ ==280896==
+ ==280896== For lists of detected and suppressed errors, rerun with: -s
+ ==280896== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+
+[1] <https://valgrind.org/docs/manual/manual-core.html#manual-core.suppress>