summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYatian XU <yatian.xu@nokia-sbell.com>2019-09-04 22:43:34 +0800
committerYatian XU <yatian.xu@nokia-sbell.com>2019-09-05 06:51:02 +0800
commit998c19266ef5f74fffd79e9c0c0a65f77ff19a43 (patch)
tree8e011aa227cc5b7a798c13bac6d193c54dff49b9
parentad8ef0f0485a8e7490d84511159c274db123c5a3 (diff)
Fix buffer overflow bug in evel_json_encode_event/evel_json_encode_batch_event.
Issue-ID: VNFSDK-463 Signed-off-by: Yatian XU <yatian.xu@nokia-sbell.com> Change-Id: I6263ace34d9dab5e058490d9d011e1535902e41d
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h6
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c8
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h39
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c269
4 files changed, 230 insertions, 92 deletions
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h
index 9de3868..8cbbeb6 100644
--- a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h
@@ -3063,7 +3063,11 @@ void evel_free_event(void * event);
* @param mode Event mode or Batch mode
* @param max_size Size of storage available in json_body.
* @param event Pointer to the ::EVENT_HEADER to encode.
- * @returns Number of bytes actually written.
+ * @returns The number of characters that would have been written if max_size
+ had been sufficiently large, not counting the terminating null
+ character. Notice that only when this returned value is less than
+ max_size, the string has been completely written(similar to snprintf).
+ Otherwise, need to enlarge the buffer size to returned value +1.
*****************************************************************************/
int evel_json_encode_event(char * json,
int max_size,
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c
index 7200e06..62d38d4 100644
--- a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c
@@ -784,10 +784,8 @@ int evel_json_encode_event(char * json,
/* Sanity check. */
/***************************************************************************/
assert(jbuf->depth == 0);
- if( jbuf->offset >= max_size ){
- EVEL_ERROR("Event exceeded size limit %d", max_size);
- assert(0);
- }
+
+ evel_json_buffer_cleanup(jbuf);
EVEL_EXIT();
@@ -852,6 +850,8 @@ int evel_json_encode_batch_event(char * json,
evel_json_close_object(jbuf);
}
+ evel_json_buffer_cleanup(jbuf);
+
}
/***************************************************************************/
/* Sanity check. */
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h
index 29ba6cd..fc6456c 100644
--- a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h
@@ -164,6 +164,11 @@ typedef struct evel_throttle_spec {
/*****************************************************************************/
#define EVEL_THROTTLE_FIELD_DEPTH 3
+/*****************************************************************************/
+/* EVEL_JSON_BUFFER json buffer grow bytes.
+/*****************************************************************************/
+#define EVEL_JSON_BUFFER_GROW_BYTES 512
+
/**************************************************************************//**
* Initialize the event handler.
*
@@ -274,6 +279,7 @@ typedef struct evel_json_buffer
char * json;
int offset;
int max_size;
+ bool extend;
/***************************************************************************/
/* The working throttle specification, which can be NULL. */
@@ -463,6 +469,39 @@ void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
EVEL_THROTTLE_SPEC * throttle_spec);
/**************************************************************************//**
+ * Cleanup a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ *****************************************************************************/
+void evel_json_buffer_cleanup(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param ... Variable parameters for format string.
+ *****************************************************************************/
+void evel_json_printf(EVEL_JSON_BUFFER * jbuf, const char* const format, ...);
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param largs Variable parameters for format string.
+ *****************************************************************************/
+void evel_json_vprintf(EVEL_JSON_BUFFER * jbuf, const char* const format, va_list largs);
+
+/**************************************************************************//**
+ * Extend the json buffer to size of max_size.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param max_size The max json buffer size.
+ *****************************************************************************/
+void evel_json_extend(EVEL_JSON_BUFFER * jbuf, int max_size);
+
+/**************************************************************************//**
* Encode a string key and string value to a ::EVEL_JSON_BUFFER.
*
* @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c
index a7ad019..7218953 100644
--- a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c
@@ -52,6 +52,7 @@ void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
jbuf->json = json;
jbuf->max_size = max_size;
jbuf->offset = 0;
+ jbuf->extend = false;
jbuf->throttle_spec = throttle_spec;
jbuf->depth = 0;
jbuf->checkpoint = -1;
@@ -60,6 +61,118 @@ void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
}
/**************************************************************************//**
+ * Cleanup a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ *****************************************************************************/
+void evel_json_buffer_cleanup(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ if (jbuf->extend && jbuf->json)
+ {
+ free(jbuf->json);
+ jbuf->extend = false;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param ... Variable parameters for format string.
+ *****************************************************************************/
+void evel_json_printf(EVEL_JSON_BUFFER * jbuf, const char* const format, ...)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ assert(format != NULL);
+
+ va_list largs;
+ va_start(largs, format);
+ evel_json_vprintf(jbuf, format, largs);
+ va_end(largs);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param largs Variable parameters for format string.
+ *****************************************************************************/
+void evel_json_vprintf(EVEL_JSON_BUFFER * jbuf, const char* const format, va_list largs)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ assert(format != NULL);
+
+ va_list largs_dup;
+ va_copy(largs_dup, largs);
+
+ int left = jbuf->max_size - jbuf->offset;
+ int len = vsnprintf(jbuf->json + jbuf->offset, left, format, largs);
+
+ if (len < left)
+ {
+ jbuf->offset += len;
+ }
+ else //buffer is not enough
+ {
+ evel_json_extend(jbuf, jbuf->offset + len + 1 + EVEL_JSON_BUFFER_GROW_BYTES);
+ jbuf->offset += vsnprintf(jbuf->json + jbuf->offset, jbuf->max_size - jbuf->offset, format, largs_dup);
+ }
+
+ va_end(largs_dup);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Extend the json buffer to size of max_size.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param max_size The max json buffer size.
+ *****************************************************************************/
+void evel_json_extend(EVEL_JSON_BUFFER * jbuf, int max_size)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+
+ if (jbuf->max_size < max_size)
+ {
+ if (jbuf->extend) //already extent the buffer
+ {
+ jbuf->json = (char*)realloc(jbuf->json, max_size);
+ assert(jbuf->json != NULL);
+ }
+ else // extent for the first time
+ {
+ char* json = (char*)malloc(max_size);
+ assert(json != NULL);
+ strncpy(json, jbuf->json, jbuf->offset);
+ jbuf->json = json;
+ jbuf->extend = true;
+ }
+
+ jbuf->max_size = max_size;
+ }
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
* Encode an integer value to a JSON buffer.
*
* @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
@@ -75,9 +188,7 @@ void evel_enc_int(EVEL_JSON_BUFFER * jbuf,
/***************************************************************************/
assert(jbuf != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%d", value);
+ evel_json_printf(jbuf, "%d", value);
EVEL_EXIT();
}
@@ -146,11 +257,10 @@ void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": \"",
- evel_json_kv_comma(jbuf),
- key);
+ evel_json_printf(jbuf,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
/***************************************************************************/
/* We need to escape quotation marks and backslashes in the value. */
@@ -159,13 +269,8 @@ void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
for (index = 0; index < length; index++)
{
- /*************************************************************************/
- /* Drop out if no more space. */
- /*************************************************************************/
- if (jbuf->max_size - jbuf->offset < 2)
- {
- break;
- }
+ //make sure there are 3 bytes available(2 for json, 1 for null)
+ evel_json_extend(jbuf, jbuf->offset + 3);
/*************************************************************************/
/* Add an escape character if necessary, then write the character */
@@ -181,9 +286,7 @@ void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
jbuf->offset++;
}
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "\"");
+ evel_json_printf(jbuf, "\"");
EVEL_EXIT();
}
@@ -250,12 +353,11 @@ void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": %d",
- evel_json_kv_comma(jbuf),
- key,
- value);
+ evel_json_printf(jbuf,
+ "%s\"%s\": %d",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
EVEL_EXIT();
}
@@ -279,12 +381,11 @@ void evel_enc_kv_object(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": %s",
- evel_json_kv_comma(jbuf),
- key,
- value);
+ evel_json_printf(jbuf,
+ "%s\"%s\": %s",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
EVEL_EXIT();
}
@@ -350,12 +451,11 @@ void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": %1f",
- evel_json_kv_comma(jbuf),
- key,
- value);
+ evel_json_printf(jbuf,
+ "%s\"%s\": %1f",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
EVEL_EXIT();
}
@@ -421,12 +521,11 @@ void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": %llu",
- evel_json_kv_comma(jbuf),
- key,
- value);
+ evel_json_printf(jbuf,
+ "%s\"%s\": %llu",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
EVEL_EXIT();
}
@@ -493,18 +592,20 @@ void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf,
assert(key != NULL);
assert(time != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": \"",
- evel_json_kv_comma(jbuf),
- key);
- jbuf->offset += strftime(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- EVEL_RFC2822_STRFTIME_FORMAT,
- localtime(time));
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "\"");
+ evel_json_printf(jbuf,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+
+ char time_buf[128] = { 0 };
+ strftime(time_buf,
+ sizeof(time_buf),
+ EVEL_RFC2822_STRFTIME_FORMAT,
+ localtime(time));
+ evel_json_printf(jbuf, time_buf);
+
+ evel_json_printf(jbuf, "\"");
+
EVEL_EXIT();
}
@@ -532,12 +633,11 @@ void evel_enc_version(EVEL_JSON_BUFFER * jbuf,
ver = (float)major_version + (float)minor_version/10.0;
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": \"%.1f\"",
- evel_json_kv_comma(jbuf),
- key,
- ver);
+ evel_json_printf(jbuf,
+ "%s\"%s\": \"%.1f\"",
+ evel_json_kv_comma(jbuf),
+ key,
+ ver);
EVEL_EXIT();
}
@@ -597,11 +697,11 @@ void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": [",
- evel_json_kv_comma(jbuf),
- key);
+ evel_json_printf(jbuf,
+ "%s\"%s\": [",
+ evel_json_kv_comma(jbuf),
+ key);
+
jbuf->depth++;
EVEL_EXIT();
@@ -621,9 +721,8 @@ void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
/***************************************************************************/
assert(jbuf != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "]");
+ evel_json_printf(jbuf, "]");
+
jbuf->depth--;
EVEL_EXIT();
@@ -655,16 +754,13 @@ void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
/***************************************************************************/
if (jbuf->json[jbuf->offset - 1] != '[')
{
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- ", ");
+ evel_json_printf(jbuf, ", ");
}
va_start(largs, format);
- jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- format,
- largs);
+
+ evel_json_vprintf(jbuf, format, largs);
+
va_end(largs);
EVEL_EXIT();
@@ -725,11 +821,11 @@ void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
assert(jbuf != NULL);
assert(key != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s\"%s\": {",
- evel_json_kv_comma(jbuf),
- key);
+ evel_json_printf(jbuf,
+ "%s\"%s\": {",
+ evel_json_kv_comma(jbuf),
+ key);
+
jbuf->depth++;
EVEL_EXIT();
@@ -760,10 +856,10 @@ void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
comma = "";
}
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "%s{",
- comma);
+ evel_json_printf(jbuf,
+ "%s{",
+ comma);
+
jbuf->depth++;
EVEL_EXIT();
@@ -783,9 +879,8 @@ void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
/***************************************************************************/
assert(jbuf != NULL);
- jbuf->offset += snprintf(jbuf->json + jbuf->offset,
- jbuf->max_size - jbuf->offset,
- "}");
+ evel_json_printf(jbuf, "}");
+
jbuf->depth--;
EVEL_EXIT();