diff --git a/ChangeLog.adoc b/ChangeLog.adoc index b3ecd1f0f..eba08353b 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -34,6 +34,7 @@ Bug fixes:: * irc: fix parsing of message 338 (whois, host) sent by Rizon server (issue #1737) * irc: fix display of message 344 received as whois geo info (issue #1736) * irc: fix display of IRC numeric messages with no parameters + * python: fix crash in hook callbacks after script loading failure (issue #1740) * trigger: fix search of triggers with UTF-8 chars in name (issue #1739) * xfer: fix auto-accept of server/nick when the server name contains UTF-8 chars (issue #1739) diff --git a/src/plugins/python/weechat-python-api.c b/src/plugins/python/weechat-python-api.c index 428bb8913..14d4984d4 100644 --- a/src/plugins/python/weechat-python-api.c +++ b/src/plugins/python/weechat-python-api.c @@ -2279,12 +2279,12 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = PyLong_FromLong ((long)fd); + func_argv[1] = &fd; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "sO", func_argv); + "si", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2293,10 +2293,6 @@ weechat_python_api_hook_fd_cb (const void *pointer, void *data, int fd) ret = *rc; free (rc); } - if (func_argv[1]) - { - Py_XDECREF((PyObject *)func_argv[1]); - } return ret; } @@ -2371,14 +2367,14 @@ weechat_python_api_hook_process_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (command) ? (char *)command : empty_arg; - func_argv[2] = PyLong_FromLong ((long)return_code); + func_argv[2] = &return_code; func_argv[3] = (out) ? (char *)out : empty_arg; func_argv[4] = (err) ? (char *)err : empty_arg; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssOss", func_argv); + "ssiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2387,10 +2383,6 @@ weechat_python_api_hook_process_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - { - Py_XDECREF((PyObject *)func_argv[2]); - } return ret; } @@ -2478,16 +2470,16 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = PyLong_FromLong ((long)status); - func_argv[2] = PyLong_FromLong ((long)gnutls_rc); - func_argv[3] = PyLong_FromLong ((long)sock); + func_argv[1] = &status; + func_argv[2] = &gnutls_rc; + func_argv[3] = &sock; func_argv[4] = (ip_address) ? (char *)ip_address : empty_arg; func_argv[5] = (error) ? (char *)error : empty_arg; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "sOOOss", func_argv); + "siiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2496,18 +2488,6 @@ weechat_python_api_hook_connect_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[1]) - { - Py_XDECREF((PyObject *)func_argv[1]); - } - if (func_argv[2]) - { - Py_XDECREF((PyObject *)func_argv[2]); - } - if (func_argv[3]) - { - Py_XDECREF((PyObject *)func_argv[3]); - } return ret; } @@ -2569,17 +2549,12 @@ weechat_python_api_hook_line_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = weechat_python_hashtable_to_dict (line); + func_argv[1] = line; ret_hashtable = weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_HASHTABLE, ptr_function, - "sO", func_argv); - - if (func_argv[1]) - { - Py_XDECREF((PyObject *)func_argv[1]); - } + "sh", func_argv); return ret_hashtable; } @@ -2645,15 +2620,15 @@ weechat_python_api_hook_print_cb (const void *pointer, void *data, func_argv[3] = weechat_string_build_with_split_string (tags, ","); if (!func_argv[3]) func_argv[3] = strdup (""); - func_argv[4] = PyLong_FromLong ((long)displayed); - func_argv[5] = PyLong_FromLong ((long)highlight); + func_argv[4] = &displayed; + func_argv[5] = &highlight; func_argv[6] = (prefix) ? (char *)prefix : empty_arg; func_argv[7] = (message) ? (char *)message : empty_arg; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssssOOss", func_argv); + "ssssiiss", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2664,14 +2639,6 @@ weechat_python_api_hook_print_cb (const void *pointer, void *data, } if (func_argv[3]) free (func_argv[3]); - if (func_argv[4]) - { - Py_XDECREF((PyObject *)func_argv[4]); - } - if (func_argv[5]) - { - Py_XDECREF((PyObject *)func_argv[5]); - } return ret; } @@ -2845,12 +2812,12 @@ weechat_python_api_hook_hsignal_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (signal) ? (char *)signal : empty_arg; - func_argv[2] = weechat_python_hashtable_to_dict (hashtable); + func_argv[2] = hashtable; rc = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, ptr_function, - "ssO", func_argv); + "ssh", func_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2859,10 +2826,6 @@ weechat_python_api_hook_hsignal_cb (const void *pointer, void *data, ret = *rc; free (rc); } - if (func_argv[2]) - { - Py_XDECREF((PyObject *)func_argv[2]); - } return ret; } @@ -3120,17 +3083,12 @@ weechat_python_api_hook_info_hashtable_cb (const void *pointer, void *data, { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; func_argv[1] = (info_name) ? (char *)info_name : empty_arg; - func_argv[2] = weechat_python_hashtable_to_dict (hashtable); + func_argv[2] = hashtable; ret_hashtable = weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_HASHTABLE, ptr_function, - "ssO", func_argv); - - if (func_argv[2]) - { - Py_XDECREF((PyObject *)func_argv[2]); - } + "ssh", func_argv); return ret_hashtable; } @@ -3249,16 +3207,12 @@ weechat_python_api_hook_focus_cb (const void *pointer, void *data, if (ptr_function && ptr_function[0]) { func_argv[0] = (ptr_data) ? (char *)ptr_data : empty_arg; - func_argv[1] = weechat_python_hashtable_to_dict (info); + func_argv[1] = info; ret_hashtable = weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_HASHTABLE, ptr_function, - "sO", func_argv); - if (func_argv[1]) - { - Py_XDECREF((PyObject *)func_argv[1]); - } + "sh", func_argv); return ret_hashtable; } @@ -4060,17 +4014,12 @@ weechat_python_api_bar_item_build_cb (const void *pointer, void *data, func_argv[1] = (char *)API_PTR2STR(item); func_argv[2] = (char *)API_PTR2STR(window); func_argv[3] = (char *)API_PTR2STR(buffer); - func_argv[4] = weechat_python_hashtable_to_dict (extra_info); + func_argv[4] = extra_info; ret = (char *)weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_STRING, ptr_function + 7, - "ssssO", func_argv); - - if (func_argv[4]) - { - Py_XDECREF((PyObject *)func_argv[4]); - } + "ssssh", func_argv); } else { diff --git a/src/plugins/python/weechat-python.c b/src/plugins/python/weechat-python.c index d6d501e43..0a4cca493 100644 --- a/src/plugins/python/weechat-python.c +++ b/src/plugins/python/weechat-python.c @@ -480,6 +480,7 @@ weechat_python_exec (struct t_plugin_script *script, old_python_current_script = python_current_script; python_current_script = script; old_interpreter = NULL; + if (script->interpreter) { old_interpreter = PyThreadState_Swap (NULL); @@ -487,6 +488,12 @@ weechat_python_exec (struct t_plugin_script *script, } evMain = PyImport_AddModule ((char *) "__main__"); + /* + * FIXME: sometimes NULL is returned with nested calls of hook callbacks, + * to prevent any crash, we just skip execution of the function + */ + if (!evMain) + goto end; evDict = PyModule_GetDict (evMain); evFunc = PyDict_GetItemString (evDict, function); @@ -506,26 +513,38 @@ weechat_python_exec (struct t_plugin_script *script, { if (i < argc) { - argv2[i] = argv[i]; - if (format[i] == 's') + switch (format[i]) { + case 's': /* string */ + argv2[i] = argv[i]; #if PY_MAJOR_VERSION >= 3 - if (weechat_utf8_is_valid (argv2[i], -1, NULL)) - format2[i] = 's'; /* Python 3: str */ - else - format2[i] = 'y'; /* Python 3: bytes */ + if (weechat_utf8_is_valid (argv2[i], -1, NULL)) + format2[i] = 's'; /* Python 3: str */ + else + format2[i] = 'y'; /* Python 3: bytes */ #else - format2[i] = 's'; /* Python 2: str */ + format2[i] = 's'; /* Python 2: str */ #endif - } - else - { - format2[i] = format[i]; + break; + case 'i': /* integer */ + argv2[i] = PyLong_FromLong ((long)(*((int *)argv[i]))); + format2[i] = 'O'; + break; + case 'h': /* hash */ + argv2[i] = weechat_python_hashtable_to_dict ( + (struct t_hashtable *)argv[i]); + format2[i] = 'O'; + break; + case 'O': /* object */ + argv2[i] = argv[i]; + format2[i] = 'O'; + break; } } else { argv2[i] = NULL; + format2[i] = '\0'; } } format2[argc] = '\0'; @@ -539,6 +558,12 @@ weechat_python_exec (struct t_plugin_script *script, argv2[10], argv2[11], argv2[12], argv2[13], argv2[14], argv2[15]); + + for (i = 0; i < argc; i++) + { + if (argv2[i] && (format2[i] == 'O')) + Py_XDECREF((PyObject *)argv2[i]); + } } else {