summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2015-07-16 16:12:35 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2015-07-16 16:19:55 +0100
commite259b2f30d86fdde7dab27a25e8088d36421acc7 (patch)
tree7c3499bb6a4f9ecf237fe64cdc9f53efacc67c78
parent3b41daca780e9e83d04dcad43e2fbd5a2ab8c120 (diff)
downloadgtk+-e259b2f30d86fdde7dab27a25e8088d36421acc7.tar.gz
Avoid O(n²) walking of string arrays
"Yo, we heard you like traversing NULL-terminated arrays to operate on them, so we called g_strv_length() as the for condition, so you can iterate the array while iterating the array." Instead of making famed rapper and television producer Xzibit proud, we should avoid calling g_strv_length() on an array while looping on the array, to avoid quadratic complexity. We do this in various places that deal with arrays of strings that we cannot really guess are short enough not to matter — e.g. the list of CSS selectors in the inspector, or the required authentication information for printing.
-rw-r--r--gtk/gtkprintbackend.c25
-rw-r--r--gtk/inspector/selector.c5
-rw-r--r--modules/printbackends/cups/gtkcupssecretsutils.c5
-rw-r--r--testsuite/a11y/state/state-record.c7
4 files changed, 24 insertions, 18 deletions
diff --git a/gtk/gtkprintbackend.c b/gtk/gtkprintbackend.c
index cda9376007..8ec6dbc99b 100644
--- a/gtk/gtkprintbackend.c
+++ b/gtk/gtkprintbackend.c
@@ -706,24 +706,27 @@ password_dialog_response (GtkWidget *dialog,
GtkPrintBackend *backend)
{
GtkPrintBackendPrivate *priv = backend->priv;
- gint i;
+ gint i, auth_info_len;
if (response_id == GTK_RESPONSE_OK)
gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
else
gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
- for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
- if (priv->auth_info[i] != NULL)
- {
- memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
- g_free (priv->auth_info[i]);
- priv->auth_info[i] = NULL;
- }
- g_free (priv->auth_info);
- priv->auth_info = NULL;
+ /* We want to clear the data before freeing it */
+ auth_info_len = g_strv_length (priv->auth_info_required);
+ for (i = 0; i < auth_info_len; i++)
+ {
+ if (priv->auth_info[i] != NULL)
+ {
+ memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
+ g_free (priv->auth_info[i]);
+ priv->auth_info[i] = NULL;
+ }
+ }
- g_strfreev (priv->auth_info_required);
+ g_clear_pointer (&priv->auth_info, g_free);
+ g_clear_pointer (&priv->auth_info_required, g_strfreev);
gtk_widget_destroy (dialog);
diff --git a/gtk/inspector/selector.c b/gtk/inspector/selector.c
index e19f74ca9c..c820d3b70a 100644
--- a/gtk/inspector/selector.c
+++ b/gtk/inspector/selector.c
@@ -64,7 +64,7 @@ gtk_inspector_selector_set_object (GtkInspectorSelector *oh,
GObject *object)
{
GtkTreeIter iter, parent;
- gint i;
+ gint i, words_len;
GtkWidget *widget;
gchar *path, **words;
const gchar *title;
@@ -85,7 +85,8 @@ gtk_inspector_selector_set_object (GtkInspectorSelector *oh,
path = gtk_widget_path_to_string (gtk_widget_get_path (widget));
words = g_strsplit (path, " ", 0);
- for (i = 0; i < g_strv_length (words); i++)
+ words_len = g_strv_length (words);
+ for (i = 0; i < words_len; i++)
{
gtk_tree_store_append (oh->priv->model, &iter, i ? &parent : NULL);
gtk_tree_store_set (oh->priv->model, &iter,
diff --git a/modules/printbackends/cups/gtkcupssecretsutils.c b/modules/printbackends/cups/gtkcupssecretsutils.c
index d5df4a7326..925f7d561c 100644
--- a/modules/printbackends/cups/gtkcupssecretsutils.c
+++ b/modules/printbackends/cups/gtkcupssecretsutils.c
@@ -109,7 +109,7 @@ get_secret_cb (GObject *source_object,
*key = NULL,
*value = NULL;
GVariantIter *iter = NULL;
- guint i;
+ guint i, required_len;
gint pw_field = -1;
task = user_data;
@@ -228,7 +228,8 @@ get_secret_cb (GObject *source_object,
fail:
/* Error out */
GTK_NOTE (PRINTING, g_print ("Failed to lookup secret.\n"));
- for (i = 0; i < g_strv_length (task_data->auth_info_required); i++)
+ required_len = g_strv_length (task_data->auth_info_required);
+ for (i = 0; i < required_len; i++)
{
/* Not all fields of auth_info are neccessarily written so we can not
use strfreev here */
diff --git a/testsuite/a11y/state/state-record.c b/testsuite/a11y/state/state-record.c
index cf9313b1b0..dd37c6233c 100644
--- a/testsuite/a11y/state/state-record.c
+++ b/testsuite/a11y/state/state-record.c
@@ -142,7 +142,7 @@ record_events (const gchar *ui_file,
GError *error;
gchar *contents;
gchar **actions;
- gint i;
+ gint i, len;
builder = gtk_builder_new ();
error = NULL;
@@ -152,8 +152,9 @@ record_events (const gchar *ui_file,
g_file_get_contents (in_file, &contents, NULL, &error);
g_assert_no_error (error);
actions = g_strsplit (contents, "\n", 0);
-
- for (i = 0; i < g_strv_length (actions); i++)
+
+ len = g_strv_length (actions);
+ for (i = 0; i < len; i++)
do_action (builder, actions[i], string);
g_object_unref (builder);