mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
Some applications set environ to a heap-allocated pointer, call
setenv (expecting it to call realloc), free environ, and then
restore the original environ pointer. This breaks after
commit 7a61e7f557
("stdlib: Make
getenv thread-safe in more cases") because after the setenv call,
the environ pointer does not point to the start of a heap allocation.
Instead, setenv creates a separate allocation and changes environ
to point into that. This means that the free call in the application
results in heap corruption.
The interim approach was more compatible with other libcs because
it does not assume that the incoming environ pointer is allocated
as if by malloc (if it was written by the application). However,
it seems to be more important to stay compatible with previous
glibc version: assume the incoming pointer is heap allocated,
and preserve this property after setenv calls.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
64 lines
2 KiB
C
64 lines
2 KiB
C
/* Test using setenv with a malloc-allocated environ variable.
|
|
Copyright (C) 2025 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
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
/* This test is not in the scope for POSIX or any other standard, but
|
|
some applications assume that environ is a heap-allocated pointer
|
|
after a call to setenv on an empty environment. */
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <support/check.h>
|
|
#include <support/support.h>
|
|
|
|
static const char *original_path;
|
|
static char **save_environ;
|
|
|
|
static void
|
|
rewrite_environ (void)
|
|
{
|
|
save_environ = environ;
|
|
environ = xmalloc (sizeof (*environ));
|
|
*environ = NULL;
|
|
TEST_COMPARE (setenv ("A", "1", 1), 0);
|
|
TEST_COMPARE (setenv ("B", "2", 1), 0);
|
|
TEST_VERIFY (environ != save_environ);
|
|
TEST_COMPARE_STRING (environ[0], "A=1");
|
|
TEST_COMPARE_STRING (environ[1], "B=2");
|
|
TEST_COMPARE_STRING (environ[2], NULL);
|
|
TEST_COMPARE_STRING (getenv ("PATH"), NULL);
|
|
free (environ);
|
|
environ = save_environ;
|
|
TEST_COMPARE_STRING (getenv ("PATH"), original_path);
|
|
}
|
|
|
|
static int
|
|
do_test (void)
|
|
{
|
|
original_path = getenv ("PATH");
|
|
rewrite_environ ();
|
|
|
|
/* Test again after reallocated the environment due to an initial
|
|
setenv call. */
|
|
TEST_COMPARE (setenv ("TST_SETENV_MALLOC", "1", 1), 0);
|
|
TEST_VERIFY (environ != save_environ);
|
|
rewrite_environ ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
#include <support/test-driver.c>
|