From: Michal Privoznik <mpriv...@redhat.com>

There's a problem with glib: what we might consider functions are
in fact macros and to make things worse - they do declare local
variables. For instance here's the declaration of
g_clear_pointer() macro:

#define g_clear_pointer(pp, destroy)                     \
  G_STMT_START                                           \
  {                                                      \
    G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
    glib_typeof ((pp)) _pp = (pp);                       \
    glib_typeof (*(pp)) _ptr = *_pp;                     \
    *_pp = NULL;                                         \
    if (_ptr)                                            \
      (destroy) (_ptr);                                  \
  }                                                      \
  G_STMT_END                                             \

Now, as of v6.2.0-rc1~267 our VIR_FREE() macro is in fact a
redeclaration of g_clear_pointer(). Thus, calling VIR_FREE()
increases stack size!

Ideally, this wouldn't be a problem, because those variables
(_pp, _ptr) live in their own block. And clever compiler can just
reuse space created for one block.

But then there's clang where we are hitting this exact problem in
functions like doRemoteOpen() where either g_clear_pointer() is
called directly, or there are macros like EXTRACT_URI_ARG_STR()
which hide the call away.

That's why despite our previous efforts decreasing stack size we
still needed v9.8.0-rc1~208.

Well, moving URI argument extraction (those calls to
EXTRACT_URI_ARG_* macros) into a separate function helps us
decrease stack size from 2296 bytes to 1320.

Even after this there are still more possibilities for
improvements, but those will be addressed in future commits.

Signed-off-by: Michal Privoznik <mpriv...@redhat.com>
---
 src/remote/remote_driver.c | 113 +++++++++++++++++++++++++++----------
 1 file changed, 82 insertions(+), 31 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 745cd34f83..681594e406 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -758,13 +758,74 @@ remoteConnectFormatURI(virURI *uri,
             virReportError(VIR_ERR_INVALID_ARG, \
                            _("Failed to parse value of URI component %1$s"), \
                            var->name); \
-            goto error; \
+            return -1; \
         } \
         ARG_VAR = tmp == 0; \
         var->ignore = 1; \
         continue; \
     }
 
+static int
+doRemoteOpenExtractURIArgs(virConnectPtr conn,
+                           char **name,
+                           char **command,
+                           char **sockname,
+                           char **authtype,
+                           char **sshauth,
+                           char **netcat,
+                           char **keyfile,
+                           char **pkipath,
+                           char **knownHosts,
+                           char **knownHostsVerify,
+                           char **tls_priority,
+                           char **mode_str,
+                           char **proxy_str,
+#ifndef WIN32
+                           bool *tty,
+#endif
+                           bool *sanity,
+                           bool *verify)
+{
+    size_t i;
+
+    for (i = 0; i < conn->uri->paramsCount; i++) {
+        virURIParam *var = &conn->uri->params[i];
+
+        EXTRACT_URI_ARG_STR("name", *name);
+        EXTRACT_URI_ARG_STR("command", *command);
+        EXTRACT_URI_ARG_STR("socket", *sockname);
+        EXTRACT_URI_ARG_STR("auth", *authtype);
+        EXTRACT_URI_ARG_STR("sshauth", *sshauth);
+        EXTRACT_URI_ARG_STR("netcat", *netcat);
+        EXTRACT_URI_ARG_STR("keyfile", *keyfile);
+        EXTRACT_URI_ARG_STR("pkipath", *pkipath);
+        EXTRACT_URI_ARG_STR("known_hosts", *knownHosts);
+        EXTRACT_URI_ARG_STR("known_hosts_verify", *knownHostsVerify);
+        EXTRACT_URI_ARG_STR("tls_priority", *tls_priority);
+        EXTRACT_URI_ARG_STR("mode", *mode_str);
+        EXTRACT_URI_ARG_STR("proxy", *proxy_str);
+        EXTRACT_URI_ARG_BOOL("no_sanity", *sanity);
+        EXTRACT_URI_ARG_BOOL("no_verify", *verify);
+#ifndef WIN32
+        EXTRACT_URI_ARG_BOOL("no_tty", *tty);
+#endif
+
+        if (STRCASEEQ(var->name, "authfile")) {
+            /* Strip this param, used by virauth.c */
+            var->ignore = 1;
+            continue;
+        }
+
+        VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
+                  var->name, var->value);
+    }
+
+    return 0;
+}
+
+#undef EXTRACT_URI_ARG_STR
+#undef EXTRACT_URI_ARG_BOOL
+
 
 /*
  * URIs that this driver needs to handle:
@@ -818,7 +879,6 @@ doRemoteOpen(virConnectPtr conn,
     bool tty = true;
 #endif
     int mode;
-    size_t i;
     int proxy;
 
     /* We handle *ALL* URIs here. The caller has rejected any
@@ -844,35 +904,28 @@ doRemoteOpen(virConnectPtr conn,
      * although that won't be the case for now).
      */
     if (conn->uri) {
-        for (i = 0; i < conn->uri->paramsCount; i++) {
-            virURIParam *var = &conn->uri->params[i];
-            EXTRACT_URI_ARG_STR("name", name);
-            EXTRACT_URI_ARG_STR("command", command);
-            EXTRACT_URI_ARG_STR("socket", sockname);
-            EXTRACT_URI_ARG_STR("auth", authtype);
-            EXTRACT_URI_ARG_STR("sshauth", sshauth);
-            EXTRACT_URI_ARG_STR("netcat", netcat);
-            EXTRACT_URI_ARG_STR("keyfile", keyfile);
-            EXTRACT_URI_ARG_STR("pkipath", pkipath);
-            EXTRACT_URI_ARG_STR("known_hosts", knownHosts);
-            EXTRACT_URI_ARG_STR("known_hosts_verify", knownHostsVerify);
-            EXTRACT_URI_ARG_STR("tls_priority", tls_priority);
-            EXTRACT_URI_ARG_STR("mode", mode_str);
-            EXTRACT_URI_ARG_STR("proxy", proxy_str);
-            EXTRACT_URI_ARG_BOOL("no_sanity", sanity);
-            EXTRACT_URI_ARG_BOOL("no_verify", verify);
+        /* This really needs to be a separate function to keep
+         * the stack size at sane levels. */
+        if (doRemoteOpenExtractURIArgs(conn,
+                                       &name,
+                                       &command,
+                                       &sockname,
+                                       &authtype,
+                                       &sshauth,
+                                       &netcat,
+                                       &keyfile,
+                                       &pkipath,
+                                       &knownHosts,
+                                       &knownHostsVerify,
+                                       &tls_priority,
+                                       &mode_str,
+                                       &proxy_str,
 #ifndef WIN32
-            EXTRACT_URI_ARG_BOOL("no_tty", tty);
+                                       &tty,
 #endif
-
-            if (STRCASEEQ(var->name, "authfile")) {
-                /* Strip this param, used by virauth.c */
-                var->ignore = 1;
-                continue;
-            }
-
-            VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
-                       var->name, var->value);
+                                       &sanity,
+                                       &verify) < 0) {
+            goto error;
         }
 
         /* Construct the original name. */
@@ -1248,8 +1301,6 @@ doRemoteOpen(virConnectPtr conn,
     VIR_FREE(priv->hostname);
     return VIR_DRV_OPEN_ERROR;
 }
-#undef EXTRACT_URI_ARG_STR
-#undef EXTRACT_URI_ARG_BOOL
 
 static struct private_data *
 remoteAllocPrivateData(void)
-- 
2.49.0

Reply via email to