scripts: fix memory leak in hook_info callback

v2.8-utf8proc
Sébastien Helleu 2018-04-13 19:55:20 +02:00
parent cc06b95ba7
commit 9265acf879
19 changed files with 122 additions and 46 deletions

View File

@ -37,6 +37,7 @@ Bug fixes::
* php: fix return code of functions config_write_option and config_write_line
* php: fix memory leak in 72 functions returning allocated strings
* ruby: fix memory leak in 7 functions returning allocated strings
* scripts: fix memory leak in hook_info callback
* scripts: fix return value of hook_infolist callback (pointer instead of string)
* scripts: return long integer instead of string in function infolist_time
* xfer: set option TCP_NODELAY on socket when receiving a file via DCC (issue #1171)

View File

@ -57,6 +57,8 @@
plugin_script_str2ptr (weechat_guile_plugin, \
GUILE_CURRENT_SCRIPT_NAME, \
guile_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&guile_data, __string);
#define API_SCM_TO_STRING(__str) \
weechat_guile_api_scm_to_string(__str, \
guile_strings, &guile_num_strings)
@ -2875,7 +2877,7 @@ weechat_guile_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -2887,10 +2889,12 @@ weechat_guile_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_guile_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_guile_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -1247,12 +1247,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
guile_quiet = 1;
plugin_script_end (plugin, &guile_data);
if (guile_script_eval)
{
weechat_guile_unload (guile_script_eval);
guile_script_eval = NULL;
}
plugin_script_end (plugin, &guile_data);
guile_quiet = 0;
/* unprotect module */

View File

@ -95,7 +95,8 @@ extern "C"
plugin_script_str2ptr (weechat_js_plugin, \
JS_CURRENT_SCRIPT_NAME, \
js_function_name.c_str(), __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&js_data, __string);
#define API_RETURN_OK return v8::True();
#define API_RETURN_ERROR return v8::False();
#define API_RETURN_EMPTY \
@ -2779,7 +2780,7 @@ weechat_js_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -2791,10 +2792,12 @@ weechat_js_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_js_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_js_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -963,12 +963,12 @@ EXPORT int
weechat_plugin_end (struct t_weechat_plugin *plugin)
{
js_quiet = 1;
plugin_script_end (plugin, &js_data);
if (js_script_eval)
{
weechat_js_unload (js_script_eval);
js_script_eval = NULL;
}
plugin_script_end (plugin, &js_data);
js_quiet = 0;
/* free some data */

View File

@ -67,6 +67,8 @@
plugin_script_str2ptr (weechat_lua_plugin, \
LUA_CURRENT_SCRIPT_NAME, \
lua_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&lua_data, __string);
#define API_RETURN_OK \
lua_pushinteger (L, 1); \
return 1
@ -2994,7 +2996,7 @@ weechat_lua_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -3006,10 +3008,12 @@ weechat_lua_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_lua_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_lua_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -1281,12 +1281,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
lua_quiet = 1;
plugin_script_end (plugin, &lua_data);
if (lua_script_eval)
{
weechat_lua_unload (lua_script_eval);
lua_script_eval = NULL;
}
plugin_script_end (plugin, &lua_data);
lua_quiet = 0;
/* free some data */

View File

@ -60,6 +60,8 @@
plugin_script_str2ptr (weechat_perl_plugin, \
PERL_CURRENT_SCRIPT_NAME, \
perl_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&perl_data, __string);
#define API_RETURN_OK XSRETURN_YES
#define API_RETURN_ERROR XSRETURN_NO
#define API_RETURN_EMPTY XSRETURN_EMPTY
@ -2918,7 +2920,7 @@ weechat_perl_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -2930,10 +2932,12 @@ weechat_perl_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_perl_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_perl_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -1317,12 +1317,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
perl_quiet = 1;
plugin_script_end (plugin, &perl_data);
if (perl_script_eval)
{
weechat_perl_unload (perl_script_eval);
perl_script_eval = NULL;
}
plugin_script_end (plugin, &perl_data);
perl_quiet = 0;
#ifndef MULTIPLICITY

View File

@ -67,6 +67,8 @@
plugin_script_str2ptr (weechat_php_plugin, \
PHP_CURRENT_SCRIPT_NAME, \
php_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&php_data, __string);
#define API_RETURN_OK RETURN_LONG((long)1)
#define API_RETURN_ERROR RETURN_LONG((long)0)
#define API_RETURN_EMPTY RETURN_NULL()
@ -2824,7 +2826,7 @@ weechat_php_api_hook_info_cb (const void *pointer,
weechat_php_cb (pointer, data, func_argv, "sss",
WEECHAT_SCRIPT_EXEC_STRING, &rc);
return rc;
return API_STATIC_STRING(rc);
}
API_FUNC(hook_info)

View File

@ -1319,12 +1319,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
php_quiet = 1;
plugin_script_end (plugin, &php_data);
if (php_script_eval)
{
weechat_php_unload (php_script_eval);
php_script_eval = NULL;
}
plugin_script_end (plugin, &php_data);
php_quiet = 0;
if (weechat_php_func_map)

View File

@ -171,6 +171,13 @@ plugin_script_init (struct t_weechat_plugin *weechat_plugin,
char *action_signals[] = { "install", "remove", "autoload", NULL };
int i, auto_load_scripts;
/* initialize static strings */
plugin_data->index_static_string = 0;
for (i = 0; i < WEECHAT_SCRIPT_STATIC_STRINGS; i++)
{
plugin_data->static_string[i] = NULL;
}
/* initialize script configuration file (file: "<language>.conf") */
plugin_script_config_init (weechat_plugin, plugin_data);
@ -387,6 +394,29 @@ invalid:
return NULL;
}
/*
* Gets a "static string": a string allocated that will be freed later
* (or when the plugin is unloaded).
*
* The "string" argument must have been allocated by free (or strdup, ...)
* and will be automatically freed later.
*/
char *
plugin_script_get_static_string (struct t_plugin_script_data *plugin_data,
char *string)
{
plugin_data->index_static_string = (plugin_data->index_static_string + 1) %
WEECHAT_SCRIPT_STATIC_STRINGS;
if (plugin_data->static_string[plugin_data->index_static_string])
free (plugin_data->static_string[plugin_data->index_static_string]);
plugin_data->static_string[plugin_data->index_static_string] = string;
return plugin_data->static_string[plugin_data->index_static_string];
}
/*
* Builds concatenated function name and data (both are strings).
* The result will be sent to callbacks.
@ -1742,7 +1772,7 @@ void
plugin_script_end (struct t_weechat_plugin *weechat_plugin,
struct t_plugin_script_data *plugin_data)
{
int scripts_loaded;
int scripts_loaded, i;
/* unload all scripts */
scripts_loaded = (*(plugin_data->scripts)) ? 1 : 0;
@ -1756,6 +1786,16 @@ plugin_script_end (struct t_weechat_plugin *weechat_plugin,
/* write config file (file: "<language>.conf") */
weechat_config_write (*(plugin_data->config_file));
weechat_config_free (*(plugin_data->config_file));
/* free static strings */
for (i = 0; i < WEECHAT_SCRIPT_STATIC_STRINGS; i++)
{
if (plugin_data->static_string[i])
{
free (plugin_data->static_string[i]);
plugin_data->static_string[i] = NULL;
}
}
}
/*

View File

@ -33,6 +33,8 @@ enum t_weechat_script_exec_type
#define WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE 16
#define WEECHAT_SCRIPT_STATIC_STRINGS 32
#define WEECHAT_SCRIPT_EVAL_NAME "__eval__"
#define WEECHAT_SCRIPT_MSG_NOT_INIT(__current_script, \
@ -78,6 +80,8 @@ struct t_plugin_script_data
struct t_config_option **config_look_eval_keep_context;
struct t_plugin_script **scripts;
struct t_plugin_script **last_script;
char *static_string[WEECHAT_SCRIPT_STATIC_STRINGS];
int index_static_string;
/* callbacks */
int (*callback_command) (const void *pointer, void *data,
@ -125,6 +129,8 @@ extern void *plugin_script_str2ptr (struct t_weechat_plugin *weechat_plugin,
const char *script_name,
const char *function_name,
const char *pointer_str);
extern char *plugin_script_get_static_string (struct t_plugin_script_data *plugin_data,
char *string);
extern char *plugin_script_build_function_and_data (const char *function,
const char *data);
extern void plugin_script_get_function_and_data (void *callback_data,

View File

@ -59,6 +59,8 @@
plugin_script_str2ptr (weechat_python_plugin, \
PYTHON_CURRENT_SCRIPT_NAME, \
python_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&python_data, __string);
#define API_RETURN_OK return PyLong_FromLong((long)1)
#define API_RETURN_ERROR return PyLong_FromLong ((long)0)
#define API_RETURN_EMPTY \
@ -2948,7 +2950,7 @@ weechat_python_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -2960,10 +2962,12 @@ weechat_python_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_python_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_python_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -1609,12 +1609,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
python_quiet = 1;
plugin_script_end (plugin, &python_data);
if (python_script_eval)
{
weechat_python_unload (python_script_eval);
python_script_eval = NULL;
}
plugin_script_end (plugin, &python_data);
python_quiet = 0;
/* free python interpreter */

View File

@ -57,6 +57,8 @@
plugin_script_str2ptr (weechat_ruby_plugin, \
RUBY_CURRENT_SCRIPT_NAME, \
ruby_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&ruby_data, __string);
#define API_RETURN_OK return INT2FIX (1)
#define API_RETURN_ERROR return INT2FIX (0)
#define API_RETURN_EMPTY return Qnil
@ -3513,7 +3515,7 @@ weechat_ruby_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -3525,10 +3527,12 @@ weechat_ruby_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_ruby_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_ruby_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -1425,12 +1425,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
ruby_quiet = 1;
plugin_script_end (plugin, &ruby_data);
if (ruby_script_eval)
{
weechat_ruby_unload (ruby_script_eval);
ruby_script_eval = NULL;
}
plugin_script_end (plugin, &ruby_data);
ruby_quiet = 0;
ruby_cleanup (0);

View File

@ -68,6 +68,8 @@
plugin_script_str2ptr (weechat_tcl_plugin, \
TCL_CURRENT_SCRIPT_NAME, \
tcl_function_name, __string)
#define API_STATIC_STRING(__string) \
plugin_script_get_static_string(&tcl_data, __string);
#define API_RETURN_OK \
{ \
objp = Tcl_GetObjResult (interp); \
@ -3209,7 +3211,7 @@ weechat_tcl_api_hook_info_cb (const void *pointer, void *data,
{
struct t_plugin_script *script;
void *func_argv[3];
char empty_arg[1] = { '\0' };
char empty_arg[1] = { '\0' }, *result;
const char *ptr_function, *ptr_data;
script = (struct t_plugin_script *)pointer;
@ -3221,10 +3223,12 @@ weechat_tcl_api_hook_info_cb (const void *pointer, void *data,
func_argv[1] = (info_name) ? (char *)info_name : empty_arg;
func_argv[2] = (arguments) ? (char *)arguments : empty_arg;
return (const char *)weechat_tcl_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
result = (char *)weechat_tcl_exec (script,
WEECHAT_SCRIPT_EXEC_STRING,
ptr_function,
"sss", func_argv);
return API_STATIC_STRING(result);
}
return NULL;

View File

@ -970,12 +970,12 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* unload all scripts */
tcl_quiet = 1;
plugin_script_end (plugin, &tcl_data);
if (tcl_script_eval)
{
weechat_tcl_unload (tcl_script_eval);
tcl_script_eval = NULL;
}
plugin_script_end (plugin, &tcl_data);
tcl_quiet = 0;
/* free some data */