From 46619573e0f9ec8e85d5a1882dfe171a5edfb0ac Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Sat, 24 Feb 2024 21:35:04 +0100
Subject: [PATCH 1/2] egl: Make sure GError gets set when we return FALSE

The convention is that when a function returns FALSE or NULL, the error
will be set. In this file we call set_egl_error but it might not set an
error. Code of the form

if (egl_do_thing (..., &error))
 use_error (error);

will crash in those cases.

This commit makes sure we always set the error even if EGL doesn't give
us an error.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3614>
---
 src/backends/meta-egl.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
index ac19828c4cd..fefba7c6767 100644
--- a/src/backends/meta-egl.c
+++ b/src/backends/meta-egl.c
@@ -158,7 +158,10 @@ set_egl_error (GError **error)
 
   error_number = eglGetError ();
   if (error_number == EGL_SUCCESS)
-    return;
+    {
+      g_warning ("Expected an EGL error but eglGetError returned EGL_SUCCESS");
+      error_number = -1;
+    }
 
   error_str = get_egl_error_str (error_number);
   g_set_error_literal (error, META_EGL_ERROR,
-- 
GitLab


From 8234f5bc7ebbe1bc861248bc06bee1a5a54daed9 Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Sat, 24 Feb 2024 21:56:13 +0100
Subject: [PATCH 2/2] egl: Return success status from
 meta_egl_query_device_string

QueryDeviceString can successfully return NULL. The convention however
is that when NULL is returned, the error will be set.

This commit makes the returned string an output parameter which allows
us to return the success status and have the error set accordingly.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3614>
---
 src/backends/meta-egl.c                       | 58 ++++++++++++++-----
 src/backends/meta-egl.h                       |  9 +--
 .../native/meta-render-device-egl-stream.c    | 20 +++----
 src/wayland/meta-wayland-dma-buf.c            | 15 +++--
 4 files changed, 66 insertions(+), 36 deletions(-)

diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
index fefba7c6767..9a57c52dec4 100644
--- a/src/backends/meta-egl.c
+++ b/src/backends/meta-egl.c
@@ -169,6 +169,25 @@ set_egl_error (GError **error)
                        error_str);
 }
 
+static void
+check_egl_error (GError **error)
+{
+  EGLint error_number;
+  const char *error_str;
+
+  if (!error)
+    return;
+
+  error_number = eglGetError ();
+  if (error_number == EGL_SUCCESS)
+    return;
+
+  error_str = get_egl_error_str (error_number);
+  g_set_error_literal (error, META_EGL_ERROR,
+                       error_number,
+                       error_str);
+}
+
 gboolean
 meta_extensions_string_has_extensions_valist (const char   *extensions_str,
                                               const char ***missing_extensions,
@@ -781,25 +800,32 @@ meta_egl_query_devices (MetaEgl      *egl,
   return TRUE;
 }
 
-const char *
-meta_egl_query_device_string (MetaEgl     *egl,
-                              EGLDeviceEXT device,
-                              EGLint       name,
-                              GError     **error)
+gboolean
+meta_egl_query_device_string (MetaEgl       *egl,
+                              EGLDeviceEXT   device,
+                              EGLint         name,
+                              const char   **out_string,
+                              GError       **error)
 {
+  g_autoptr (GError) local_error = NULL;
   const char *device_string;
 
   if (!is_egl_proc_valid (egl->eglQueryDeviceStringEXT, error))
-    return NULL;
+    return FALSE;
 
   device_string = egl->eglQueryDeviceStringEXT (device, name);
   if (!device_string)
     {
-      set_egl_error (error);
-      return NULL;
+      check_egl_error (&local_error);
+      if (local_error)
+        {
+          g_propagate_error (error, local_error);
+          return FALSE;
+        }
     }
 
-  return device_string;
+  *out_string = device_string;
+  return TRUE;
 }
 
 gboolean
@@ -812,14 +838,18 @@ meta_egl_egl_device_has_extensions (MetaEgl        *egl,
   va_list var_args;
   const char *extensions_str;
   gboolean has_extensions;
-  GError *error = NULL;
+  g_autoptr (GError) error = NULL;
 
-  extensions_str = meta_egl_query_device_string (egl, device, EGL_EXTENSIONS,
-                                                 &error);
-  if (!extensions_str)
+  if (!meta_egl_query_device_string (egl, device, EGL_EXTENSIONS,
+                                     &extensions_str, &error))
     {
       g_warning ("Failed to query device string: %s", error->message);
-      g_error_free (error);
+      return FALSE;
+    }
+
+  if (!extensions_str)
+    {
+      g_warning ("EGL_EXTENSIONS device string returned NULL");
       return FALSE;
     }
 
diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h
index 4ed54a53997..09bee954ad9 100644
--- a/src/backends/meta-egl.h
+++ b/src/backends/meta-egl.h
@@ -173,10 +173,11 @@ gboolean meta_egl_query_devices (MetaEgl      *egl,
                                  EGLint       *num_devices,
                                  GError      **error);
 
-const char * meta_egl_query_device_string (MetaEgl     *egl,
-                                           EGLDeviceEXT device,
-                                           EGLint       name,
-                                           GError     **error);
+gboolean meta_egl_query_device_string (MetaEgl       *egl,
+                                       EGLDeviceEXT   device,
+                                       EGLint         name,
+                                       const char   **out_string,
+                                       GError       **error);
 
 gboolean meta_egl_egl_device_has_extensions (MetaEgl        *egl,
                                              EGLDeviceEXT    device,
diff --git a/src/backends/native/meta-render-device-egl-stream.c b/src/backends/native/meta-render-device-egl-stream.c
index d3eb29d56a2..6a4be9e9d09 100644
--- a/src/backends/native/meta-render-device-egl-stream.c
+++ b/src/backends/native/meta-render-device-egl-stream.c
@@ -64,10 +64,11 @@ get_egl_device_display (MetaRenderDevice  *render_device,
                                         error);
 }
 
-static const char *
-get_drm_device_file (MetaEgl     *egl,
-                     EGLDeviceEXT device,
-                     GError     **error)
+static gboolean
+get_drm_device_file (MetaEgl       *egl,
+                     EGLDeviceEXT   device,
+                     const char   **out_device_file_path,
+                     GError       **error)
 {
   if (!meta_egl_egl_device_has_extensions (egl, device,
                                            NULL,
@@ -77,12 +78,11 @@ get_drm_device_file (MetaEgl     *egl,
       g_set_error (error, G_IO_ERROR,
                    G_IO_ERROR_FAILED,
                    "Missing required EGLDevice extension EGL_EXT_device_drm");
-      return NULL;
+      return FALSE;
     }
 
-  return meta_egl_query_device_string (egl, device,
-                                       EGL_DRM_DEVICE_FILE_EXT,
-                                       error);
+  return meta_egl_query_device_string (egl, device, EGL_DRM_DEVICE_FILE_EXT,
+                                       out_device_file_path, error);
 }
 
 static EGLDeviceEXT
@@ -133,8 +133,8 @@ find_egl_device (MetaRenderDevice  *render_device,
 
       g_clear_error (error);
 
-      egl_device_drm_path = get_drm_device_file (egl, devices[i], error);
-      if (!egl_device_drm_path)
+      if (!get_drm_device_file (egl, devices[i], &egl_device_drm_path, error) ||
+          !egl_device_drm_path)
         continue;
 
       if (g_str_equal (egl_device_drm_path, device_file_path))
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 7085bec3137..221df3dc0a6 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1821,10 +1821,9 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor  *compositor,
                                           "EGL_EXT_device_drm_render_node",
                                           NULL))
     {
-      device_path = meta_egl_query_device_string (egl, egl_device,
-                                                  EGL_DRM_RENDER_NODE_FILE_EXT,
-                                                  &local_error);
-      if (local_error)
+      if (!meta_egl_query_device_string (egl, egl_device,
+                                         EGL_DRM_RENDER_NODE_FILE_EXT,
+                                         &device_path, &local_error))
         {
           g_warning ("Failed to query EGL render node path: %s",
                      local_error->message);
@@ -1837,13 +1836,13 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor  *compositor,
                                           "EGL_EXT_device_drm",
                                           NULL))
     {
-      device_path = meta_egl_query_device_string (egl, egl_device,
-                                                  EGL_DRM_DEVICE_FILE_EXT,
-                                                  &local_error);
-      if (local_error)
+      if (!meta_egl_query_device_string (egl, egl_device,
+                                         EGL_DRM_DEVICE_FILE_EXT,
+                                         &device_path, &local_error))
         {
           g_warning ("Failed to query EGL render node path: %s",
                      local_error->message);
+          g_clear_error (&local_error);
         }
     }
 
-- 
GitLab

