Bug 189805 - setenv with value == NULL coredumps on FreeBSD
Summary: setenv with value == NULL coredumps on FreeBSD
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-14 16:10 UTC by Enji Cooper
Modified: 2018-04-04 12:44 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Enji Cooper freebsd_committer freebsd_triage 2014-05-14 16:10:00 UTC
One of the tests imported from FreeBSD tests out setenv with value => NULL as it's a requirement of the libcall. FreeBSD coredumps with a segfault on this test because libc (behind the scenes) runs a strcmp on the buffer, which subsequently blows up when trying to analyze the NULL pointer.

value => NULL is undefined per POSIX, so the behavior is implementation dependent, but value is assumed to be a string, not a NULL pointer. It seems like an edgecase that could be caught and improved upon as it would be nice if an error was set or at the very least an assert was triggered in setenv when this situation was encountered so the error was localized to the block of code instead of corrupting the stack later on down the line.

Here's what pho and I discovered:

- FreeBSD/OSX segfault.
- Linux succeeds. Subsequent getenvs return NULL.
- NetBSD returns -1/sets EINVAL.

Bruce E weighed in on this, and believes the libcall should always coredump, but he didn't recommend how it should coredump.

Fix: 

The original proposed fix to just return/set and error is out here: https://github.com/yaneurabeya/freebsd/pull/5 .
How-To-Repeat: % /bin/sh
% cat > setenv_segfault.c <<EOF
cat ./test_setenv_segfault.c 
#include <stdlib.h>

int
main(void)
{

	setenv("somevar", NULL, 0);
	return (0);
}
EOF
% clang -g -Wall -o setenv_segfault setenv_segfault.c
% gdb ./setenv_segfault
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...
(gdb) r
Starting program: /root/setenv_segfault 

Program received signal SIGSEGV, Segmentation fault.
0x2818bd4d in strlen () from /lib/libc.so.7
(gdb) bt
#0  0x2818bd4d in strlen () from /lib/libc.so.7
#1  0x28188a35 in setenv () from /lib/libc.so.7
#2  0x281885b8 in setenv () from /lib/libc.so.7
#3  0x080485c3 in main () at setenv_segfault.c:7
Comment 1 Garrett Cooper 2014-05-14 16:11:12 UTC
On May 14, 2014, at 8:10 AM, FreeBSD-gnats-submit@FreeBSD.org wrote:

> Thank you very much for your problem report.
> It has the internal identification `bin/189805'.
> The individual assigned to look at your
> report is: freebsd-bugs.=20
>=20
> You can access the state of your problem report at any time
> via this link:
>=20
> http://www.freebsd.org/cgi/query-pr.cgi?pr=3D189805
>=20
>> Category:       bin
>> Responsible:    freebsd-bugs
>> Synopsis:       setenv(
>> Arrival-Date:   Wed May 14 15:10:00 UTC 2014

Hi,
	Could someone with GNATS access please fix the synopsis to say =
=93setenv with value =3D=3D NULL coredumps on FreeBSD=94?
Thanks in advance -_-!
-Garrett=
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2015-01-18 22:41:13 UTC
I think segfaulting is a useful response to passing an invalid pointer to a library function. It is a way to indicate the error which is hard to ignore (so callers will be fixed), and also tends to require no additional code. So I think nothing needs to change here.
Comment 3 Enji Cooper freebsd_committer freebsd_triage 2015-10-25 02:47:54 UTC
(In reply to Jilles Tjoelker from comment #2)

An assert and adding behavior so it would return as described in comment # 0 would be better than a segfault. We have a ton of applications at $work that are multithreaded, and it peeves me off when they segfault and we have to go track down why.

Dereferencing NULL is inconsistent with other OSes and makes us look silly -- especially when it's not documented.