File weechat-fix-hook_process-shell-injection.patch of Package weechat.openSUSE_12.1_Update

Index: weechat-0.3.6/src/core/wee-hook.c
===================================================================
--- weechat-0.3.6.orig/src/core/wee-hook.c
+++ weechat-0.3.6/src/core/wee-hook.c
@@ -1370,7 +1370,8 @@ hook_process (struct t_weechat_plugin *p
 void
 hook_process_child (struct t_hook *hook_process)
 {
-    char *exec_args[4] = { "sh", "-c", NULL, NULL };
+    char **exec_args;
+    int i;
     
     /*
      * close stdin, so that process will fail to read stdin (process reading
@@ -1393,10 +1394,25 @@ hook_process_child (struct t_hook *hook_
     }
     
     /* launch command */
-    exec_args[2] = HOOK_PROCESS(hook_process, command);
-    execvp (exec_args[0], exec_args);
+    exec_args = string_split_shell (HOOK_PROCESS(hook_process, command));
+    if (exec_args)
+    {
+        if (weechat_debug_core >= 1)
+        {
+            log_printf ("hook_process, command='%s'",
+                        HOOK_PROCESS(hook_process, command));
+            for (i = 0; exec_args[i]; i++)
+            {
+                log_printf ("  args[%02d] == '%s'", i, exec_args[i]);
+            }
+        }
+        execvp (exec_args[0], exec_args);
+    }
     
     /* should not be executed if execvp was ok */
+    if (exec_args)
+        string_free_split (exec_args);
+
     fprintf (stderr, "Error with command '%s'\n",
              HOOK_PROCESS(hook_process, command));
     _exit (EXIT_FAILURE);
Index: weechat-0.3.6/src/core/wee-string.c
===================================================================
--- weechat-0.3.6.orig/src/core/wee-string.c
+++ weechat-0.3.6/src/core/wee-string.c
@@ -971,6 +971,196 @@ string_split (const char *string, const
 }
 
 /*
+ * string_split_shell: split a string like the shell does for a command with
+ *                     arguments.
+ *                     Note: result must be freed with string_free_split.
+ *                     This function is a C conversion of python class "shlex"
+ *                     (file: Lib/shlex.py in python repository)
+ *                     Doc: http://docs.python.org/3/library/shlex.html
+ *                     Copyrights in shlex.py:
+ *                       Module and documentation by Eric S. Raymond, 21 Dec 1998
+ *                       Input stacking and error message cleanup added by ESR, March 2000
+ *                       push_source() and pop_source() made explicit by ESR, January 2001.
+ *                       Posix compliance, split(), string arguments, and
+ *                       iterator interface by Gustavo Niemeyer, April 2003.
+ */
+
+char **
+string_split_shell (const char *string)
+{
+    int temp_len, num_args, add_char_to_temp, add_temp_to_args, quoted;
+    char *string2, *temp, **args, **args2, state, escapedstate;
+    char *ptr_string, *ptr_next, saved_char;
+
+    if (!string)
+        return NULL;
+
+    string2 = strdup (string);
+    if (!string2)
+        return NULL;
+
+    /*
+     * prepare "args" with one pointer to NULL, the "args" will be reallocated
+     * later, each time a new argument is added
+     */
+    num_args = 0;
+    args = malloc ((num_args + 1) * sizeof (args[0]));
+    if (!args)
+    {
+        free (string2);
+        return NULL;
+    }
+    args[0] = NULL;
+
+    /* prepare a temp string for working (adding chars one by one) */
+    temp = malloc ((2 * strlen (string)) + 1);
+    if (!temp)
+    {
+        free (string2);
+        free (args);
+        return NULL;
+    }
+    temp[0] = '\0';
+    temp_len = 0;
+
+    state = ' ';
+    escapedstate = ' ';
+    quoted = 0;
+    ptr_string = string2;
+    while (ptr_string[0])
+    {
+        add_char_to_temp = 0;
+        add_temp_to_args = 0;
+        ptr_next = utf8_next_char (ptr_string);
+        saved_char = ptr_next[0];
+        ptr_next[0] = '\0';
+        if (state == ' ')
+        {
+            if ((ptr_string[0] == ' ') || (ptr_string[0] == '\t')
+                || (ptr_string[0] == '\r') || (ptr_string[0] == '\n'))
+            {
+                if (temp[0] || quoted)
+                    add_temp_to_args = 1;
+            }
+            else if (ptr_string[0] == '\\')
+            {
+                escapedstate = 'a';
+                state = ptr_string[0];
+            }
+            else if ((ptr_string[0] == '\'') || (ptr_string[0] == '"'))
+            {
+                state = ptr_string[0];
+            }
+            else
+            {
+                add_char_to_temp = 1;
+                state = 'a';
+            }
+        }
+        else if ((state == '\'') || (state == '"'))
+        {
+            quoted = 1;
+            if (ptr_string[0] == state)
+            {
+                state = 'a';
+            }
+            else if ((state == '"') && (ptr_string[0] == '\\'))
+            {
+                escapedstate = state;
+                state = ptr_string[0];
+            }
+            else
+            {
+                add_char_to_temp = 1;
+            }
+        }
+        else if (state == '\\')
+        {
+            if (((escapedstate == '\'') || (escapedstate == '"'))
+                && (ptr_string[0] != state) && (ptr_string[0] != escapedstate))
+            {
+                temp[temp_len] = state;
+                temp_len++;
+                temp[temp_len] = '\0';
+            }
+            add_char_to_temp = 1;
+            state = escapedstate;
+        }
+        else if (state == 'a')
+        {
+            if ((ptr_string[0] == ' ') || (ptr_string[0] == '\t')
+                || (ptr_string[0] == '\r') || (ptr_string[0] == '\n'))
+            {
+                state = ' ';
+                if (temp[0] || quoted)
+                    add_temp_to_args = 1;
+            }
+            else if (ptr_string[0] == '\\')
+            {
+                escapedstate = 'a';
+                state = ptr_string[0];
+            }
+            else if ((ptr_string[0] == '\'') || (ptr_string[0] == '"'))
+            {
+                state = ptr_string[0];
+            }
+            else
+            {
+                add_char_to_temp = 1;
+            }
+        }
+        if (add_char_to_temp)
+        {
+            memcpy (temp + temp_len, ptr_string, ptr_next - ptr_string);
+            temp_len += (ptr_next - ptr_string);
+            temp[temp_len] = '\0';
+        }
+        if (add_temp_to_args)
+        {
+            num_args++;
+            args2 = realloc (args, (num_args + 1) * sizeof (args[0]));
+            if (!args2)
+            {
+                free (string2);
+                free (temp);
+                return args;
+            }
+            args = args2;
+            args[num_args - 1] = strdup (temp);
+            args[num_args] = NULL;
+            temp[0] = '\0';
+            temp_len = 0;
+            escapedstate = ' ';
+            quoted = 0;
+        }
+        ptr_next[0] = saved_char;
+        ptr_string = ptr_next;
+    }
+
+    if (temp[0] || (state != ' '))
+    {
+        num_args++;
+        args2 = realloc (args, (num_args + 1) * sizeof (args[0]));
+        if (!args2)
+        {
+            free (string2);
+            free (temp);
+            return args;
+        }
+        args = args2;
+        args[num_args - 1] = strdup (temp);
+        args[num_args] = NULL;
+        temp[0] = '\0';
+        temp_len = 0;
+    }
+
+    free (string2);
+    free (temp);
+
+    return args;
+}
+
+/*
  * string_free_split: free a split string
  */
 
Index: weechat-0.3.6/src/core/wee-string.h
===================================================================
--- weechat-0.3.6.orig/src/core/wee-string.h
+++ weechat-0.3.6/src/core/wee-string.h
@@ -52,6 +52,7 @@ extern int string_has_highlight_regex (c
 extern char *string_mask_to_regex (const char *mask);
 extern char **string_split (const char *string, const char *separators,
                             int keep_eol, int num_items_max, int *num_items);
+extern char **string_split_shell (const char *string);
 extern void string_free_split (char **split_string);
 extern char *string_build_with_split_string (const char **split_string,
                                              const char *separator);
openSUSE Build Service is sponsored by