Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.d/bugfix/ZBX-178371
-rw-r--r--src/libs/zbxembed/httprequest.c74
-rw-r--r--src/libs/zbxembed/zabbix.c19
-rw-r--r--src/zabbix_js/zabbix_js.c3
4 files changed, 70 insertions, 27 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-17837 b/ChangeLog.d/bugfix/ZBX-17837
new file mode 100644
index 00000000000..02c41f114b4
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-17837
@@ -0,0 +1 @@
+.......PS. [ZBX-17837] fixed memory leaks when handling CurlHttpRequest errors (Andris, wiper)
diff --git a/src/libs/zbxembed/httprequest.c b/src/libs/zbxembed/httprequest.c
index 1ee15ef7a58..972cce623b4 100644
--- a/src/libs/zbxembed/httprequest.c
+++ b/src/libs/zbxembed/httprequest.c
@@ -38,11 +38,16 @@ typedef struct
}
zbx_es_httprequest_t;
+/* ZBX_CURL_SETOPT() macro is a code snippet to make code shorter and facilitate resource deallocation */
+/* in case of error. Be careful with using ZBX_CURL_SETOPT(), duk_push_error_object() and duk_error() */
+/* in functions - it is easy to get memory leaks because duk_error() causes longjmp(). */
+/* Note that the caller of ZBX_CURL_SETOPT() must define variable 'int err_index' and label 'out'. */
#define ZBX_CURL_SETOPT(ctx, handle, opt, value, err) \
if (CURLE_OK != (err = curl_easy_setopt(handle, opt, value))) \
{ \
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot set cURL option " #opt ": %s.", \
- curl_easy_strerror(err)); \
+ err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, \
+ "cannot set cURL option " #opt ": %s.", curl_easy_strerror(err)); \
+ goto out; \
}
static size_t curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
@@ -115,13 +120,16 @@ static duk_ret_t es_httprequest_ctor(duk_context *ctx)
zbx_es_httprequest_t *request;
CURLcode err;
zbx_es_env_t *env;
+ int err_index = -1;
if (!duk_is_constructor_call(ctx))
return DUK_RET_TYPE_ERROR;
duk_push_global_stash(ctx);
+
if (1 != duk_get_prop_string(ctx, -1, "\xff""\xff""zbx_env"))
return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot access internal environment");
+
env = (zbx_es_env_t *)duk_to_pointer(ctx, -1);
duk_pop(ctx);
@@ -131,7 +139,10 @@ static duk_ret_t es_httprequest_ctor(duk_context *ctx)
memset(request, 0, sizeof(zbx_es_httprequest_t));
if (NULL == (request->handle = curl_easy_init()))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot initialize cURL library");
+ {
+ err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "cannot initialize cURL library");
+ goto out;
+ }
ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_COOKIEFILE, "", err);
ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_FOLLOWLOCATION, 1L, err);
@@ -147,6 +158,17 @@ static duk_ret_t es_httprequest_ctor(duk_context *ctx)
duk_push_c_function(ctx, es_httprequest_dtor, 1);
duk_set_finalizer(ctx, -2);
+out:
+ if (-1 != err_index)
+ {
+ if (NULL != request)
+ {
+ if (NULL != request->handle)
+ curl_easy_cleanup(request->handle);
+ zbx_free(request);
+ }
+ return duk_throw(ctx);
+ }
return 0;
}
@@ -163,18 +185,26 @@ static duk_ret_t es_httprequest_add_header(duk_context *ctx)
zbx_es_httprequest_t *request;
CURLcode err;
char *utf8 = NULL;
+ int err_index = -1;
if (NULL == (request = es_httprequest(ctx)))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "internal scripting error: null object");
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
if (SUCCEED != zbx_cesu8_to_utf8(duk_to_string(ctx, 0), &utf8))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot convert header to utf8");
+ {
+ err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR, "cannot convert header to utf8");
+ goto out;
+ }
request->headers = curl_slist_append(request->headers, utf8);
ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_HTTPHEADER, request->headers, err);
request->custom_header = 1;
+out:
zbx_free(utf8);
+ if (-1 != err_index)
+ return duk_throw(ctx);
+
return 0;
}
@@ -190,7 +220,7 @@ static duk_ret_t es_httprequest_clear_header(duk_context *ctx)
zbx_es_httprequest_t *request;
if (NULL == (request = es_httprequest(ctx)))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "internal scripting error: null object");
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
curl_slist_free_all(request->headers);
request->headers = NULL;
@@ -214,11 +244,11 @@ static duk_ret_t es_httprequest_query(duk_context *ctx, const char *http_request
zbx_es_httprequest_t *request;
char *url = NULL, *contents = NULL;
CURLcode err;
- duk_ret_t ret;
+ int err_index = -1;
if (SUCCEED != zbx_cesu8_to_utf8(duk_to_string(ctx, 0), &url))
{
- ret = duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot convert URL to utf8");
+ err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR, "cannot convert URL to utf8");
goto out;
}
@@ -226,14 +256,15 @@ static duk_ret_t es_httprequest_query(duk_context *ctx, const char *http_request
{
if (SUCCEED != zbx_cesu8_to_utf8(duk_to_string(ctx, 1), &contents))
{
- ret = duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot convert request contents to utf8");
+ err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR,
+ "cannot convert request contents to utf8");
goto out;
}
}
if (NULL == (request = es_httprequest(ctx)))
{
- ret = duk_error(ctx, DUK_RET_TYPE_ERROR, "internal scripting error: null object");
+ err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
goto out;
}
@@ -266,17 +297,20 @@ static duk_ret_t es_httprequest_query(duk_context *ctx, const char *http_request
if (CURLE_OK != (err = curl_easy_perform(request->handle)))
{
- ret = duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot get URL: %s.", curl_easy_strerror(err));
+ err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "cannot get URL: %s.",
+ curl_easy_strerror(err));
goto out;
}
duk_push_string(ctx, request->data);
- ret = 1;
out:
zbx_free(url);
zbx_free(contents);
- return ret;
+ if (-1 != err_index)
+ return duk_throw(ctx);
+
+ return 1;
}
/******************************************************************************
@@ -338,11 +372,15 @@ static duk_ret_t es_httprequest_set_proxy(duk_context *ctx)
{
zbx_es_httprequest_t *request;
CURLcode err;
+ int err_index = -1;
if (NULL == (request = es_httprequest(ctx)))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "internal scripting error: null object");
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_PROXY, duk_to_string(ctx, 0), err);
+out:
+ if (-1 != err_index)
+ return duk_throw(ctx);
return 1;
}
@@ -361,10 +399,10 @@ static duk_ret_t es_httprequest_status(duk_context *ctx)
CURLcode err;
if (NULL == (request = es_httprequest(ctx)))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "internal scripting error: null object");
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
if (CURLE_OK != (err = curl_easy_getinfo(request->handle, CURLINFO_RESPONSE_CODE, &response_code)))
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot obtain request status: %s", curl_easy_strerror(err));
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "cannot obtain request status: %s", curl_easy_strerror(err));
duk_push_number(ctx, (duk_double_t)response_code);
@@ -388,9 +426,9 @@ static const duk_function_list_entry httprequest_methods[] = {
static duk_ret_t es_httprequest_ctor(duk_context *ctx)
{
if (!duk_is_constructor_call(ctx))
- return DUK_RET_TYPE_ERROR;
+ return DUK_RET_EVAL_ERROR;
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "missing cURL library");
+ return duk_error(ctx, DUK_RET_EVAL_ERROR, "missing cURL library");
}
static const duk_function_list_entry httprequest_methods[] = {
diff --git a/src/libs/zbxembed/zabbix.c b/src/libs/zbxembed/zabbix.c
index ee487552df6..7b7bc8d1094 100644
--- a/src/libs/zbxembed/zabbix.c
+++ b/src/libs/zbxembed/zabbix.c
@@ -70,7 +70,7 @@ static duk_ret_t es_zabbix_log(duk_context *ctx)
{
zbx_es_env_t *env;
char *message = NULL;
- int level;
+ int level, err_index = -1;
duk_memory_functions out_funcs;
level = duk_to_int(ctx, 0);
@@ -87,9 +87,13 @@ static duk_ret_t es_zabbix_log(duk_context *ctx)
env = (zbx_es_env_t *)out_funcs.udata;
if (NULL == env->json)
+ goto out;
+
+ if (ZBX_ES_LOG_MEMORY_LIMIT < env->json->buffer_size) /* approximate limit */
{
- zbx_free(message);
- return 0;
+ err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "log exceeds the maximum size of "
+ ZBX_FS_UI64 " bytes.", ZBX_ES_LOG_MEMORY_LIMIT);
+ goto out;
}
zbx_json_addobject(env->json, NULL);
@@ -97,14 +101,11 @@ static duk_ret_t es_zabbix_log(duk_context *ctx)
zbx_json_adduint64(env->json, "ms", zbx_get_duration_ms(&env->start_time));
zbx_json_addstring(env->json, "message", message, ZBX_JSON_TYPE_STRING);
zbx_json_close(env->json);
-
+out:
zbx_free(message);
- if (ZBX_ES_LOG_MEMORY_LIMIT < env->json->buffer_size) /* approximate limit */
- {
- return duk_error(ctx, DUK_RET_TYPE_ERROR, "log exceeds the maximum size of " ZBX_FS_UI64 " bytes.",
- ZBX_ES_LOG_MEMORY_LIMIT);
- }
+ if (-1 != err_index)
+ return duk_throw(ctx);
return 0;
}
diff --git a/src/zabbix_js/zabbix_js.c b/src/zabbix_js/zabbix_js.c
index 03904f5c414..2bffcd13150 100644
--- a/src/zabbix_js/zabbix_js.c
+++ b/src/zabbix_js/zabbix_js.c
@@ -151,6 +151,7 @@ static char *execute_script(const char *script, const char *param, int timeout,
if (FAIL == zbx_es_init_env(&es, &errmsg))
{
*error = zbx_dsprintf(NULL, "cannot initialize scripting environment: %s", errmsg);
+ zbx_free(errmsg);
return NULL;
}
@@ -160,12 +161,14 @@ static char *execute_script(const char *script, const char *param, int timeout,
if (FAIL == zbx_es_compile(&es, script, &code, &size, &errmsg))
{
*error = zbx_dsprintf(NULL, "cannot compile script: %s", errmsg);
+ zbx_free(errmsg);
goto out;
}
if (FAIL == zbx_es_execute(&es, script, code, size, param, &result, &errmsg))
{
*error = zbx_dsprintf(NULL, "cannot execute script: %s", errmsg);
+ zbx_free(errmsg);
goto out;
}
out: