From: Florian Weimer Date: Mon, 2 Feb 2026 20:15:48 +0000 (+0100) Subject: elf: Add test case for LD_PROFILE/LD_PROFILE_OUTPUT interaction X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=364426a59ee30ee3e528e5b5cae36b5dee045320;p=thirdparty%2Fglibc.git elf: Add test case for LD_PROFILE/LD_PROFILE_OUTPUT interaction This verifies that LD_PROFILE is correctly ignored if LD_PROFILE_OUTPUT is not set. The test was initially auto-generated, then heavily edited and re-edited for brevity and clarity. The test uses glibc-specific interfaces (including one that did not exist at all a couple of hours ago), so this should be unproblematic. --- diff --git a/elf/Makefile b/elf/Makefile index 01cc51636e..30ac283186 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -452,6 +452,7 @@ tests += \ tst-initorder \ tst-initorder2 \ tst-latepthread \ + tst-ld_profile \ tst-main1 \ tst-next-ver \ tst-nodelete-dlclose \ diff --git a/elf/tst-ld_profile.c b/elf/tst-ld_profile.c new file mode 100644 index 0000000000..6c392f682b --- /dev/null +++ b/elf/tst-ld_profile.c @@ -0,0 +1,139 @@ +/* Test LD_PROFILE/LD_PROFILE_OUTPUT interaction (bug 33797). + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Expected profile file path (based on LD_PROFILE_OUTPUT and LIBC_SO). */ +static char *profile_file_path; + +/* Path to this test program for recursive invocation. */ +static char *program; + +/* LD_PROFILE_OUTPUT environment variable setting. */ +static char *ld_profile_output_env; + +/* Run the test program with the specified environment array. */ +static struct support_capture_subprocess +run_test_program (char *env[]) +{ + /* Make sure the the potential output file does not exist. */ + unlink (profile_file_path); + +/* Command line arguments for recursive invocation. This turns the + test program in a no-op (with LD_PROFILE output the only side effect). */ + static char *recurse_argv[] = + { + (char *) "tst-ld_profile", (char *) "recurse", NULL + }; + struct support_spawn_wrapped *w + = support_spawn_wrap (program, recurse_argv, env, 0); + struct support_capture_subprocess proc + = support_capture_subprogram (w->path, w->argv, w->envp); + support_spawn_wrapped_free (w); + + return proc; +} + +static void +test_profile_without_output (void) +{ + char *env[] = { (char *) "LD_PROFILE=" LIBC_SO, NULL }; + struct support_capture_subprocess proc = run_test_program (env); + const char *expected_warning = + "warning: LD_PROFILE ignored because LD_PROFILE_OUTPUT not specified\n"; + TEST_COMPARE_STRING (proc.err.buffer, expected_warning); + support_capture_subprocess_check (&proc, + "LD_PROFILE without LD_PROFILE_OUTPUT", + 0, sc_allow_stderr); + support_capture_subprocess_free (&proc); + + TEST_VERIFY (access (profile_file_path, F_OK) != 0); + /* Also check the old /var/tmp path. */ + TEST_VERIFY (access ("/var/tmp/" LIBC_SO ".profile", F_OK) != 0); +} + +static void +test_profile_with_output (void) +{ + char *env[] = { (char *) "LD_PROFILE=" LIBC_SO, ld_profile_output_env, NULL }; + struct support_capture_subprocess proc = run_test_program (env); + support_capture_subprocess_check (&proc, "LD_PROFILE with LD_PROFILE_OUTPUT", + 0, sc_allow_none); + support_capture_subprocess_free (&proc); + + /* This asserts that the file was created. */ + TEST_COMPARE (unlink (profile_file_path), 0); +} + +static void +test_output_without_profile (void) +{ + char *env[] = { ld_profile_output_env, NULL }; + struct support_capture_subprocess proc = run_test_program (env); + support_capture_subprocess_check (&proc, + "LD_PROFILE_OUTPUT without LD_PROFILE", + 0, sc_allow_none); + support_capture_subprocess_free (&proc); + + TEST_VERIFY (access (profile_file_path, F_OK) != 0); +} + +static void +prepare (int argc, char **argv) +{ + /* Do nothing on recursive invocation. */ + if (argc >= 2 && strcmp (argv[1], "recurse") == 0) + exit (0); +} + +#define PREPARE prepare + +static int +do_test (void) +{ + if (access ("/var/tmp/" LIBC_SO ".profile", F_OK) == 0) + FAIL_UNSUPPORTED ("/var/tmp/" LIBC_SO ".profile exists"); + + /* Temporary directory for the profile output. */ + char *profile_output_dir = support_create_temp_directory ("tst-ld_profile"); + profile_file_path = xasprintf ("%s/%s.profile", profile_output_dir, LIBC_SO); + ld_profile_output_env = xasprintf ("LD_PROFILE_OUTPUT=%s", + profile_output_dir); + program = xasprintf ("%s/elf/tst-ld_profile", support_objdir_root); + + test_profile_without_output (); + test_profile_with_output (); + test_output_without_profile (); + + free (program); + free (ld_profile_output_env); + free (profile_file_path); + free (profile_output_dir); + + return 0; +} + +#include