From 5b7233548f7f16a50650274cfb36d4cfc5769566 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Mon, 28 Sep 2020 18:11:50 +0100
Subject: [PATCH] system-info: Always pass around a non-NULL environment block

Instead of calling getenv() if the environment is NULL, we determine
what's in the environment on creating the SrtSystemInfo and then pass
it around as a parameter.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 steam-runtime-tools/architecture-internal.h |  3 +-
 steam-runtime-tools/architecture.c          | 12 ++--
 steam-runtime-tools/graphics-internal.h     |  3 +-
 steam-runtime-tools/graphics.c              | 75 +++++++++------------
 steam-runtime-tools/library.c               | 10 ++-
 steam-runtime-tools/locale-internal.h       |  3 +-
 steam-runtime-tools/locale.c                |  7 +-
 steam-runtime-tools/runtime.c               |  8 +--
 steam-runtime-tools/steam.c                 | 10 +--
 steam-runtime-tools/system-info.c           | 44 ++++++------
 steam-runtime-tools/utils-internal.h        |  2 +
 steam-runtime-tools/utils.c                 | 18 +++++
 12 files changed, 104 insertions(+), 91 deletions(-)

diff --git a/steam-runtime-tools/architecture-internal.h b/steam-runtime-tools/architecture-internal.h
index 0ec66b4f2..8461ab924 100644
--- a/steam-runtime-tools/architecture-internal.h
+++ b/steam-runtime-tools/architecture-internal.h
@@ -29,7 +29,8 @@
 #include <glib.h>
 #include <json-glib/json-glib.h>
 
-G_GNUC_INTERNAL gboolean _srt_architecture_can_run (const char *helpers_path,
+G_GNUC_INTERNAL gboolean _srt_architecture_can_run (gchar **envp,
+                                                    const char *helpers_path,
                                                     const char *multiarch);
 
 gboolean _srt_architecture_can_run_from_report (JsonObject *json_obj);
diff --git a/steam-runtime-tools/architecture.c b/steam-runtime-tools/architecture.c
index c3d1fffdf..eb740f167 100644
--- a/steam-runtime-tools/architecture.c
+++ b/steam-runtime-tools/architecture.c
@@ -44,7 +44,8 @@
  */
 
 gboolean
-_srt_architecture_can_run (const char *helpers_path,
+_srt_architecture_can_run (gchar **envp,
+                           const char *helpers_path,
                            const char *multiarch)
 {
   gchar *helper = NULL;
@@ -56,6 +57,7 @@ _srt_architecture_can_run (const char *helpers_path,
   const gchar *ld_preload;
   gchar *filtered_preload = NULL;
 
+  g_return_val_if_fail (envp != NULL, FALSE);
   g_return_val_if_fail (multiarch != NULL, FALSE);
   g_return_val_if_fail (_srt_check_not_setuid (), FALSE);
 
@@ -72,7 +74,7 @@ _srt_architecture_can_run (const char *helpers_path,
   g_debug ("Testing architecture %s with %s",
            multiarch, (const char *) g_ptr_array_index (argv, 0));
 
-  my_environ = g_get_environ ();
+  my_environ = g_strdupv (envp);
   ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD");
   if (ld_preload != NULL)
     {
@@ -138,7 +140,8 @@ out:
 gboolean
 srt_architecture_can_run_i386 (void)
 {
-  return _srt_architecture_can_run (NULL, SRT_ABI_I386);
+  return _srt_architecture_can_run ((gchar **) _srt_peek_environ_nonnull (),
+                                    NULL, SRT_ABI_I386);
 }
 
 /**
@@ -156,7 +159,8 @@ srt_architecture_can_run_i386 (void)
 gboolean
 srt_architecture_can_run_x86_64 (void)
 {
-  return _srt_architecture_can_run (NULL, SRT_ABI_X86_64);
+  return _srt_architecture_can_run ((gchar **) _srt_peek_environ_nonnull (),
+                                    NULL, SRT_ABI_X86_64);
 }
 
 /**
diff --git a/steam-runtime-tools/graphics-internal.h b/steam-runtime-tools/graphics-internal.h
index 3f29332cf..3fe4f1954 100644
--- a/steam-runtime-tools/graphics-internal.h
+++ b/steam-runtime-tools/graphics-internal.h
@@ -74,7 +74,8 @@ static inline int _srt_graphics_hash_key(SrtWindowSystem winsys, SrtRenderingInt
 
 #ifndef __GTK_DOC_IGNORE__
 
-G_GNUC_INTERNAL SrtGraphicsIssues _srt_check_graphics (const char *helpers_path,
+G_GNUC_INTERNAL SrtGraphicsIssues _srt_check_graphics (gchar **envp,
+                                                       const char *helpers_path,
                                                        SrtTestFlags test_flags,
                                                        const char *multiarch_tuple,
                                                        SrtWindowSystem window_system,
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index d5e82151c..f49c05dc4 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -681,11 +681,9 @@ _argv_for_list_vdpau_drivers (gchar **envp,
   const gchar *vdpau_driver = NULL;
   GPtrArray *argv;
 
-  if (envp != NULL)
-    vdpau_driver = g_environ_getenv (envp, "VDPAU_DRIVER");
-  else
-    vdpau_driver = g_getenv ("VDPAU_DRIVER");
+  g_return_val_if_fail (envp != NULL, NULL);
 
+  vdpau_driver = g_environ_getenv (envp, "VDPAU_DRIVER");
   argv = _srt_get_helper (helpers_path, multiarch_tuple, "capsule-capture-libs",
                           SRT_HELPER_FLAGS_SEARCH_PATH, error);
 
@@ -774,6 +772,7 @@ _argv_for_list_glx_icds_in_path (const char *helpers_path,
 
 /**
  * _srt_check_library_vendor:
+ * @envp: (not nullable): The environment
  * @multiarch_tuple: A multiarch tuple to check e.g. i386-linux-gnu
  * @window_system: The window system to check.
  * @rendering_interface: The graphics renderer to check.
@@ -798,7 +797,8 @@ _argv_for_list_glx_icds_in_path (const char *helpers_path,
  *  %SRT_RENDERING_INTERFACE_VULKAN or if there was a problem loading the library.
  */
 static SrtGraphicsLibraryVendor
-_srt_check_library_vendor (const char *multiarch_tuple,
+_srt_check_library_vendor (gchar **envp,
+                           const char *multiarch_tuple,
                            SrtWindowSystem window_system,
                            SrtRenderingInterface rendering_interface)
 {
@@ -808,6 +808,8 @@ _srt_check_library_vendor (const char *multiarch_tuple,
   SrtLibraryIssues issues;
   const char * const *dependencies;
 
+  g_return_val_if_fail (envp != NULL, SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN);
+
   /* Vulkan, VDPAU and VA-API are always vendor-neutral, so it doesn't make sense to check it.
    * We simply return SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN */
   if (rendering_interface == SRT_RENDERING_INTERFACE_VULKAN ||
@@ -950,6 +952,7 @@ _srt_run_helper (GStrv *my_environ,
 
 /**
  * _srt_check_graphics:
+ * @envp: (not nullable): Used instead of `environ`
  * @helpers_path: An optional path to find wflinfo helpers, PATH is used if null.
  * @test_flags: Flags used during automated testing
  * @multiarch_tuple: A multiarch tuple to check e.g. i386-linux-gnu
@@ -963,7 +966,8 @@ _srt_run_helper (GStrv *my_environ,
  *  if no problems were found
  */
 G_GNUC_INTERNAL SrtGraphicsIssues
-_srt_check_graphics (const char *helpers_path,
+_srt_check_graphics (gchar **envp,
+                     const char *helpers_path,
                      SrtTestFlags test_flags,
                      const char *multiarch_tuple,
                      SrtWindowSystem window_system,
@@ -992,6 +996,7 @@ _srt_check_graphics (const char *helpers_path,
   g_return_val_if_fail (((unsigned) window_system) < SRT_N_WINDOW_SYSTEMS, SRT_GRAPHICS_ISSUES_UNKNOWN);
   g_return_val_if_fail (((unsigned) rendering_interface) < SRT_N_RENDERING_INTERFACES, SRT_GRAPHICS_ISSUES_UNKNOWN);
   g_return_val_if_fail (_srt_check_not_setuid (), SRT_GRAPHICS_ISSUES_UNKNOWN);
+  g_return_val_if_fail (envp != NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
 
   GPtrArray *argv = _argv_for_graphics_test (helpers_path,
                                              test_flags,
@@ -1008,7 +1013,7 @@ _srt_check_graphics (const char *helpers_path,
       goto out;
     }
 
-  my_environ = g_get_environ ();
+  my_environ = g_strdupv (envp);
   ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD");
   if (ld_preload != NULL)
     {
@@ -1016,7 +1021,9 @@ _srt_check_graphics (const char *helpers_path,
       my_environ = g_environ_setenv (my_environ, "LD_PRELOAD", filtered_preload, TRUE);
     }
 
-  library_vendor = _srt_check_library_vendor (multiarch_tuple, window_system, rendering_interface);
+  library_vendor = _srt_check_library_vendor (envp, multiarch_tuple,
+                                              window_system,
+                                              rendering_interface);
 
   switch (rendering_interface)
     {
@@ -2481,8 +2488,8 @@ get_glvnd_datadir (void)
 /*
  * _srt_load_egl_icds:
  * @sysroot: (not nullable): The root directory, usually `/`
- * @envp: (array zero-terminated=1): Behave as though `environ` was this
- *  array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ`
+ *  was this array
  * @multiarch_tuples: (nullable): If not %NULL, and a Flatpak environment
  *  is detected, assume a freedesktop-sdk-based runtime and look for
  *  GL extensions for these multiarch tuples
@@ -2497,7 +2504,6 @@ _srt_load_egl_icds (const char *sysroot,
                     gchar **envp,
                     const char * const *multiarch_tuples)
 {
-  gchar **environ_copy = NULL;
   const gchar *value;
   gsize i;
   /* To avoid O(n**2) performance, we build this list in reverse order,
@@ -2506,12 +2512,7 @@ _srt_load_egl_icds (const char *sysroot,
 
   g_return_val_if_fail (sysroot != NULL, NULL);
   g_return_val_if_fail (_srt_check_not_setuid (), NULL);
-
-  if (envp == NULL)
-    {
-      environ_copy = g_get_environ ();
-      envp = environ_copy;
-    }
+  g_return_val_if_fail (envp != NULL, NULL);
 
   /* See
    * https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md
@@ -2572,7 +2573,6 @@ _srt_load_egl_icds (const char *sysroot,
       g_free (flatpak_info);
     }
 
-  g_strfreev (environ_copy);
   return g_list_reverse (ret);
 }
 
@@ -3008,7 +3008,7 @@ srt_glx_icd_new (const gchar *library_soname,
 
 /**
  * _srt_get_modules_from_path:
- * @envp: (array zero-terminated=1): Behave as though `environ` was this array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this array
  * @helpers_path: (nullable): An optional path to find "inspect-library" helper, PATH
  *  is used if %NULL
  * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple
@@ -3043,6 +3043,7 @@ _srt_get_modules_from_path (gchar **envp,
   GDir *dir = NULL;
   SrtLibraryIssues issues;
 
+  g_return_if_fail (envp != NULL);
   g_return_if_fail (module_directory_path != NULL);
   g_return_if_fail (drivers_out != NULL);
 
@@ -3136,7 +3137,7 @@ _srt_get_modules_from_path (gchar **envp,
 
 /**
  * _srt_list_modules_from_directory:
- * @envp: (array zero-terminated=1): Behave as though `environ` was this array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this array
  * @argv: (array zero-terminated=1) (not nullable): The `argv` of the helper to use
  * @tmp_directory: (not nullable) (type filename): Full path to the destination
  *  directory used by the "capsule-capture-libs" helper
@@ -3177,6 +3178,7 @@ _srt_list_modules_from_directory (gchar **envp,
   gchar *soname_path = NULL;
 
   g_return_if_fail (argv != NULL);
+  g_return_if_fail (envp != NULL);
   g_return_if_fail (tmp_directory != NULL);
   g_return_if_fail (known_table != NULL);
   g_return_if_fail (modules_out != NULL);
@@ -3296,7 +3298,7 @@ out:
 /**
  * _srt_get_modules_full:
  * @sysroot: (not nullable): The root directory, usually `/`
- * @envp: (array zero-terminated=1): Behave as though `environ` was this array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this array
  * @helpers_path: (nullable): An optional path to find "inspect-library" helper, PATH is used if %NULL
  * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple
  *  such as %SRT_ABI_X86_64
@@ -3336,6 +3338,7 @@ _srt_get_modules_full (const char *sysroot,
   GPtrArray *vdpau_argv = NULL;
   GError *error = NULL;
 
+  g_return_if_fail (envp != NULL);
   g_return_if_fail (multiarch_tuple != NULL);
   g_return_if_fail (drivers_out != NULL);
   g_return_if_fail (sysroot != NULL);
@@ -3364,18 +3367,9 @@ _srt_get_modules_full (const char *sysroot,
         g_return_if_reached ();
     }
 
-  if (envp != NULL)
-    {
-      drivers_path = g_environ_getenv (envp, env_override);
-      force_elf_class = g_environ_getenv (envp, "SRT_TEST_FORCE_ELF");
-      ld_library_path = g_environ_getenv (envp, "LD_LIBRARY_PATH");
-    }
-  else
-    {
-      drivers_path = g_getenv (env_override);
-      force_elf_class = g_getenv ("SRT_TEST_FORCE_ELF");
-      ld_library_path = g_getenv ("LD_LIBRARY_PATH");
-    }
+  drivers_path = g_environ_getenv (envp, env_override);
+  force_elf_class = g_environ_getenv (envp, "SRT_TEST_FORCE_ELF");
+  ld_library_path = g_environ_getenv (envp, "LD_LIBRARY_PATH");
 
   flatpak_info = g_build_filename (sysroot, ".flatpak-info", NULL);
   drivers_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -3667,7 +3661,7 @@ out:
 /*
  * _srt_list_glx_icds:
  * @sysroot: (not nullable): The root directory, usually `/`
- * @envp: (array zero-terminated=1): Behave as though `environ` was this array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this array
  * @helpers_path: (nullable): An optional path to find "capsule-capture-libs" helper,
  *  PATH is used if %NULL
  * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple
@@ -3764,7 +3758,7 @@ out:
 /**
  * _srt_list_graphics_modules:
  * @sysroot: (not nullable): The root directory, usually `/`
- * @envp: (array zero-terminated=1): Behave as though `environ` was this array
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this array
  * @helpers_path: (nullable): An optional path to find "inspect-library" helper, PATH is used if %NULL
  * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple
  *  such as %SRT_ABI_X86_64
@@ -4826,7 +4820,7 @@ get_vulkan_sysconfdir (void)
 /*
  * _srt_load_vulkan_icds:
  * @sysroot: (not nullable): The root directory, usually `/`
- * @envp: (array zero-terminated=1): Behave as though `environ` was this
+ * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` was this
  *  array
  * @multiarch_tuples: (nullable): If not %NULL, and a Flatpak environment
  *  is detected, assume a freedesktop-sdk-based runtime and look for
@@ -4842,7 +4836,6 @@ _srt_load_vulkan_icds (const char *sysroot,
                        gchar **envp,
                        const char * const *multiarch_tuples)
 {
-  gchar **environ_copy = NULL;
   const gchar *value;
   gsize i;
   /* To avoid O(n**2) performance, we build this list in reverse order,
@@ -4850,12 +4843,7 @@ _srt_load_vulkan_icds (const char *sysroot,
   GList *ret = NULL;
 
   g_return_val_if_fail (_srt_check_not_setuid (), NULL);
-
-  if (envp == NULL)
-    {
-      environ_copy = g_get_environ ();
-      envp = environ_copy;
-    }
+  g_return_val_if_fail (envp != NULL, NULL);
 
   /* See
    * https://github.com/KhronosGroup/Vulkan-Loader/blob/master/loader/LoaderAndLayerInterface.md#icd-manifest-file-format
@@ -4980,7 +4968,6 @@ _srt_load_vulkan_icds (const char *sysroot,
       g_free (tmp);
     }
 
-  g_strfreev (environ_copy);
   return g_list_reverse (ret);
 }
 
diff --git a/steam-runtime-tools/library.c b/steam-runtime-tools/library.c
index 3401b6987..a8c0d8265 100644
--- a/steam-runtime-tools/library.c
+++ b/steam-runtime-tools/library.c
@@ -613,7 +613,8 @@ srt_check_library_presence (const char *requested_name,
                             SrtLibrary **more_details_out)
 {
   return _srt_check_library_presence (NULL, requested_name, multiarch,
-                                      symbols_path, NULL, NULL,
+                                      symbols_path, NULL,
+                                      (gchar **) _srt_peek_environ_nonnull (),
                                       symbols_format, more_details_out);
 }
 
@@ -656,6 +657,7 @@ _srt_check_library_presence (const char *helpers_path,
   g_return_val_if_fail (multiarch != NULL, SRT_LIBRARY_ISSUES_UNKNOWN);
   g_return_val_if_fail (more_details_out == NULL || *more_details_out == NULL,
                         SRT_LIBRARY_ISSUES_UNKNOWN);
+  g_return_val_if_fail (envp != NULL, SRT_LIBRARY_ISSUES_UNKNOWN);
   g_return_val_if_fail (_srt_check_not_setuid (), SRT_LIBRARY_ISSUES_UNKNOWN);
 
   if (symbols_path == NULL)
@@ -714,11 +716,7 @@ _srt_check_library_presence (const char *helpers_path,
   /* NULL terminate the array */
   g_ptr_array_add (argv, NULL);
 
-  if (envp == NULL)
-    my_environ = g_get_environ ();
-  else
-    my_environ = g_strdupv (envp);
-
+  my_environ = g_strdupv (envp);
   ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD");
   if (ld_preload != NULL)
     {
diff --git a/steam-runtime-tools/locale-internal.h b/steam-runtime-tools/locale-internal.h
index 0a036744f..1d3ac5e1e 100644
--- a/steam-runtime-tools/locale-internal.h
+++ b/steam-runtime-tools/locale-internal.h
@@ -55,7 +55,8 @@ _srt_locale_new (const char *requested_name,
 }
 
 G_GNUC_INTERNAL
-SrtLocale *_srt_check_locale (const char *helpers_path,
+SrtLocale *_srt_check_locale (gchar **envp,
+                              const char *helpers_path,
                               const char *multiarch_tuple,
                               const char *requested_name,
                               GError **error);
diff --git a/steam-runtime-tools/locale.c b/steam-runtime-tools/locale.c
index f10a05c83..d8d8b2eb8 100644
--- a/steam-runtime-tools/locale.c
+++ b/steam-runtime-tools/locale.c
@@ -192,6 +192,7 @@ srt_locale_class_init (SrtLocaleClass *cls)
 
 /*
  * _srt_check_locale:
+ * @envp: Environment variables
  * @helpers_path: Path to find helper executables
  * @multiarch_tuple: Multiarch tuple of helper executable to use
  * @requested_name: The locale name to check for
@@ -205,7 +206,8 @@ srt_locale_class_init (SrtLocaleClass *cls)
  * Returns: (transfer full): A #SrtLocale object, or %NULL
  */
 SrtLocale *
-_srt_check_locale (const char *helpers_path,
+_srt_check_locale (gchar **envp,
+                   const char *helpers_path,
                    const char *multiarch_tuple,
                    const char *requested_name,
                    GError **error)
@@ -222,6 +224,7 @@ _srt_check_locale (const char *helpers_path,
   int exit_status;
 
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+  g_return_val_if_fail (envp != NULL, NULL);
   g_return_val_if_fail (requested_name != NULL, NULL);
   g_return_val_if_fail (_srt_check_not_setuid (), NULL);
 
@@ -234,7 +237,7 @@ _srt_check_locale (const char *helpers_path,
   if (argv == NULL)
     goto out;
 
-  my_environ = g_get_environ ();
+  my_environ = g_strdupv (envp);
   ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD");
   if (ld_preload != NULL)
     {
diff --git a/steam-runtime-tools/runtime.c b/steam-runtime-tools/runtime.c
index 82efce91a..be908f2e3 100644
--- a/steam-runtime-tools/runtime.c
+++ b/steam-runtime-tools/runtime.c
@@ -127,8 +127,7 @@ same_stat (GStatBuf *left,
  * @bin32: (nullable): The absolute path to `ubuntu12_32`
  * @expected_version: (nullable): The expected version number of the
  *  Steam Runtime
- * @custom_environ: (nullable): The list of environment variables to use. If NULL
- *  g_get_environ will be used instead.
+ * @custom_environ: (not nullable): The list of environment variables to use
  * @version_out: (optional) (type utf8) (out): The actual version number
  * @path_out: (optional) (type filename) (out): The absolute path of the
  *  Steam Runtime
@@ -167,10 +166,7 @@ _srt_runtime_check (const char *bin32,
                         SRT_RUNTIME_ISSUES_UNKNOWN);
   g_return_val_if_fail (_srt_check_not_setuid (), SRT_RUNTIME_ISSUES_UNKNOWN);
 
-  if (custom_environ == NULL)
-    my_environ = g_get_environ ();
-  else
-    my_environ = g_strdupv (custom_environ);
+  my_environ = g_strdupv (custom_environ);
 
   env = g_environ_getenv (my_environ, "STEAM_RUNTIME");
 
diff --git a/steam-runtime-tools/steam.c b/steam-runtime-tools/steam.c
index 47103d4f5..3cb2f583d 100644
--- a/steam-runtime-tools/steam.c
+++ b/steam-runtime-tools/steam.c
@@ -270,13 +270,14 @@ srt_steam_get_bin32_path (SrtSteam *self)
 
 /**
  * _srt_steam_check:
- * @my_environ: (nullable): The list of environment variables to use.
+ * @my_environ: (not nullable): The list of environment variables to use.
  * @more_details_out: (out) (optional) (transfer full): Used to return an
  *  #SrtSteam object representing information about the current Steam
  *  installation. Free with `g_object_unref()`.
  *
- * Please note that @my_environ can't be used when checking the default
- * desktop entry that handles `steam:` URIs.
+ * Please note that when checking the default desktop entry that handles
+ * `steam:` URIs, @my_environ is ignored and the real environment is used
+ * instead.
  *
  * Returns: A bitfield containing problems, or %SRT_STEAM_ISSUES_NONE
  *  if no problems were found
@@ -304,11 +305,12 @@ _srt_steam_check (const GStrv my_environ,
   GStrv env = NULL;
   GError *error = NULL;
 
+  g_return_val_if_fail (my_environ != NULL, SRT_STEAM_ISSUES_UNKNOWN);
   g_return_val_if_fail (_srt_check_not_setuid (), SRT_STEAM_ISSUES_UNKNOWN);
   g_return_val_if_fail (more_details_out == NULL || *more_details_out == NULL,
                         SRT_STEAM_ISSUES_UNKNOWN);
 
-  env = (my_environ == NULL) ? g_get_environ () : g_strdupv (my_environ);
+  env = g_strdupv (my_environ);
 
   home = g_environ_getenv (env, "HOME");
   user_data = g_environ_getenv (env, "XDG_DATA_HOME");
diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index 770c701d0..997a2df65 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -98,7 +98,7 @@ struct _SrtSystemInfo
   gchar *expectations;
   /* Root directory to inspect, usually "/" */
   gchar *sysroot;
-  /* Fake environment variables, or %NULL to use the real environment */
+  /* Environment variables */
   gchar **env;
   /* Path to find helper executables, or %NULL to use $SRT_HELPERS_PATH
    * or the installed helpers */
@@ -322,6 +322,7 @@ srt_system_info_init (SrtSystemInfo *self)
   self->container.type = SRT_CONTAINER_TYPE_UNKNOWN;
 
   srt_system_info_set_sysroot (self, "/");
+  srt_system_info_set_environ (self, NULL);
 }
 
 static void
@@ -570,6 +571,7 @@ SrtSystemInfo *
 srt_system_info_new_from_json (const char *path,
                                GError **error)
 {
+  static const char * const no_strings[] = { NULL };
   SrtSystemInfo *info = NULL;
   JsonObject *json_obj = NULL;
   JsonObject *json_sub_obj = NULL;
@@ -581,6 +583,7 @@ srt_system_info_new_from_json (const char *path,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, (gchar * const *) no_strings);
 
   parser = json_parser_new ();
 
@@ -783,7 +786,7 @@ srt_system_info_can_run (SrtSystemInfo *self,
 
   if (abi->can_run == TRI_MAYBE)
     {
-      if (_srt_architecture_can_run (self->helpers_path, multiarch_tuple))
+      if (_srt_architecture_can_run (self->env, self->helpers_path, multiarch_tuple))
         abi->can_run = TRI_YES;
       else
         abi->can_run = TRI_NO;
@@ -846,15 +849,6 @@ graphics_compare (SrtGraphics *a, SrtGraphics *b)
   return (aKey < bKey) ? -1 : (aKey > bKey);
 }
 
-static gchar **
-get_environ (SrtSystemInfo *self)
-{
-  if (self->env != NULL)
-    return self->env;
-  else
-    return environ;
-}
-
 /* Path components from ${prefix} to steamrt expectations */
 #define STEAMRT_EXPECTATIONS "lib", "steamrt", "expectations"
 
@@ -869,7 +863,7 @@ ensure_expectations (SrtSystemInfo *self)
       const char *runtime;
       gchar *def = NULL;
 
-      runtime = g_environ_getenv (get_environ (self), "STEAM_RUNTIME");
+      runtime = g_environ_getenv (self->env, "STEAM_RUNTIME");
 
       if (runtime != NULL && runtime[0] == '/')
         {
@@ -1032,7 +1026,7 @@ ensure_overrides_cached (SrtSystemInfo *self)
 
       if (!g_spawn_sync (self->sysroot,     /* working directory */
                         (gchar **) argv,
-                        get_environ (self),
+                        self->env,
                         G_SPAWN_SEARCH_PATH,
                         _srt_child_setup_unblock_signals,
                         NULL,    /* user data */
@@ -1135,7 +1129,7 @@ ensure_pinned_libs_cached (SrtSystemInfo *self)
 
       if (!g_spawn_sync (runtime, /* working directory */
                         (gchar **) argv,
-                        get_environ (self),
+                        self->env,
                         G_SPAWN_SEARCH_PATH,
                         _srt_child_setup_unblock_signals,
                         NULL,    /* user data */
@@ -1174,7 +1168,7 @@ ensure_pinned_libs_cached (SrtSystemInfo *self)
 
       if (!g_spawn_sync (runtime,    /* working directory */
                         (gchar **) argv,
-                        get_environ (self),
+                        self->env,
                         G_SPAWN_SEARCH_PATH,
                         _srt_child_setup_unblock_signals,
                         NULL,    /* user data */
@@ -1455,7 +1449,7 @@ srt_system_info_check_libraries (SrtSystemInfo *self,
                                                                           multiarch_tuple,
                                                                           symbols_file,
                                                                           (const gchar * const *)hidden_deps,
-                                                                          NULL,
+                                                                          self->env,
                                                                           SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
                                                                           &library);
               g_hash_table_insert (abi->cached_results, soname, library);
@@ -1600,7 +1594,7 @@ srt_system_info_check_library (SrtSystemInfo *self,
                                                         multiarch_tuple,
                                                         symbols_file,
                                                         (const gchar * const *)hidden_deps,
-                                                        NULL,
+                                                        self->env,
                                                         SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
                                                         &library);
                   g_hash_table_insert (abi->cached_results, soname_found, library);
@@ -1626,7 +1620,7 @@ srt_system_info_check_library (SrtSystemInfo *self,
                                         multiarch_tuple,
                                         NULL,
                                         NULL,
-                                        NULL,
+                                        self->env,
                                         SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
                                         &library);
   g_hash_table_insert (abi->cached_results, g_strdup (requested_name), library);
@@ -1755,7 +1749,8 @@ srt_system_info_check_graphics (SrtSystemInfo *self,
     return SRT_GRAPHICS_ISSUES_UNKNOWN;
 
   graphics = NULL;
-  issues = _srt_check_graphics (self->helpers_path,
+  issues = _srt_check_graphics (self->env,
+                                self->helpers_path,
                                 self->test_flags,
                                 multiarch_tuple,
                                 window_system,
@@ -1891,7 +1886,11 @@ srt_system_info_set_environ (SrtSystemInfo *self,
   forget_pinned_libs (self);
   g_clear_pointer (&self->cached_driver_environment, g_strfreev);
   g_strfreev (self->env);
-  self->env = g_strdupv ((gchar **) env);
+
+  if (env != NULL)
+    self->env = g_strdupv ((gchar **) env);
+  else
+    self->env = g_strdupv ((gchar **) _srt_peek_environ_nonnull ());
 
   /* Forget what we know about Steam because it is bounded to the environment. */
   forget_steam (self);
@@ -2748,7 +2747,8 @@ srt_system_info_check_locale (SrtSystemInfo *self,
       GError *local_error = NULL;
       SrtLocale *locale = NULL;
 
-      locale = _srt_check_locale (self->helpers_path,
+      locale = _srt_check_locale (self->env,
+                                  self->helpers_path,
                                   srt_system_info_get_primary_multiarch_tuple (self),
                                   g_quark_to_string (quark),
                                   &local_error);
@@ -3121,7 +3121,7 @@ ensure_driver_environment (SrtSystemInfo *self)
     {
       GPtrArray *builder;
       GRegex *regex;
-      gchar **env_list = get_environ (self);
+      gchar **env_list = self->env;
       /* This is the list of well-known driver-selection environment variables,
        * plus __GLX_FORCE_VENDOR_LIBRARY_%d that will be searched with a regex */
       static const gchar * const drivers_env[] = {"VDPAU_DRIVER",
diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h
index dc5d7c92c..072758074 100644
--- a/steam-runtime-tools/utils-internal.h
+++ b/steam-runtime-tools/utils-internal.h
@@ -100,3 +100,5 @@ gboolean _srt_file_test_in_sysroot (const char *sysroot,
                                     int sysroot_fd,
                                     const char *filename,
                                     GFileTest test);
+
+G_GNUC_INTERNAL const char * const *_srt_peek_environ_nonnull (void);
diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c
index 223a06565..ee69aa63f 100644
--- a/steam-runtime-tools/utils.c
+++ b/steam-runtime-tools/utils.c
@@ -996,3 +996,21 @@ _srt_file_test_in_sysroot (const char *sysroot,
 
   return FALSE;
 }
+
+/*
+ * Return a pointer to the environment block, without copying.
+ * In the unlikely event that `environ == NULL`, return a pointer to
+ * an empty #GStrv.
+ */
+const char * const *
+_srt_peek_environ_nonnull (void)
+{
+  static const char * const no_strings[] = { NULL };
+
+  g_return_val_if_fail (_srt_check_not_setuid (), no_strings);
+
+  if (environ != NULL)
+    return (const char * const *) environ;
+  else
+    return no_strings;
+}
-- 
GitLab