aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/xfuncs_printf.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 1b11caf6b..f569b0263 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -344,20 +344,28 @@ void FAST_FUNC xsetenv(const char *key, const char *value)
*/
void FAST_FUNC bb_unsetenv(const char *var)
{
- char *tp = strchr(var, '=');
-
- if (!tp) {
- unsetenv(var);
- return;
+ char onstack[128 - 16]; /* smaller stack setup code on x86 */
+ char *tp;
+
+ tp = strchr(var, '=');
+ if (tp) {
+ /* In case var was putenv'ed, we can't replace '='
+ * with NUL and unsetenv(var) - it won't work,
+ * env is modified by the replacement, unsetenv
+ * sees "VAR" instead of "VAR=VAL" and does not remove it!
+ * Horror :(
+ */
+ unsigned sz = tp - var;
+ if (sz < sizeof(onstack)) {
+ ((char*)mempcpy(onstack, var, sz))[0] = '\0';
+ tp = NULL;
+ var = onstack;
+ } else {
+ /* unlikely: very long var name */
+ var = tp = xstrndup(var, sz);
+ }
}
-
- /* In case var was putenv'ed, we can't replace '='
- * with NUL and unsetenv(var) - it won't work,
- * env is modified by the replacement, unsetenv
- * sees "VAR" instead of "VAR=VAL" and does not remove it!
- * horror :( */
- tp = xstrndup(var, tp - var);
- unsetenv(tp);
+ unsetenv(var);
free(tp);
}