From: Florian Forster Date: Tue, 13 Sep 2016 08:44:46 +0000 (+0200) Subject: curl_json plugin: Skip unexpected non-map values. X-Git-Tag: collectd-5.6.1~1^2~5 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=ba52f94929822b1968f05cfbb37985af2e0b83a4;p=collectd.git curl_json plugin: Skip unexpected non-map values. Assume, for example, the config `Key "*/foo"`. This config expects JSON in the form: { "bar": { "foo": 1337 } } If the available JSON is instead: { "error_code": 0, "bar": { "foo": 1337 } } the code will take a look at the zero associated with "error_code" and determine that a map (with key "foo") is expected instead. Previously the code would continue, eventually calling `cj_get_type()` which expects that `key->type` is a valid pointer, resulting in a segmentation fault. This patch does three things to ensure that this segmentation fault does not happen again: 1. `cj_get_type()` checks its argument to make sure it is valid before dereferencing any pointers. 2. In case a non-map is found when a map is expected, the code will return instead of limping on. 3. After calling `cj_cb_inc_array_index()`, which may update the key, make sure that it actually did and that key is valid now. Fixes: #1896 --- diff --git a/src/curl_json.c b/src/curl_json.c index 4188f378..a547ddcd 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -143,6 +143,9 @@ static int cj_get_type (cj_key_t *key) { const data_set_t *ds; + if ((key == NULL) || !CJ_IS_KEY (key)) + return -EINVAL; + ds = plugin_get_ds (key->type); if (ds == NULL) { @@ -226,12 +229,15 @@ static int cj_cb_number (void *ctx, buffer[sizeof (buffer) - 1] = 0; if ((key == NULL) || !CJ_IS_KEY (key)) { - if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/) + if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/) { NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects" " a map.", buffer); + return (CJ_CB_CONTINUE); + } + cj_cb_inc_array_index (ctx, /* update_key = */ 1); key = db->state[db->depth].key; - if (key == NULL) { + if ((key == NULL) || !CJ_IS_KEY (key)) { return (CJ_CB_CONTINUE); } }