This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository libx2goclient.
commit e1100f6544bda45fb0ab19525d53694f060dfb99 Author: Mihai Moldovan <io...@ionic.de> Date: Thu Jul 30 09:59:20 2020 +0200 src/x2goclient-network-ssh.c: rename x2goclient_network_ssh_ptrarray_print () to x2goclient_network_ssh_gptrarray_to_string () and fully rework it. Instead of having it print out the result directly via g_log (and not having any control of the actual printing), make it return a boolean value indicating errors and a string as an output parameter. This way, callers can handle the string however they want. Additionally, pre-calculate the size of the resulting string (checking for size-based wrapping along the way) and copy data in chunks instead of using the old Shlemiel-The-Painter algorithm. --- src/x2goclient-network-ssh.c | 160 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 19 deletions(-) diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c index feab49c..f43a894 100644 --- a/src/x2goclient-network-ssh.c +++ b/src/x2goclient-network-ssh.c @@ -134,7 +134,7 @@ static gboolean x2goclient_network_ssh_kill_subprocesses (X2GoClientNetworkSSH * static gboolean x2goclient_network_ssh_parent_connect (X2GoClientNetwork *parent, GError **gerr); static gboolean x2goclient_network_ssh_fetch_openssh_version (X2GoClientNetworkSSH *self, GError **gerr); static void x2goclient_network_ssh_log_std_str (const gchar * const str, const gsize str_size, const _Bool select_stderr); -static void x2goclient_network_ssh_ptrarray_print (GPtrArray * const arr, const gchar * const prelude); +static gboolean x2goclient_network_ssh_gptrarray_to_string (GPtrArray * const arr, const gchar * const prelude, gchar ** const ret_str); static void x2goclient_network_ssh_class_init (X2GoClientNetworkSSHClass *klass) { @@ -951,7 +951,21 @@ static gboolean x2goclient_network_ssh_parent_connect (X2GoClientNetwork *parent } if (ret) { - x2goclient_network_ssh_gptrarray_print (ssh_cmd, "Would try to connect via:"); + gchar *ssh_cmd_str = NULL; + if (x2goclient_network_ssh_gptrarray_to_string (ssh_cmd, "Would try to connect via:", &ssh_cmd_str)) { + if (ssh_cmd_str) { + g_log (NULL, G_LOG_LEVEL_DEBUG, "%s", ssh_cmd_str); + + g_free (ssh_cmd_str); + ssh_cmd_str = NULL; + } + else { + g_log (NULL, G_LOG_LEVEL_DEBUG, "Unable to print out OpenSSH client command, it was completely empty."); + } + } + else { + g_log (NULL, G_LOG_LEVEL_DEBUG, "Unable to print out OpenSSH client command, internal error (the string likely was too big)."); + } g_log (NULL, G_LOG_LEVEL_DEBUG, "Launching!"); GError *ssh_err = NULL; @@ -1101,36 +1115,144 @@ static void x2goclient_network_ssh_log_std_str (const gchar * const str, const g } } -static void x2goclient_network_ssh_gptrarray_print (GPtrArray * const arr, const gchar * const prelude) { - g_return_if_fail (arr); +static gboolean x2goclient_network_ssh_gptrarray_to_string (GPtrArray * const arr, const gchar * const prelude, gchar ** const ret_str) { +#define SIZE_LOW_WRAP(buffer_size, elem_size) ((G_MAXSIZE - (buffer_size)) < ((elem_size))) + gboolean ret = FALSE; + + g_return_val_if_fail (((arr) && (ret_str)), ret); + + *(ret_str) = NULL; - /* - * Yeah, this is potentially slow, but there is no better way to use - * g_log (). - */ gchar *tmp = NULL; const gchar *empty = "(NULL)"; + const gsize empty_size = strlen (empty); + + /* Account for terminating NULL. */ + gsize size = 1; + + /* + * First, calculate the total size. + * + * Calculating the size and printing will take two iterations, but that's + * still better than a lot of reallocations and data moves. + */ + ret = TRUE; if (prelude) { - tmp = g_strdup (prelude); + const gsize elem_size = strlen (prelude); + + if (SIZE_LOW_WRAP (size, elem_size)) { + ret = FALSE; + } + else { + size += elem_size; + } } + for (gsize i = 0; ((i < arr->len) && (ret)); ++i) { + const gchar *cur_entry = g_ptr_array_index (arr, i); + + gsize additional_chars = 0; + /* Account for the potential additional chars " []". */ + if ((0 == i) && (!(prelude))) { + /* No space character necessary if we don't have a prelude. */ + additional_chars = 2; + } + else { + additional_chars = 3; + } + + if (SIZE_LOW_WRAP (size, additional_chars)) { + ret = FALSE; + continue; + } - for (gsize i = 0; i < arr->len; ++i) { - gchar *tmp_new = NULL; - gchar *cur_entry = (gchar *)g_ptr_array_index (arr, i); + size += additional_chars; + gsize elem_size = 0; if (cur_entry) { - tmp_new = g_strdup_printf ("%s [%s]", tmp, cur_entry); + elem_size = strlen (cur_entry); } else { - tmp_new = g_strdup_printf ("%s [%s]", tmp, empty); + elem_size = empty_size; } - g_free (tmp); + if (SIZE_LOW_WRAP (size, elem_size)) { + ret = FALSE; + continue; + } + + size += elem_size; + } + + if (ret) { + /* Now allocate enough space. */ + *(ret_str) = tmp = g_new0 (gchar, size); + + gsize tmp_size = size, + written_size = 0; + + /* + * *(ret_str) could be NULL now, but that can only happen if both the + * prelude and array are empty. + * + * That's fine, since in that case everything will be skipped. + */ + if ((prelude) && (tmp)) { + written_size = g_strlcpy (tmp, prelude, tmp_size); + + if (written_size >= tmp_size) { + /* Truncation. */ + ret = FALSE; + } + else { + tmp += written_size; + tmp_size -= written_size; + } + } + +#define HANDLE_TRUNC() \ + do { \ + if (written_size >= tmp_size) { \ + /* Truncation. */ \ + ret = FALSE; \ + continue; \ + } \ + else { \ + tmp += written_size; \ + tmp_size -= written_size; \ + } \ + } while (0) + + for (gsize i = 0; ((i < arr->len) && (ret)); ++i) { + const gchar *cur_entry = g_ptr_array_index (arr, i); + + if ((0 != i) || (prelude)) { + written_size = g_strlcpy (tmp, " ", tmp_size); + HANDLE_TRUNC (); + } + + written_size = g_strlcpy (tmp, "[", tmp_size); + HANDLE_TRUNC (); + + if (cur_entry) { + written_size = g_strlcpy (tmp, cur_entry, tmp_size); + } + else { + written_size = g_strlcpy (tmp, empty, tmp_size); + } + HANDLE_TRUNC (); - tmp = tmp_new; + written_size = g_strlcpy (tmp, "]", tmp_size); + HANDLE_TRUNC (); + } } - g_log (NULL, G_LOG_LEVEL_DEBUG, "%s", tmp); - g_free (tmp); - tmp = NULL; + if (!(ret)) { + /* Clean up, we errored. */ + g_free (*(ret_str)); + *(ret_str) = tmp = NULL; + } + + return (ret); +#undef HANDLE_TRUNC +#undef SIZE_LOW_WRAP } -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git _______________________________________________ x2go-commits mailing list x2go-commits@lists.x2go.org https://lists.x2go.org/listinfo/x2go-commits