[runtime] Switch getenv to use heap memory
authorAlexander Kyte <alexmkyte@gmail.com>
Mon, 27 Mar 2017 06:18:43 +0000 (02:18 -0400)
committerAlexander Kyte <alexmkyte@gmail.com>
Thu, 30 Mar 2017 17:58:10 +0000 (13:58 -0400)
Getenv doesn't use heap memory, it uses static memory.
Mono's usage is consistent with a view of getenv memory contents
that are durable and can be stored and manipulated.

In a multithreaded context, getenv calls can race and corrupt
string buffers as they are read. In a single threaded context,
subsequent calls to getenv will lead to overwriting the memory
that pointers to previous calls point to.

In order to bring memory safety back, we duplicate memory and
manage it at each call-site.

Note: this changes the API semantics of g_getenv. This is necessary
because the locking around the getenv buffer is safest when confined to
the function in eglib.

44 files changed:
eglib/src/glib.h
eglib/src/gmisc-unix.c
eglib/src/gmisc-win32.c
mono/arch/ia64/codegen.c
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/boehm-gc.c
mono/metadata/class.c
mono/metadata/cominterop.c
mono/metadata/console-unix.c
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/locales.c
mono/metadata/lock-tracer.c
mono/metadata/mono-config.c
mono/metadata/threadpool-io.c
mono/metadata/w32file-unix.c
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/driver.c
mono/mini/helpers.c
mono/mini/ir-emit.h
mono/mini/liveness.c
mono/mini/llvm-jit.cpp
mono/mini/method-to-ir.c
mono/mini/mini-arm.c
mono/mini/mini-cross-helpers.c
mono/mini/mini-gc.c
mono/mini/mini-llvm.c
mono/mini/mini-ppc.h
mono/mini/mini-runtime.c
mono/mini/mini-x86.c
mono/mini/mini.c
mono/profiler/mono-profiler-log.c
mono/sgen/sgen-gc.c
mono/utils/checked-build.c
mono/utils/mono-hwcap.c
mono/utils/mono-io-portability.c
mono/utils/mono-logger.c
mono/utils/mono-mmap.c
mono/utils/mono-rand.c
mono/utils/mono-threads-coop.c
mono/utils/mono-threads.c
mono/utils/strenc.c

index 8ceec487041d6bb7c3a2a72d3f8e85cfd2ecaa78..6f16fcb292bb692f2e2fc5daa5d7c3a5a8cd0189 100644 (file)
@@ -160,7 +160,8 @@ typedef struct _GMemChunk GMemChunk;
  * Misc.
  */
 
-const gchar *    g_getenv(const gchar *variable);
+gboolean         g_hasenv(const gchar *variable);
+gchar *          g_getenv(const gchar *variable);
 gboolean         g_setenv(const gchar *variable, const gchar *value, gboolean overwrite);
 void             g_unsetenv(const gchar *variable);
 
index 273024871c5f890e01410f8a12094cf256cd33d8..2529069a981047ac63b392340c801857ca4760d4 100644 (file)
 #include <unistd.h>
 #endif
 
+static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER;
 
-const gchar *
-g_getenv(const gchar *variable)
+/* MONO Comment
+ * 
+ * As per the UNIX spec, 
+ * "The return value from getenv() may point to static data which may be overwritten by subsequent calls to getenv(), setenv(), or unsetenv()."
+ * Source: Unix Manual Pages for getenv, IEEE Std 1003.1
+ *
+ * This means that using pointers returned from getenv may (and does) lead to many
+ * pointers which refer to the same piece of memory. When one is freed, all will be freed.
+ *
+ * This is unsafe and an ergonomics risk to fix in the callers. While the caller could lock,
+ * this introduces the risk for looping or exiting while inside of a lock. For this reason,
+ * g_getenv does not mimic the behavior of POSIX getenv anymore.
+ *
+ * The memory address returned will be unique to the invocaton, and must be freed.
+ * */ 
+gchar *
+g_getenv (const gchar *variable)
+{
+       gchar *ret = NULL;
+       pthread_mutex_lock (&env_lock);
+       gchar *res = getenv(variable);
+       if (res)
+               ret = g_strdup(res);
+       pthread_mutex_unlock (&env_lock);
+
+       return ret;
+}
+
+/*
+ * This function checks if the given variable is non-NULL
+ * in the environment. It's useful because it removes memory
+ * freeing requirements.
+ *
+ */
+gboolean
+g_hasenv (const gchar *variable)
 {
-       return getenv(variable);
+       pthread_mutex_lock (&env_lock);
+       gchar *res = getenv(variable);
+       gboolean not_null = (res != NULL);
+       pthread_mutex_unlock (&env_lock);
+
+       return not_null;
 }
 
 gboolean
 g_setenv(const gchar *variable, const gchar *value, gboolean overwrite)
 {
-       return setenv(variable, value, overwrite) == 0;
+       gboolean res;
+       pthread_mutex_lock (&env_lock);
+       res = (setenv(variable, value, overwrite) == 0);
+       pthread_mutex_unlock (&env_lock);
+       return res;
 }
 
 void
 g_unsetenv(const gchar *variable)
 {
+       pthread_mutex_lock (&env_lock);
        unsetenv(variable);
+       pthread_mutex_unlock (&env_lock);
 }
 
 gchar*
index 4aac0ef69460fe70c432dfb78f8fcfd2bd931f5a..696332bcb5c5c2ab6fdfc3637e87641f2901447c 100644 (file)
 #include <io.h>
 #include <assert.h>
 
+gboolean
+g_hasenv (const gchar *variable)
+{
+       return g_getenv (variable) != NULL;
+}
+
 const gchar *
 g_getenv(const gchar *variable)
 {
index 97e1aefcb1ed5299f1aae55d93c34caf14685029..93d85a57df3ec32061809e92309d1b064a4d5649 100644 (file)
@@ -52,11 +52,12 @@ mono_disassemble_code (guint8 *code, int size, char *id)
        system (cmd); 
        g_free (cmd);
        if (!objdump_args)
-               objdump_args = "";
+               objdump_args = strdup("");
        
        cmd = g_strdup_printf (DIS_CMD " %s %s", objdump_args, o_file);
        system (cmd);
        g_free (cmd);
+       g_free (objdump_args);
        
        g_free (o_file);
        g_free (as_file);
index 9d0576f6c4271a9b012106d499253c8ea4484e9a..58304b574be437794de04b4d31dce862f031306d 100644 (file)
@@ -2210,8 +2210,9 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
         * Unloading seems to cause problems when running NUnit/NAnt, hence
         * this workaround.
         */
-       if (g_getenv ("MONO_NO_UNLOAD"))
+       if (g_hasenv ("MONO_NO_UNLOAD"))
                return;
+
 #ifdef __native_client__
        return;
 #endif
index 43cc6b44385899e3a842482446831c69c0d687d9..a136e34fb3ac95b836e1619a7d118f27f5bdba48 100644 (file)
@@ -294,7 +294,7 @@ mono_set_assemblies_path (const char* path)
        }
        *dest = *splitted;
 
-       if (g_getenv ("MONO_DEBUG") == NULL)
+       if (g_hasenv ("MONO_DEBUG"))
                return;
 
        splitted = assemblies_path;
@@ -315,21 +315,25 @@ char* nacl_mono_path = NULL;
 static void
 check_path_env (void)
 {
-       const char* path;
-       path = g_getenv ("MONO_PATH");
+       if (assemblies_path != NULL)
+               return;
+
+       char* path = g_getenv ("MONO_PATH");
 #ifdef __native_client__
        if (!path)
-               path = nacl_mono_path;
+               path = strdup (nacl_mono_path);
 #endif
-       if (!path || assemblies_path != NULL)
+       if (!path)
                return;
 
        mono_set_assemblies_path(path);
+       g_free (path);
 }
 
 static void
-check_extra_gac_path_env (void) {
-       const char *path;
+check_extra_gac_path_env (void) 
+{
+       char *path;
        char **splitted, **dest;
        
        path = g_getenv ("MONO_GAC_PREFIX");
@@ -337,6 +341,8 @@ check_extra_gac_path_env (void) {
                return;
 
        splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000);
+       g_free (path);
+
        if (extra_gac_paths)
                g_strfreev (extra_gac_paths);
        extra_gac_paths = dest = splitted;
@@ -347,7 +353,7 @@ check_extra_gac_path_env (void) {
        }
        *dest = *splitted;
        
-       if (g_getenv ("MONO_DEBUG") == NULL)
+       if (!g_hasenv ("MONO_DEBUG"))
                return;
 
        while (*splitted) {
index f0fa3579f72bcfd9b456132a305819cc8cc5e075..5807f87eddd5e703f572a8534fde48e84a34da43 100644 (file)
@@ -198,6 +198,7 @@ mono_gc_base_init (void)
                                        log_finalizers = 1;
                                }
                        }
+                       g_free (env);
                }
        }
 
@@ -241,6 +242,7 @@ mono_gc_base_init (void)
                                */
                        }
                }
+               g_free (env);
                g_strfreev (opts);
        }
 
@@ -1319,7 +1321,7 @@ mono_gc_is_moving (void)
 gboolean
 mono_gc_is_disabled (void)
 {
-       if (GC_dont_gc || g_getenv ("GC_DONT_GC"))
+       if (GC_dont_gc || g_hasenv ("GC_DONT_GC"))
                return TRUE;
        else
                return FALSE;
index 24e9afa16d5c400765431100fafa54a57056930e..1aa43ee53ebfd99e6c3b823cc5f39bd70d8bd0e1 100644 (file)
@@ -3689,7 +3689,7 @@ is_wcf_hack_disabled (void)
        static gboolean disabled;
        static gboolean inited = FALSE;
        if (!inited) {
-               disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
+               disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
                inited = TRUE;
        }
        return disabled;
index b830214e8838eea0f63b3ea4125a41fe65b53a8e..b5679c919e0eaf6b781ddbff542a6036840d6d83 100644 (file)
@@ -599,13 +599,15 @@ cominterop_type_from_handle (MonoType *handle)
 void
 mono_cominterop_init (void)
 {
-       const char* com_provider_env;
+       char* com_provider_env;
 
        mono_os_mutex_init_recursive (&cominterop_mutex);
 
        com_provider_env = g_getenv ("MONO_COM");
        if (com_provider_env && !strcmp(com_provider_env, "MS"))
                com_provider = MONO_COM_MS;
+       if (com_provider_env)
+               g_free (com_provider_env);
 
        register_icall (cominterop_get_method_interface, "cominterop_get_method_interface", "ptr ptr", FALSE);
        register_icall (cominterop_get_function_pointer, "cominterop_get_function_pointer", "ptr ptr int32", FALSE);
index 7d60b770fe57a3999f7c0ba60b19ed292b2c157a..59d55ee8d6b519244525a91b3197be3b95460c25 100644 (file)
@@ -456,12 +456,16 @@ ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardow
        if (dims == -1){
                int cols = 0, rows = 0;
                                      
-               const char *str = g_getenv ("COLUMNS");
-               if (str != NULL)
+               char *str = g_getenv ("COLUMNS");
+               if (str != NULL) {
                        cols = atoi (str);
+                       g_free (str);
+               }
                str = g_getenv ("LINES");
-               if (str != NULL)
+               if (str != NULL) {
                        rows = atoi (str);
+                       g_free (str);
+               }
 
                if (cols != 0 && rows != 0)
                        cols_and_lines = (cols << 16) | rows;
index 2f3b7f7f27fc1a5dec9a8c1d2adb5193ed908486..2e6392549d835a732a4f28b7cdf9b5ca317593a3 100644 (file)
@@ -6524,7 +6524,7 @@ ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
 ICALL_EXPORT MonoStringHandle
 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
 {
-       const gchar *value;
+       gchar *value;
 
        if (utf8_name == NULL)
                return NULL_HANDLE_STRING;
@@ -6534,7 +6534,9 @@ ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_na
        if (value == 0)
                return NULL_HANDLE_STRING;
        
-       return mono_string_new_handle (mono_domain_get (), value, error);
+       MonoStringHandle res = mono_string_new_handle (mono_domain_get (), value, error);
+       g_free (value);
+       return res;
 }
 
 /*
index 0c507f5c1da1301a5ba886ac032240700bb0b143..d09924ff496afc30d6fc625ffedb7ca7ba0d4d53 100644 (file)
@@ -255,7 +255,7 @@ mono_images_init (void)
        for(hash_idx = 0; hash_idx < IMAGES_HASH_COUNT; hash_idx++)
                loaded_images_hashes [hash_idx] = g_hash_table_new (g_str_hash, g_str_equal);
 
-       debug_assembly_unload = g_getenv ("MONO_DEBUG_ASSEMBLY_UNLOAD") != NULL;
+       debug_assembly_unload = g_hasenv ("MONO_DEBUG_ASSEMBLY_UNLOAD");
 
        install_pe_loader ();
 
index 113fe1f2136b731aaf260dcff8c54a5492e9e02d..157750c81d8665d3410e16d231bc865b632f00e1 100644 (file)
@@ -478,22 +478,27 @@ get_darwin_locale (void)
 static char *
 get_posix_locale (void)
 {
-       const char *locale;
+       char *locale;
 
        locale = g_getenv ("LC_ALL");
        if (locale == NULL) {
                locale = g_getenv ("LANG");
-               if (locale == NULL)
-                       locale = setlocale (LC_ALL, NULL);
+               if (locale == NULL) {
+                       char *static_locale = setlocale (LC_ALL, NULL);
+                       if (static_locale)
+                               locale = g_strdup (static_locale);
+               }
        }
        if (locale == NULL)
                return NULL;
 
        /* Skip English-only locale 'C' */
-       if (strcmp (locale, "C") == 0)
+       if (strcmp (locale, "C") == 0) {
+               g_free (locale);
                return NULL;
+       }
 
-       return g_strdup (locale);
+       return locale;
 }
 
 
index 16fcbdb0618c251bb1b90d3bfbf8e4b22cf8ee7a..bbf939994ab304d288ce6beb1c0fdfd4cd749277 100644 (file)
@@ -73,8 +73,10 @@ mono_locks_tracer_init (void)
        int res;
        char *name;
        mono_os_mutex_init_recursive (&tracer_lock);
-       if (!g_getenv ("MONO_ENABLE_LOCK_TRACER"))
+
+       if (!g_hasenv ("MONO_ENABLE_LOCK_TRACER"))
                return;
+
        name = g_strdup_printf ("locks.%d", getpid ());
        trace_file = fopen (name, "w+");
        g_free (name);
index fe82c2e037bef78c7074f11e22a817abd3093f40..8a65e0b8ece23931bf8ca9b36358d6de4299c54e 100644 (file)
@@ -163,8 +163,7 @@ mono_parser = {
 
 static GHashTable *config_handlers;
 
-static const char *mono_cfg_dir = NULL;
-static char *mono_cfg_dir_allocated = NULL;
+static char *mono_cfg_dir = NULL;
 
 /* when this interface is stable, export it. */
 typedef struct MonoParseHandler MonoParseHandler;
@@ -470,7 +469,7 @@ mono_config_cleanup (void)
 {
        if (config_handlers)
                g_hash_table_destroy (config_handlers);
-       g_free (mono_cfg_dir_allocated);
+       g_free (mono_cfg_dir);
 }
 
 /* FIXME: error handling */
@@ -651,9 +650,10 @@ mono_config_parse (const char *filename) {
                return;
        }
 
-       home = g_getenv ("MONO_CONFIG");
-       if (home) {
-               mono_config_parse_file (home);
+       // FIXME: leak, do we store any references to home
+       char *env_home = g_getenv ("MONO_CONFIG");
+       if (env_home) {
+               mono_config_parse_file (env_home);
                return;
        }
 
@@ -673,10 +673,12 @@ mono_config_parse (const char *filename) {
 void
 mono_set_config_dir (const char *dir)
 {
-       /* If this variable is set, overrides the directory computed */
-       mono_cfg_dir = g_getenv ("MONO_CFG_DIR");
-       if (mono_cfg_dir == NULL)
-               mono_cfg_dir = mono_cfg_dir_allocated = g_strdup (dir);
+       /* If this environment variable is set, overrides the directory computed */
+       char *env_mono_cfg_dir = g_getenv ("MONO_CFG_DIR");
+       if (env_mono_cfg_dir == NULL && dir != NULL)
+               env_mono_cfg_dir = strdup (dir);
+
+       mono_cfg_dir = env_mono_cfg_dir;
 }
 
 const char* 
index 4e3b30f011541330aa48beb58265f4b6d68a9d17..6b394e0f8c87f5c242a5fd1dac777fc97779ad11 100644 (file)
@@ -542,7 +542,7 @@ initialize (void)
        threadpool_io->updates_size = 0;
 
        threadpool_io->backend = backend_poll;
-       if (g_getenv ("MONO_ENABLE_AIO") != NULL) {
+       if (g_hasenv ("MONO_ENABLE_AIO")) {
 #if defined(HAVE_EPOLL)
                threadpool_io->backend = backend_epoll;
 #elif defined(HAVE_KQUEUE)
index cda335d25a69471d6ef9d5a5114f3cda884f9f27..084a1e6792c0192caec7c0bc1aebdaa9c7285465 100644 (file)
@@ -5075,7 +5075,7 @@ mono_w32file_init (void)
 /*     mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
 /*                                         MONO_W32HANDLE_CAP_WAIT); */
 
-       if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+       if (g_hasenv ("MONO_STRICT_IO_EMULATION"))
                lock_while_writing = TRUE;
 }
 
index ce87be85147787fadc4017bb32d96a9be54733ac..598e75830157d60ff90910d5015df84757056c23 100644 (file)
@@ -2355,8 +2355,11 @@ mono_aot_init (void)
 #endif
        mono_counters_register ("Async JIT info size", MONO_COUNTER_INT|MONO_COUNTER_JIT, &async_jit_info_size);
 
-       if (g_getenv ("MONO_LASTAOT"))
-               mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT"));
+       char *lastaot = g_getenv ("MONO_LASTAOT");
+       if (lastaot) {
+               mono_last_aot_method = atoi (lastaot);
+               g_free (lastaot);
+       }
        aot_cache_init ();
 }
 
index e18cb98d643bd015f474be8bec56aa36e03706b6..547966a98cdef3a9e844f987cccdd6ae80b65f01 100644 (file)
@@ -882,7 +882,7 @@ mono_debugger_agent_parse_options (char *options)
        char **args, **ptr;
        char *host;
        int port;
-       const char *extra;
+       char *extra;
 
 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
        fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
@@ -890,8 +890,10 @@ mono_debugger_agent_parse_options (char *options)
 #endif
 
        extra = g_getenv ("MONO_SDB_ENV_OPTIONS");
-       if (extra)
+       if (extra) {
                options = g_strdup_printf ("%s,%s", options, extra);
+               g_free (extra);
+       }
 
        agent_config.enabled = TRUE;
        agent_config.suspend = TRUE;
index 9674a350f904aa1434741540ab3db5f58c94ab10..7b5a7c68a4cd6b46440eda8d9ae1aed1a18c69f5 100644 (file)
@@ -1605,7 +1605,7 @@ mono_main (int argc, char* argv[])
        darwin_change_default_file_handles ();
 #endif
 
-       if (g_getenv ("MONO_NO_SMP"))
+       if (g_hasenv ("MONO_NO_SMP"))
                mono_set_use_smp (FALSE);
        
        g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
@@ -1967,7 +1967,7 @@ mono_main (int argc, char* argv[])
        }
 #endif
 
-       if (g_getenv ("MONO_XDEBUG"))
+       if (g_hasenv ("MONO_XDEBUG"))
                enable_debugging = TRUE;
 
 #ifdef MONO_CROSS_COMPILE
@@ -2545,10 +2545,11 @@ mono_parse_env_options (int *ref_argc, char **ref_argv [])
 {
        char *ret;
        
-       const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
+       char *env_options = g_getenv ("MONO_ENV_OPTIONS");
        if (env_options == NULL)
                return;
        ret = mono_parse_options_from (env_options, ref_argc, ref_argv);
+       g_free (env_options);
        if (ret == NULL)
                return;
        fprintf (stderr, "%s", ret);
index 493dbc85a70b677bcf498cf3218b579892dc9528..047add7aab5d2816c7a99226ba101ced681182eb 100644 (file)
@@ -145,7 +145,7 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
 #ifdef HOST_WIN32
        const char *tmp = g_get_tmp_dir ();
 #endif
-       const char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
+       char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
        char *as_file;
        char *o_file;
        char *cmd;
@@ -276,7 +276,7 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
        unused = system (cmd); 
        g_free (cmd);
        if (!objdump_args)
-               objdump_args = "";
+               objdump_args = g_strdup ("");
 
        fflush (stdout);
 
@@ -293,6 +293,7 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
        cmd = g_strdup_printf (ARCH_PREFIX DIS_CMD " %s %s", objdump_args, o_file);
        unused = system (cmd);
        g_free (cmd);
+       g_free (objdump_args);
 #else
        g_assert_not_reached ();
 #endif /* HAVE_SYSTEM */
index 522438da5b06d3cf9168208ca95f5ed579144006..c11cd46ae081a02e008d6a99c2fe100d11373586 100644 (file)
@@ -812,10 +812,12 @@ static int ccount = 0;
             ins->inst_false_bb = NULL; \
             mono_link_bblock ((cfg), (cfg)->cbb, (truebb)); \
             MONO_ADD_INS ((cfg)->cbb, ins); \
-            if (g_getenv ("COUNT2") && ccount == atoi (g_getenv ("COUNT2")) - 1) { printf ("HIT: %d\n", cfg->cbb->block_num); } \
-            if (g_getenv ("COUNT2") && ccount < atoi (g_getenv ("COUNT2"))) { \
+            char *count2 = g_getenv ("COUNT2"); \
+            if (count2 && ccount == atoi (count2) - 1) { printf ("HIT: %d\n", cfg->cbb->block_num); } \
+            if (count2 && ccount < atoi (count2)) { \
                  cfg->cbb->extended = TRUE; \
             } else { NEW_BBLOCK ((cfg), falsebb); ins->inst_false_bb = (falsebb); mono_link_bblock ((cfg), (cfg)->cbb, (falsebb)); MONO_START_BB ((cfg), falsebb); } \
+            if (count2) g_free (count2); \
         } \
        } while (0)
 #else
index cfdc728c0d019e49bf5b19d187be5919eb0d0465..64ad6f4bd3c64343ae6a32520bf7fa7a6f9c79b5 100644 (file)
@@ -856,7 +856,7 @@ mono_analyze_liveness2 (MonoCompile *cfg)
        static guint32 disabled = -1;
 
        if (disabled == -1)
-               disabled = g_getenv ("DISABLED") != NULL;
+               disabled = g_hasenv ("DISABLED");
 
        if (disabled)
                return;
index 868097e617085fc86c9dfb0007a9666922bce742..e10f65766c97c3db26ecd53d7415bbc893ff44c2 100644 (file)
@@ -530,7 +530,11 @@ static void
 force_pass_linking (void)
 {
        // Make sure the rest is linked in, but never executed
-       if (g_getenv ("FOO") != (char*)-1)
+       char *foo = g_getenv ("FOO");
+       gboolean ret = (foo != (char*)-1);
+       g_free (foo);
+
+       if (ret) 
                return;
 
        // This is a subset of the passes in LinkAllPasses.h
index 6e28f2a0e60938c7a9cedd1f3827de7fec3a0617..6e30cdc295716ad1ca163fbaac78269ba4a07bd4 100644 (file)
@@ -4595,9 +4595,11 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        /* also consider num_locals? */
        /* Do the size check early to avoid creating vtables */
        if (!inline_limit_inited) {
-               if (g_getenv ("MONO_INLINELIMIT"))
-                       inline_limit = atoi (g_getenv ("MONO_INLINELIMIT"));
-               else
+               char *inlinelimit;
+               if ((inlinelimit = g_getenv ("MONO_INLINELIMIT"))) {
+                       inline_limit = atoi (inlinelimit);
+                       g_free (inlinelimit);
+               } else
                        inline_limit = INLINE_LENGTH_LIMIT;
                inline_limit_inited = TRUE;
        }
index 1ab5eeab15c852da548777f57ae2659139d46854..58964502b7fcbb47b0a892f7fc74319537b605ff 100644 (file)
@@ -811,6 +811,7 @@ mono_arch_init (void)
 
        if (soft && !strncmp (soft, "1", 1))
                arm_fpu = MONO_ARM_FPU_NONE;
+       g_free (soft);
 #endif
 #endif
 
@@ -858,6 +859,7 @@ mono_arch_init (void)
 
                thumb_supported = strstr (cpu_arch, "thumb") != NULL;
                thumb2_supported = strstr (cpu_arch, "thumb2") != NULL;
+               g_free (cpu_arch);
        }
 }
 
index 28e04d6d6288388a8ca141a481b7262cd1b7ea5a..0a61530c8922a371f1c686759a4e3abebb920f71 100644 (file)
@@ -52,7 +52,7 @@ mono_cross_helpers_run (void)
 #endif
 
 #ifndef USED_CROSS_COMPILER_OFFSETS
-       if (g_getenv ("DUMP_CROSS_OFFSETS"))
+       if (g_hasenv ("DUMP_CROSS_OFFSETS"))
                mono_dump_jit_offsets ();
 #endif
        
index d83009b18342bba963006a88588cd354e06ed4ab..a7eacef6bcfc310e27dff68e48ce3d95a77e4e4a 100644 (file)
@@ -924,8 +924,11 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
                 * Debugging aid to control the number of frames scanned precisely
                 */
                if (!precise_frame_limit_inited) {
-                       if (g_getenv ("MONO_PRECISE_COUNT"))
-                               precise_frame_limit = atoi (g_getenv ("MONO_PRECISE_COUNT"));
+                       char *mono_precise_count = g_getenv ("MONO_PRECISE_COUNT");
+                       if (mono_precise_count) {
+                               precise_frame_limit = atoi (mono_precise_count);
+                               g_free (mono_precise_count);
+                       }
                        precise_frame_limit_inited = TRUE;
                }
                                
@@ -1280,10 +1283,13 @@ mini_gc_init_gc_map (MonoCompile *cfg)
                static int precise_count;
 
                precise_count ++;
-               if (g_getenv ("MONO_GCMAP_COUNT")) {
-                       if (precise_count == atoi (g_getenv ("MONO_GCMAP_COUNT")))
+               char *mono_gcmap_count = g_getenv ("MONO_GCMAP_COUNT");
+               if (mono_gcmap_count) {
+                       int count = atoi (mono_gcmap_count);
+                       g_free (mono_gcmap_count);
+                       if (precise_count == count)
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
-                       if (precise_count > atoi (g_getenv ("MONO_GCMAP_COUNT")))
+                       if (precise_count > count)
                                return;
                }
        }
@@ -2503,6 +2509,7 @@ parse_debug_options (void)
                exit (1);
        }
        g_strfreev (opts);
+       g_free (env);
 }
 
 void
index 3fb5dfce0117b9e7df33932b2fa3a7de384465fd..880abaed5733b0e3bafea900e888031e529844c6 100644 (file)
@@ -6937,13 +6937,16 @@ emit_method_inner (EmitContext *ctx)
                static int count = 0;
                count ++;
 
-               if (g_getenv ("LLVM_COUNT")) {
-                       if (count == atoi (g_getenv ("LLVM_COUNT"))) {
+               char *llvm_count_str = g_getenv ("LLVM_COUNT");
+               if (llvm_count_str) {
+                       int lcount = atoi (llvm_count_str);
+                       g_free (llvm_count_str);
+                       if (count == lcount) {
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
                                fflush (stdout);
                                last = TRUE;
                        }
-                       if (count > atoi (g_getenv ("LLVM_COUNT"))) {
+                       if (count > lcount) {
                                set_failure (ctx, "count");
                                return;
                        }
index c5b6750559c9f3eb66cedc0d92ececdfabb35ed0..ff1dda35d6d8c9a85fa20a31b756bac1cdb07aa4 100644 (file)
@@ -365,18 +365,18 @@ void mono_ppc_set_func_into_sigctx (void *sigctx, void *func);
 #ifdef DEBUG_ELFABIV2
 
 #define DEBUG_ELFABIV2_printf(a, ...) \
-{if (getenv("DEBUG_ELFABIV2")) { printf(a, ##__VA_ARGS__); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf(a, ##__VA_ARGS__); fflush(stdout); g_free (debug_env); } }
 
 #define DEBUG_ELFABIV2_mono_print_ins(a) \
-{if (getenv("DEBUG_ELFABIV2")) { if (!a) {printf("null\n");} else {mono_print_ins(a);} fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { if (!a) {printf("null\n");} else {mono_print_ins(a);} fflush(stdout); g_free (debug_env); } }
 
 extern char* mono_type_full_name (MonoType *type);
 
 #define DEBUG_ELFABIV2_mono_print_type(a) \
-{if (getenv("DEBUG_ELFABIV2")) { printf("%s, size: %d\n", mono_type_get_name(a), mini_type_stack_size (a, 0)); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf("%s, size: %d\n", mono_type_get_name(a), mini_type_stack_size (a, 0)); fflush(stdout); g_free (debug_env); } }
 
 #define DEBUG_ELFABIV2_mono_print_class(a) \
-{if (getenv("DEBUG_ELFABIV2")) { printf("%s\n", mono_type_get_name(&a->byval_arg)); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf("%s\n", mono_type_get_name(&a->byval_arg)); fflush(stdout); g_free (debug_env); } }
 
 #else
 
index d573c31ce04be54923e55f37bb708299940016df..9c3f28cbb8f6075370b2a9d6d7a1ef40df7d29da 100644 (file)
@@ -559,7 +559,7 @@ mono_debug_count (void)
 {
        static int count = 0;
        static gboolean inited;
-       static const char *value;
+       static char *value;
 
        count ++;
 
@@ -571,10 +571,13 @@ mono_debug_count (void)
        if (!value)
                return TRUE;
 
-       if (count == atoi (value))
+       int int_val = atoi (value);
+       g_free (value);
+
+       if (count == int_val)
                break_count ();
 
-       if (count > atoi (value))
+       if (count > int_val)
                return FALSE;
 
        return TRUE;
@@ -3204,13 +3207,14 @@ mini_parse_debug_option (const char *option)
 static void
 mini_parse_debug_options (void)
 {
-       const char *options = g_getenv ("MONO_DEBUG");
+       char *options = g_getenv ("MONO_DEBUG");
        gchar **args, **ptr;
 
        if (!options)
                return;
 
        args = g_strsplit (options, ",", -1);
+       g_free (options);
 
        for (ptr = args; ptr && *ptr; ptr++) {
                const char *arg = *ptr;
@@ -3599,8 +3603,9 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_threads_runtime_init (&ticallbacks);
 
-       if (g_getenv ("MONO_DEBUG") != NULL)
+       if (g_hasenv ("MONO_DEBUG")) {
                mini_parse_debug_options ();
+       }
 
        mono_code_manager_init ();
 
@@ -3619,15 +3624,16 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_unwind_init ();
 
-       if (mini_get_debug_options ()->lldb || g_getenv ("MONO_LLDB")) {
+       if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
                mono_lldb_init ("");
                mono_dont_free_domains = TRUE;
        }
 
 #ifdef XDEBUG_ENABLED
-       if (g_getenv ("MONO_XDEBUG")) {
-               const char *xdebug_opts = g_getenv ("MONO_XDEBUG");
-               mono_xdebug_init (xdebug_opts);
+       char *mono_xdebug = g_getenv ("MONO_XDEBUG");
+       if (mono_xdebug) {
+               mono_xdebug_init (mono_xdebug);
+               g_free (mono_xdebug);
                /* So methods for multiple domains don't have the same address */
                mono_dont_free_domains = TRUE;
                mono_using_xdebug = TRUE;
index b85c2242c69e8fc7fb8e2b4ddfce4cb25bdcd6ab..47b71ddd88ee7e7772b41f36b125f7c9ee1d1bd9 100644 (file)
@@ -5495,13 +5495,16 @@ mono_arch_is_inst_imm (gint64 imm)
 void
 mono_arch_finish_init (void)
 {
-       if (!g_getenv ("MONO_NO_TLS")) {
+       char *mono_no_tls = g_getenv ("MONO_NO_TLS");
+       if (!mono_no_tls) {
 #ifndef TARGET_WIN32
 #if MONO_XEN_OPT
                optimize_for_xen = access ("/proc/xen", F_OK) == 0;
 #endif
 #endif
-       }               
+       } else {
+               g_free (mono_no_tls);
+       }
 }
 
 void
index 21dd9c8f7ea21323fda7a86424318f7037c027b6..c0ce85bc0d6c1fc39e9738099cf23c9fada8a2ec 100644 (file)
@@ -3113,7 +3113,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
 #endif
        static gboolean verbose_method_inited;
-       static const char *verbose_method_name;
+       static char *verbose_method_name;
 
        InterlockedIncrement (&mono_jit_stats.methods_compiled);
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
@@ -3405,6 +3405,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                        if (strcmp (cfg->method->name, name) == 0)
                                cfg->verbose_level = 4;
                }
+               g_free (verbose_method_name);
        }
 
        cfg->intvars = (guint16 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * header->max_stack);
index b4b2751e34a872615453c3bb2ffa1629d256b534..3a7500e0b1247d4ad4a40b7a421a1c19832716d3 100644 (file)
@@ -4932,7 +4932,7 @@ mono_profiler_startup (const char *desc)
                if ((opt = match_option (p, "coverage", NULL)) != p) {
                        do_coverage = 1;
                        events |= MONO_PROFILE_ENTER_LEAVE;
-                       debug_coverage = (g_getenv ("MONO_PROFILER_DEBUG_COVERAGE") != NULL);
+                       debug_coverage = g_hasenv ("MONO_PROFILER_DEBUG_COVERAGE");
                        continue;
                }
                if ((opt = match_option (p, "onlycoverage", NULL)) != p) {
index ec27de4224b9520a93998439738af18de6bbf08d..88f0c68a2059c742b9fc48decd0d73daa6694137 100644 (file)
@@ -2912,7 +2912,7 @@ parse_double_in_interval (const char *env_var, const char *opt_name, const char
 void
 sgen_gc_init (void)
 {
-       const char *env;
+       char *env;
        char **opts, **ptr;
        char *major_collector_opt = NULL;
        char *minor_collector_opt = NULL;
@@ -2957,6 +2957,7 @@ sgen_gc_init (void)
 
        if ((env = g_getenv (MONO_GC_PARAMS_NAME)) || gc_params_options) {
                params_opts = g_strdup_printf ("%s,%s", gc_params_options ? gc_params_options : "", env ? env : "");
+               g_free (env);
        }
 
        if (params_opts) {
@@ -3174,6 +3175,7 @@ sgen_gc_init (void)
 
        if ((env = g_getenv (MONO_GC_DEBUG_NAME)) || gc_debug_options) {
                debug_opts = g_strdup_printf ("%s,%s", gc_debug_options ? gc_debug_options  : "", env ? env : "");
+               g_free (env);
        }
 
        if (debug_opts) {
index 51524916490be41b7181cf2cb0c697f5745dcdd6..9af2739b0868956b4893de27dd528c263ee504d2 100644 (file)
@@ -58,6 +58,7 @@ mono_check_mode_enabled (MonoCheckMode query)
 #endif
                        }
                        g_strfreev (env_split);
+                       g_free (env_string);
                }
 
                check_mode = env_check_mode;
@@ -71,10 +72,12 @@ mono_check_transition_limit (void)
        static int transition_limit = -1;
        if (transition_limit < 0) {
                const gchar *env_string = g_getenv ("MONO_CHECK_THREAD_TRANSITION_HISTORY");
-               if (env_string)
+               if (env_string) {
                        transition_limit = atoi (env_string);
-               else
+                       g_free (env_string);
+               } else {
                        transition_limit = 3;
+               }
        }
        return transition_limit;
 }
index 00fad690193a5f8415f4afc317b1c28afa97fd99..158db963ed0364f0cd7c26cbd201df407724b867 100644 (file)
@@ -33,8 +33,8 @@ static gboolean hwcap_inited = FALSE;
 void
 mono_hwcap_init (void)
 {
-       const char *verbose = g_getenv ("MONO_VERBOSE_HWCAP");
-       const char *conservative = g_getenv ("MONO_CONSERVATIVE_HWCAP");
+       char *verbose = g_getenv ("MONO_VERBOSE_HWCAP");
+       char *conservative = g_getenv ("MONO_CONSERVATIVE_HWCAP");
 
        if (hwcap_inited)
                return;
@@ -44,6 +44,9 @@ mono_hwcap_init (void)
 
        if (verbose && !strncmp (verbose, "1", 1))
                mono_hwcap_print ();
+
+       g_free (verbose);
+       g_free (conservative);
 }
 
 void
index 7e22eafa8cc9cf25b2c9870a6ad44c42e5e3df0b..c17e5d7203dd00a26b662c3a06731b51246f9fe6 100644 (file)
@@ -19,7 +19,7 @@ static inline gchar *mono_portability_find_file_internal (GString **report, cons
 
 void mono_portability_helpers_init (void)
 {
-        const gchar *env;
+        gchar *env;
 
        if (mono_io_portability_helpers != PORTABILITY_UNKNOWN)
                return;
@@ -52,6 +52,7 @@ void mono_portability_helpers_init (void)
                                 mono_io_portability_helpers |= (PORTABILITY_DRIVE | PORTABILITY_CASE);
                        }
                 }
+               g_free (env);
        }
 }
 
index 5cc59c77fbe6dd87bf56d097df56dc7380e9baf9..3228d6058f10e7fd8524c9eaf869d7bdc949fcdc 100644 (file)
@@ -43,10 +43,20 @@ mono_trace_init (void)
                mono_internal_current_level = G_LOG_LEVEL_ERROR;
                level_stack = g_queue_new();
 
-               mono_trace_set_mask_string(g_getenv("MONO_LOG_MASK"));
-               mono_trace_set_level_string(g_getenv("MONO_LOG_LEVEL"));
-               mono_trace_set_logheader_string(g_getenv("MONO_LOG_HEADER"));
-               mono_trace_set_logdest_string(g_getenv("MONO_LOG_DEST"));
+               char *mask = g_getenv ("MONO_LOG_MASK");
+               char *level = g_getenv ("MONO_LOG_LEVEL");
+               char *header = g_getenv ("MONO_LOG_HEADER");
+               char *dest = g_getenv ("MONO_LOG_DEST");
+
+               mono_trace_set_mask_string(mask);
+               mono_trace_set_level_string(level);
+               mono_trace_set_logheader_string(header);
+               mono_trace_set_logdest_string(dest);
+
+               g_free (mask);
+               g_free (level);
+               g_free (header);
+               g_free (dest);
        }
 }
 
index 10a190ff9b059383a5705e6e0e5d765a79a7122d..e2868f62de12e7eca24533ad4e500ec41037f710 100644 (file)
@@ -416,7 +416,7 @@ static gboolean
 shared_area_disabled (void)
 {
        if (!use_shared_area) {
-               if (g_getenv ("MONO_DISABLE_SHARED_AREA"))
+               if (g_hasenv ("MONO_DISABLE_SHARED_AREA"))
                        use_shared_area = -1;
                else
                        use_shared_area = 1;
index a51253c1d86a1baee8fb210a5fcdf4640358443c..4962795b621a489d9fa988e9bc2959f87503629c 100644 (file)
@@ -136,7 +136,7 @@ mono_rand_open (void)
                file = open (NAME_DEV_RANDOM, O_RDONLY);
 #endif
        if (file < 0)
-               use_egd = g_getenv("MONO_EGD_SOCKET") != NULL;
+               use_egd = g_hasenv ("MONO_EGD_SOCKET");
 
        status = 2;
 
@@ -158,13 +158,14 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, Mon
        error_init (error);
 
        if (use_egd) {
-               const char *socket_path = g_getenv ("MONO_EGD_SOCKET");
+               char *socket_path = g_getenv ("MONO_EGD_SOCKET");
                /* exception will be thrown in managed code */
                if (socket_path == NULL) {
                        *handle = NULL;
                        return FALSE;
                }
                get_entropy_from_egd (socket_path, buffer, buffer_size, error);
+               g_free (socket_path);
        } else {
                /* Read until the buffer is filled. This may block if using NAME_DEV_RANDOM. */
                gint count = 0;
index ed6b1807a3a22a97bcba35b62862c27e3a09e670..2111413c94f366f8f335f5b834cd2f2cd45f0ea1 100644 (file)
@@ -429,7 +429,7 @@ mono_threads_is_coop_enabled (void)
 #else
        static int is_coop_enabled = -1;
        if (G_UNLIKELY (is_coop_enabled == -1))
-               is_coop_enabled = g_getenv ("MONO_ENABLE_COOP") != NULL ? 1 : 0;
+               is_coop_enabled = g_hasenv ("MONO_ENABLE_COOP") ? 1 : 0;
        return is_coop_enabled == 1;
 #endif
 }
index a468cd9383db908131ff4eaf1f02de369c3ca701..fcff68c318dd5a87a54f58c73c583fb564034f29 100644 (file)
@@ -680,7 +680,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        gboolean res;
        threads_callbacks = *callbacks;
        thread_info_size = info_size;
-       const char *sleepLimit;
+       char *sleepLimit;
 #ifdef HOST_WIN32
        res = mono_native_tls_alloc (&thread_info_key, NULL);
        res = mono_native_tls_alloc (&thread_exited_key, NULL);
@@ -704,6 +704,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
                        sleepWarnDuration = threshold / 20;
                } else
                        g_warning("MONO_SLEEP_ABORT_LIMIT must be a number >= 40");
+               g_free (sleepLimit);
        }
 
        mono_os_sem_init (&global_suspend_semaphore, 1);
index ca5423cfbab59022afd6d503672b1cf81032284e..d286bd05da6f9b28c1ede7c1fe0a4cea9b187c36 100644 (file)
@@ -45,7 +45,7 @@ mono_unicode_from_external (const gchar *in, gsize *bytes)
 {
        gchar *res=NULL;
        gchar **encodings;
-       const gchar *encoding_list;
+       gchar *encoding_list;
        int i;
        glong lbytes;
        
@@ -55,10 +55,11 @@ mono_unicode_from_external (const gchar *in, gsize *bytes)
        
        encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS");
        if(encoding_list==NULL) {
-               encoding_list = "";
+               encoding_list = g_strdup("");
        }
        
        encodings=g_strsplit (encoding_list, ":", 0);
+       g_free (encoding_list);
        for(i=0;encodings[i]!=NULL; i++) {
                /* "default_locale" is a special case encoding */
                if(!strcmp (encodings[i], "default_locale")) {
@@ -119,7 +120,7 @@ gchar *mono_utf8_from_external (const gchar *in)
 {
        gchar *res=NULL;
        gchar **encodings;
-       const gchar *encoding_list;
+       gchar *encoding_list;
        int i;
        
        if(in==NULL) {
@@ -128,10 +129,11 @@ gchar *mono_utf8_from_external (const gchar *in)
        
        encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS");
        if(encoding_list==NULL) {
-               encoding_list = "";
+               encoding_list = g_strdup("");
        }
        
        encodings=g_strsplit (encoding_list, ":", 0);
+       g_free (encoding_list);
        for(i=0;encodings[i]!=NULL; i++) {
                
                /* "default_locale" is a special case encoding */
@@ -174,7 +176,7 @@ gchar *mono_utf8_from_external (const gchar *in)
 gchar *mono_unicode_to_external (const gunichar2 *uni)
 {
        gchar *utf8;
-       const gchar *encoding_list;
+       gchar *encoding_list;
        
        /* Turn the unicode into utf8 to start with, because its
         * easier to work with gchar * than gunichar2 *
@@ -191,6 +193,7 @@ gchar *mono_unicode_to_external (const gunichar2 *uni)
                int i;
                
                encodings=g_strsplit (encoding_list, ":", 0);
+               g_free (encoding_list);
                for(i=0; encodings[i]!=NULL; i++) {
                        if(!strcmp (encodings[i], "default_locale")) {
                                res=g_locale_from_utf8 (utf8, -1, NULL, NULL,