> From: Chengwen Feng [mailto:fengcheng...@huawei.com] > Sent: Friday, 17 June 2022 11.46 > > This patch supports escape special characters (including: \",\\,/,\b, > /f,/n,/r,/t) when telemetry string. > This patch is used to support telemetry xxx-dump commands which the > string may include special characters. > > Signed-off-by: Chengwen Feng <fengcheng...@huawei.com> > --- > lib/telemetry/telemetry.c | 96 +++++++++++++++++++++++++++++++++++++-- > 1 file changed, 93 insertions(+), 3 deletions(-) > > diff --git a/lib/telemetry/telemetry.c b/lib/telemetry/telemetry.c > index c6fd03a5ab..0f762f633e 100644 > --- a/lib/telemetry/telemetry.c > +++ b/lib/telemetry/telemetry.c > @@ -215,6 +215,94 @@ container_to_json(const struct rte_tel_data *d, > char *out_buf, size_t buf_len) > return used; > } > > +static bool > +json_is_special_char(char ch) > +{ > + static unsigned char is_spec[256] = { 0 }; > + static bool init_once; > + > + if (!init_once) { > + is_spec['\"'] = 1; > + is_spec['\\'] = 1; > + is_spec['/'] = 1; > + is_spec['\b'] = 1; > + is_spec['\f'] = 1; > + is_spec['\n'] = 1; > + is_spec['\r'] = 1; > + is_spec['\t'] = 1; > + init_once = true; > + } > + > + return (bool)is_spec[(unsigned char)ch]; > +}
Here's a suggestion for simplifying the code: Remove json_is_special_char(), and update json_escape_special_char() and json_format_string() as follows: > + > +static size_t > +json_escape_special_char(char *buf, const char ch) Consider making this function inline. > +{ > + size_t used = 0; > + > + switch (ch) { > + case '\"': > + buf[used++] = '\\'; > + buf[used++] = '\"'; > + break; > + case '\\': > + buf[used++] = '\\'; > + buf[used++] = '\\'; > + break; > + case '/': > + buf[used++] = '\\'; > + buf[used++] = '/'; > + break; > + case '\b': > + buf[used++] = '\\'; > + buf[used++] = 'b'; > + break; > + case '\f': > + buf[used++] = '\\'; > + buf[used++] = 'f'; > + break; > + case '\n': > + buf[used++] = '\\'; > + buf[used++] = 'n'; > + break; > + case '\r': > + buf[used++] = '\\'; > + buf[used++] = 'r'; > + break; > + case '\t': > + buf[used++] = '\\'; > + buf[used++] = 't'; > + break; > + default: Handle non-escaped characters in the default case here instead: + buf[used++] = ch; > + break; > + } > + > + return used; > +} > + > +static size_t > +json_format_string(char *buf, size_t len, const char *str) > +{ > + size_t used = 0; > + > + while (*str) { > + if (unlikely(len < used + 2)) { > + TMTY_LOG(WARNING, "Insufficient buffer when json > format string\n"); > + break; > + } > + -- replace: > + if (json_is_special_char(*str)) > + used += json_escape_special_char(buf + used, *str); > + else > + buf[used++] = *str; > + > + str++; -- by: + used += json_escape_special_char(buf + used, *str++); -- End of suggestion. Feel free to use it or not. :-) > + } > + > + return used; > +} > + > static void > output_json(const char *cmd, const struct rte_tel_data *d, int s) > { > @@ -232,9 +320,11 @@ output_json(const char *cmd, const struct > rte_tel_data *d, int s) > MAX_CMD_LEN, cmd ? cmd : "none"); > break; > case RTE_TEL_STRING: > - used = snprintf(out_buf, sizeof(out_buf), > "{\"%.*s\":\"%.*s\"}", > - MAX_CMD_LEN, cmd, > - RTE_TEL_MAX_SINGLE_STRING_LEN, d->data.str); > + used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":\"", > + MAX_CMD_LEN, cmd); > + used += json_format_string(out_buf + used, > + sizeof(out_buf) - used - 3, d->data.str); > + used += snprintf(out_buf + used, sizeof(out_buf) - used, > "\"}"); I looked for missing 0-termination in json_format_string(), but that is not required due to the immediately following snprintf(). > break; > case RTE_TEL_DICT: > prefix_used = snprintf(out_buf, sizeof(out_buf), > "{\"%.*s\":", > -- > 2.33.0 > If you want to make it generic, these four cases in output_json() also need to JSON encode the strings: case RTE_TEL_DICT: case RTE_TEL_STRING_VAL: ... case RTE_TEL_CONTAINER: ... (strings only) case RTE_TEL_ARRAY_STRING: if (d->type == RTE_TEL_ARRAY_STRING) ... else if (d->type == RTE_TEL_ARRAY_CONTAINER) ... (strings only) However, JSON encoding of strings inside arrays and containers is not required for the dump purposes addressed by this patch series, so I consider this patch complete without it. No need to add "feature creep" to this series. Reviewed-by: Morten Brørup <m...@smartsharesystems.com>