Mercurial > dovecot > core-2.2
view src/lib/env-util.c @ 21322:5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Mainly to avoid truncating >4GB strings, which might potentially cause
some security holes. Normally there are other limits, which prevent such
excessive strings from being created in the first place.
I'm sure this didn't find everything. Maybe everything could be found with
compiler warnings. -Wconversion kind of does it, but it gives way too many
unnecessary warnings.
These were mainly found with:
grep " = strlen"
egrep "unsigned int.*(size|len)"
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 12 Dec 2016 07:19:55 +0200 |
parents | 0f22db71df7a |
children | 2e2563132d5f |
line wrap: on
line source
/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "env-util.h" #ifdef __APPLE__ # include <crt_externs.h> #endif struct env_backup { pool_t pool; const char **strings; }; static pool_t env_pool = NULL; void env_put(const char *env) { if (env_pool == NULL) { env_pool = pool_alloconly_create(MEMPOOL_GROWING"Environment", 2048); } if (putenv(p_strdup(env_pool, env)) != 0) i_fatal("putenv(%s) failed: %m", env); } void env_remove(const char *name) { #ifdef HAVE_UNSETENV #ifdef UNSETENV_RET_INT if (unsetenv(name) < 0) i_fatal("unsetenv(%s) failed: %m", name); #else unsetenv(name); #endif #else extern char **environ; size_t len; char **envp; len = strlen(name); for (envp = environ; *envp != NULL; envp++) { if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=') { do { envp[0] = envp[1]; } while (*++envp != NULL); break; } } #endif } void env_clean(void) { #ifdef HAVE_CLEARENV if (clearenv() < 0) i_fatal("clearenv() failed"); #else char ***environ_p = env_get_environ_p(); /* Try to clear the environment. a) environ = NULL crashes on OS X. b) *environ = NULL doesn't work on FreeBSD 7.0. c) environ = emptyenv doesn't work on Haiku OS d) environ = calloc() should work everywhere */ *environ_p = calloc(1, sizeof(**environ_p)); #endif if (env_pool != NULL) p_clear(env_pool); } static void env_clean_except_real(const char *const preserve_envs[]) { ARRAY_TYPE(const_string) copy; const char *value, *const *envp; unsigned int i; t_array_init(©, 16); for (i = 0; preserve_envs[i] != NULL; i++) { const char *key = preserve_envs[i]; value = getenv(key); if (value != NULL) { value = t_strconcat(key, "=", value, NULL); array_append(©, &value, 1); } } /* Note that if the original environment was set with env_put(), the environment strings will be invalid after env_clean(). That's why we t_strconcat() them above. */ env_clean(); array_foreach(©, envp) env_put(*envp); } void env_clean_except(const char *const preserve_envs[]) { T_BEGIN { env_clean_except_real(preserve_envs); } T_END; } struct env_backup *env_backup_save(void) { char **environ = *env_get_environ_p(); struct env_backup *env; unsigned int i, count; pool_t pool; i_assert(environ != NULL); for (count = 0; environ[count] != NULL; count++) ; pool = pool_alloconly_create("saved environment", 4096); env = p_new(pool, struct env_backup, 1); env->pool = pool; env->strings = p_new(pool, const char *, count + 1); for (i = 0; i < count; i++) env->strings[i] = p_strdup(pool, environ[i]); return env; } void env_backup_restore(struct env_backup *env) { unsigned int i; env_clean(); for (i = 0; env->strings[i] != NULL; i++) env_put(env->strings[i]); } void env_backup_free(struct env_backup **_env) { struct env_backup *env = *_env; *_env = NULL; pool_unref(&env->pool); } char ***env_get_environ_p(void) { #ifdef __APPLE__ return _NSGetEnviron(); #else extern char **environ; return &environ; #endif } void env_deinit(void) { if (env_pool != NULL) pool_unref(&env_pool); }