summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcos <cos>2012-12-16 11:19:04 +0100
committercos <cos>2012-12-16 19:13:49 +0100
commit42ae327b55c8827142000952ebd2487624908989 (patch)
tree3bf5f005bb22b8fcbeb35aecb74a69089feff070
parent9d1edbd9c618b063a4baae39a82a81da236ea72f (diff)
downloadratpoison-fix/unsetenv_memory_corruption.zip
Remove memory corruption bug.fix/unsetenv_memory_corruption
Fix regression from commit a2aeb846. Providing putenv() a variable suffixed by an equal sign with glibc, puts the pointer of the empty string as the value of the variable. When dereferencing the empty string, strange things happen. I doubt the OpenBSD implementation has a severely different API, but have not verified this. From putenv()'s manpage in Debian, it is easy to get the impression that it is a good idea to have putenv() handling all environment variable manipulation when using glibc. According to OpenBSD's manpage, putenv() is merely an alias for setenv() with arguments. The best we can do is having putenv() removing the variable on platforms where that is possible & calling unsetenv() on OpenBSD (+ other unknown platforms).
-rw-r--r--src/actions.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/src/actions.c b/src/actions.c
index bf381c8..259ae68 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -4190,15 +4190,16 @@ cmd_chdir (int interactive UNUSED, struct cmdarg **args)
cmdret *
cmd_unsetenv (int interactive UNUSED, struct cmdarg **args)
{
- struct sbuf *s;
+ /* Remove all instances of the env. var. It is assumed a good idea to use
+ putenv() for all manipulation of environment variables, in order to let it
+ handle memory management. On OpenBSD unsetting variables using putenv() is
+ not possible. */
+#ifdef __OpenBSD__
+ unsetenv (ARG_STRING(0));
+#else
+ putenv (ARG_STRING(0));
+#endif
- /* Remove all instances of the env. var. We must add an '=' for it
- to work on OpenBSD. */
- s = sbuf_new(0);
- sbuf_copy (s, ARG_STRING(0));
- sbuf_concat (s, "=");
- putenv (sbuf_get(s));
- sbuf_free (s);
return cmdret_new (RET_SUCCESS, NULL);
}