]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Allow testing the valgrind suppression file in CI
authorBob Beck <beck@openssl.org>
Wed, 7 Jan 2026 23:21:10 +0000 (16:21 -0700)
committerTomas Mraz <tomas@openssl.org>
Tue, 10 Feb 2026 14:00:52 +0000 (15:00 +0100)
Skip the OPENSSL_cleanup() call from the openssl app and in tests
when OSSL_USE_VALGRIND environment variable is set.

This can be used in the CI to test the valgrind suppressions.

Builds upon https://github.com/openssl/openssl/pull/29573

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Tue Feb 10 14:00:54 2026
(Merged from https://github.com/openssl/openssl/pull/29575)

apps/openssl.c
doc/internal/man7/valgrind-tests.pod [new file with mode: 0644]
test/testutil/main.c

index 2d587e2249817097a08c32e69dc1ff99d7a464d8..e869910e82965ca35047b176106d32db8d461908 100644 (file)
 #include <openssl/pem.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+
+#if defined __has_include
+/* Any compiler you're going to run valgrind on has this */
+#if __has_include(<valgrind/valgrind.h>)
+#include <valgrind/valgrind.h>
+#define OPENSSL_VALGRIND_H_INCLUDED
+#endif
+#endif /* defined(__has_include) */
+
 /* Needed to get the other O_xxx flags. */
 #ifdef OPENSSL_SYS_VMS
 #include <unixio.h>
@@ -372,6 +381,31 @@ end:
 #ifndef OPENSSL_NO_SECURE_MEMORY
     CRYPTO_secure_malloc_done();
 #endif
+
+#if defined(OPENSSL_VALGRIND_TEST)
+#if defined(OPENSSL_VALGRIND_H_INCLUDED)
+#if defined(RUNNING_ON_VALGRIND)
+    /*
+     * Enable special behaviour if we are compiled with
+     * OPENSSL_VALGRIND_TEST defined.
+     *
+     * Somewhat paradoxically, we do *NOT* want to clean up normally
+     * when running our tests using valgrind in order to test the
+     * suppression file which we will ship with the distribution. We
+     * set the OSSL_USE_VALGRIND environment variable for this
+     * purpose, but we only want to dodge cleanup when running under
+     * valgrind, *and* that environment variable is set. If you run
+     * this under valgrind without that environment variable set, it
+     * will still call OPENSSL_cleanup normally.
+     *
+     */
+    if (RUNNING_ON_VALGRIND && getenv("OSSL_USE_VALGRIND") != NULL)
+        EXIT(ret);
+#endif /* defined(RUNNING_ON_VALGRIND) */
+#else
+#error "OPENSSL_VALGRIND_TEST is defined, but <valgrind/valgrind.h> could not be included!"
+#endif /* defined(OPENSSL_VALGRIND_H_INCLUDED) */
+#endif /* defined(OPENSSL_VALGRIND_TEST) */
     OPENSSL_cleanup();
     EXIT(ret);
 }
diff --git a/doc/internal/man7/valgrind-tests.pod b/doc/internal/man7/valgrind-tests.pod
new file mode 100644 (file)
index 0000000..e5b31b8
--- /dev/null
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+valgrind-tests - How we test for valgrind
+
+=head1 DESCRIPTION
+
+We have CI jobs that run to verify that the suppression file we
+ship with valgrind functions correctly when users use valgrind
+with full leak checking.
+
+While doing full leak checking shows the global objects the library
+frees on exit as leaks, which really are not leaks, it is a chore
+to continuously tell people to ignore the results from the library.
+
+==head1 ENVIRONMENT
+
+Normally the openssl application main program and the test main program
+always call OPENSSL_cleanup(). This means that running these applications
+under valgrind will not show anything. Therefore we selectively disable
+the call to OPENSSL_cleanup() when running these applications for
+testing.
+
+the test environment sets the environment variable
+
+I<OSSL_USE_VALGRIND> when using valgrind to run our tests.
+
+As such the main programs above are instrumented so that when they
+are built and the <valgrind/valgrind.h> header can be seen in the
+include path, the macro RUNNING_ON_VALGRIND is used at exit time
+to test to see if the program is actually running under valgrind.
+
+If the program is running under valgrind, the program checks to
+see if I<OSSL_USE_VALGRIND> is set in the environment. If so,
+the call to OPENSSL_cleanup() is skipped on exit. This will ensure
+the library globals are noticed by valgrind with full leak checking
+ensuring our suppression file is working in CI.
+
+=head1 COPYRIGHT
+
+Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
index 2d7c88c3831bae08b71fed8e69d41fcb5e5a67a8..c0d3ffe7fd3d5bee048ff0767ffdc77c2a97f9b9 100644 (file)
 #include "output.h"
 #include "tu_local.h"
 
+#if defined __has_include
+/* Any compiler you're going to run valgrind on has this */
+#if __has_include(<valgrind/valgrind.h>)
+#include <valgrind/valgrind.h>
+#define OPENSSL_VALGRIND_H_INCLUDED
+#endif
+#endif /* defined(__has_include) */
+
+/*
+ * At some point we should consider looking at this function with a view to
+ * moving most/all of this into onfree handlers in OSSL_LIB_CTX.
+ */
+
 int main(int argc, char *argv[])
 {
     int ret = EXIT_FAILURE;
@@ -40,6 +53,20 @@ int main(int argc, char *argv[])
 end:
     ret = pulldown_test_framework(ret);
     test_close_streams();
+#if defined(OPENSSL_VALGRIND_H_INCLUDED) && defined(RUNNING_ON_VALGRIND)
+    /*
+     * Somewhat paradoxically, we do *NOT* want to clean up normally
+     * when running our tests using valgrind in order to test the
+     * suppression file which we will ship with the distribution. We
+     * set the OSSL_USE_VALGRIND environment variable for this
+     * purpose, but we only want to dodge cleanup when running under
+     * valgrind, *and* that environment variable is set. If you run
+     * this under valgrind without that environment variable set, it
+     * will still call OPENSSL_cleanup normally.
+     */
+    if (RUNNING_ON_VALGRIND && getenv("OSSL_USE_VALGRIND") != NULL)
+        return ret;
+#endif /* defined(OPENSSL_VALGRIND_H_INCLUDED) && defined(RUNNING_ON_VALGRIND) */
     OPENSSL_cleanup();
     return ret;
 }