For string values returned from telemetry, escape any values that cannot normally appear in a json string. According to the json spec[1], the characters than need to be handled are control chars (char value < 0x20) and '"' and '\' characters.
To handle this, we replace the snprintf call with a separate string copying and encapsulation routine which checks each character as it copies it to the final array. [1] https://www.rfc-editor.org/rfc/rfc8259.txt Signed-off-by: Bruce Richardson <bruce.richard...@intel.com> --- lib/telemetry/telemetry_json.h | 48 +++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/telemetry/telemetry_json.h b/lib/telemetry/telemetry_json.h index db70690274..13df5d07e3 100644 --- a/lib/telemetry/telemetry_json.h +++ b/lib/telemetry/telemetry_json.h @@ -44,6 +44,52 @@ __json_snprintf(char *buf, const int len, const char *format, ...) return 0; /* nothing written or modified */ } +static const char control_chars[0x20] = { + ['\n'] = 'n', + ['\r'] = 'r', + ['\t'] = 't', +}; + +/** + * @internal + * Does the same as __json_snprintf(buf, len, "\"%s\"", str) + * except that it does proper escaping as necessary. + * Drops any invalid characters we don't support + */ +static inline int +__json_format_str(char *buf, const int len, const char *str) +{ + char tmp[len]; + int tmpidx = 0; + + tmp[tmpidx++] = '"'; + while (*str != '\0') { + if (*str < (int)RTE_DIM(control_chars)) { + int idx = *str; /* compilers don't like char type as index */ + if (control_chars[idx] != 0) { + tmp[tmpidx++] = '\\'; + tmp[tmpidx++] = control_chars[idx]; + } + } else if (*str == '"' || *str == '\\') { + tmp[tmpidx++] = '\\'; + tmp[tmpidx++] = *str; + } else + tmp[tmpidx++] = *str; + /* we always need space for closing quote and null character. + * Ensuring at least two free characters also means we can always take an + * escaped character like "\n" without overflowing + */ + if (tmpidx > len - 2) + return 0; + str++; + } + tmp[tmpidx++] = '"'; + tmp[tmpidx] = '\0'; + + strcpy(buf, tmp); + return tmpidx; +} + /* Copies an empty array into the provided buffer. */ static inline int rte_tel_json_empty_array(char *buf, const int len, const int used) @@ -62,7 +108,7 @@ rte_tel_json_empty_obj(char *buf, const int len, const int used) static inline int rte_tel_json_str(char *buf, const int len, const int used, const char *str) { - return used + __json_snprintf(buf + used, len - used, "\"%s\"", str); + return used + __json_format_str(buf + used, len - used, str); } /* Appends a string into the JSON array in the provided buffer. */ -- 2.34.1