Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf list: JSON escape encoding improvements

Use strbuf to make the string under construction's length unlimited. Use
the format %s to mean a literal string copy and %S to signify a need to
escape the string. Add supported for escaping a newline character.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Sandipan Das <sandipan.das@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Xin Gao <gaoxin@cdjrlc.com>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Link: https://lore.kernel.org/r/20221118024607.409083-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
1284ded7 1a9c20b4

+67 -42
+67 -42
tools/perf/builtin-list.c
··· 17 17 #include "util/metricgroup.h" 18 18 #include "util/string2.h" 19 19 #include "util/strlist.h" 20 + #include "util/strbuf.h" 20 21 #include <subcmd/pager.h> 21 22 #include <subcmd/parse-options.h> 22 23 #include <linux/zalloc.h> ··· 251 250 printf("%s]\n", print_state->need_sep ? "\n" : ""); 252 251 } 253 252 254 - static void fix_escape_printf(const char *fmt, ...) 253 + static void fix_escape_printf(struct strbuf *buf, const char *fmt, ...) 255 254 { 256 255 va_list args; 257 - char buf[2048]; 258 - size_t buf_pos = 0; 259 256 260 257 va_start(args, fmt); 258 + strbuf_setlen(buf, 0); 261 259 for (size_t fmt_pos = 0; fmt_pos < strlen(fmt); fmt_pos++) { 262 260 switch (fmt[fmt_pos]) { 263 - case '%': { 264 - const char *s = va_arg(args, const char*); 265 - 261 + case '%': 266 262 fmt_pos++; 267 - assert(fmt[fmt_pos] == 's'); 268 - for (size_t s_pos = 0; s_pos < strlen(s); s_pos++) { 269 - switch (s[s_pos]) { 270 - case '\\': 271 - __fallthrough; 272 - case '\"': 273 - buf[buf_pos++] = '\\'; 274 - assert(buf_pos < sizeof(buf)); 275 - __fallthrough; 276 - default: 277 - buf[buf_pos++] = s[s_pos]; 278 - assert(buf_pos < sizeof(buf)); 279 - break; 263 + switch (fmt[fmt_pos]) { 264 + case 's': { 265 + const char *s = va_arg(args, const char*); 266 + 267 + strbuf_addstr(buf, s); 268 + break; 269 + } 270 + case 'S': { 271 + const char *s = va_arg(args, const char*); 272 + 273 + for (size_t s_pos = 0; s_pos < strlen(s); s_pos++) { 274 + switch (s[s_pos]) { 275 + case '\n': 276 + strbuf_addstr(buf, "\\n"); 277 + break; 278 + case '\\': 279 + __fallthrough; 280 + case '\"': 281 + strbuf_addch(buf, '\\'); 282 + __fallthrough; 283 + default: 284 + strbuf_addch(buf, s[s_pos]); 285 + break; 286 + } 280 287 } 288 + break; 289 + } 290 + default: 291 + pr_err("Unexpected format character '%c'\n", fmt[fmt_pos]); 292 + strbuf_addch(buf, '%'); 293 + strbuf_addch(buf, fmt[fmt_pos]); 281 294 } 282 295 break; 283 - } 284 296 default: 285 - buf[buf_pos++] = fmt[fmt_pos]; 286 - assert(buf_pos < sizeof(buf)); 297 + strbuf_addch(buf, fmt[fmt_pos]); 287 298 break; 288 299 } 289 300 } 290 301 va_end(args); 291 - buf[buf_pos] = '\0'; 292 - fputs(buf, stdout); 302 + fputs(buf->buf, stdout); 293 303 } 294 304 295 305 static void json_print_event(void *ps, const char *pmu_name, const char *topic, ··· 313 301 { 314 302 struct json_print_state *print_state = ps; 315 303 bool need_sep = false; 304 + struct strbuf buf; 316 305 306 + strbuf_init(&buf, 0); 317 307 printf("%s{\n", print_state->need_sep ? ",\n" : ""); 318 308 print_state->need_sep = true; 319 309 if (pmu_name) { 320 - fix_escape_printf("\t\"Unit\": \"%s\"", pmu_name); 310 + fix_escape_printf(&buf, "\t\"Unit\": \"%S\"", pmu_name); 321 311 need_sep = true; 322 312 } 323 313 if (topic) { 324 - fix_escape_printf("%s\t\"Topic\": \"%s\"", need_sep ? ",\n" : "", topic); 314 + fix_escape_printf(&buf, "%s\t\"Topic\": \"%S\"", need_sep ? ",\n" : "", topic); 325 315 need_sep = true; 326 316 } 327 317 if (event_name) { 328 - fix_escape_printf("%s\t\"EventName\": \"%s\"", need_sep ? ",\n" : "", event_name); 318 + fix_escape_printf(&buf, "%s\t\"EventName\": \"%S\"", need_sep ? ",\n" : "", 319 + event_name); 329 320 need_sep = true; 330 321 } 331 322 if (event_alias && strlen(event_alias)) { 332 - fix_escape_printf("%s\t\"EventAlias\": \"%s\"", need_sep ? ",\n" : "", event_alias); 323 + fix_escape_printf(&buf, "%s\t\"EventAlias\": \"%S\"", need_sep ? ",\n" : "", 324 + event_alias); 333 325 need_sep = true; 334 326 } 335 327 if (scale_unit && strlen(scale_unit)) { 336 - fix_escape_printf("%s\t\"ScaleUnit\": \"%s\"", need_sep ? ",\n" : "", 328 + fix_escape_printf(&buf, "%s\t\"ScaleUnit\": \"%S\"", need_sep ? ",\n" : "", 337 329 scale_unit); 338 330 need_sep = true; 339 331 } 340 332 if (event_type_desc) { 341 - fix_escape_printf("%s\t\"EventType\": \"%s\"", need_sep ? ",\n" : "", 333 + fix_escape_printf(&buf, "%s\t\"EventType\": \"%S\"", need_sep ? ",\n" : "", 342 334 event_type_desc); 343 335 need_sep = true; 344 336 } 345 337 if (deprecated) { 346 - fix_escape_printf("%s\t\"Deprecated\": \"%s\"", need_sep ? ",\n" : "", 338 + fix_escape_printf(&buf, "%s\t\"Deprecated\": \"%S\"", need_sep ? ",\n" : "", 347 339 deprecated ? "1" : "0"); 348 340 need_sep = true; 349 341 } 350 342 if (desc) { 351 - fix_escape_printf("%s\t\"BriefDescription\": \"%s\"", need_sep ? ",\n" : "", desc); 343 + fix_escape_printf(&buf, "%s\t\"BriefDescription\": \"%S\"", need_sep ? ",\n" : "", 344 + desc); 352 345 need_sep = true; 353 346 } 354 347 if (long_desc) { 355 - fix_escape_printf("%s\t\"PublicDescription\": \"%s\"", need_sep ? ",\n" : "", 348 + fix_escape_printf(&buf, "%s\t\"PublicDescription\": \"%S\"", need_sep ? ",\n" : "", 356 349 long_desc); 357 350 need_sep = true; 358 351 } 359 352 if (encoding_desc) { 360 - fix_escape_printf("%s\t\"Encoding\": \"%s\"", need_sep ? ",\n" : "", encoding_desc); 353 + fix_escape_printf(&buf, "%s\t\"Encoding\": \"%S\"", need_sep ? ",\n" : "", 354 + encoding_desc); 361 355 need_sep = true; 362 356 } 363 357 if (metric_name) { 364 - fix_escape_printf("%s\t\"MetricName\": \"%s\"", need_sep ? ",\n" : "", metric_name); 358 + fix_escape_printf(&buf, "%s\t\"MetricName\": \"%S\"", need_sep ? ",\n" : "", 359 + metric_name); 365 360 need_sep = true; 366 361 } 367 362 if (metric_expr) { 368 - fix_escape_printf("%s\t\"MetricExpr\": \"%s\"", need_sep ? ",\n" : "", metric_expr); 363 + fix_escape_printf(&buf, "%s\t\"MetricExpr\": \"%S\"", need_sep ? ",\n" : "", 364 + metric_expr); 369 365 need_sep = true; 370 366 } 371 367 printf("%s}", need_sep ? "\n" : ""); 368 + strbuf_release(&buf); 372 369 } 373 370 374 371 static void json_print_metric(void *ps __maybe_unused, const char *group, ··· 387 366 { 388 367 struct json_print_state *print_state = ps; 389 368 bool need_sep = false; 369 + struct strbuf buf; 390 370 371 + strbuf_init(&buf, 0); 391 372 printf("%s{\n", print_state->need_sep ? ",\n" : ""); 392 373 print_state->need_sep = true; 393 374 if (group) { 394 - fix_escape_printf("\t\"MetricGroup\": \"%s\"", group); 375 + fix_escape_printf(&buf, "\t\"MetricGroup\": \"%S\"", group); 395 376 need_sep = true; 396 377 } 397 378 if (name) { 398 - fix_escape_printf("%s\t\"MetricName\": \"%s\"", need_sep ? ",\n" : "", name); 379 + fix_escape_printf(&buf, "%s\t\"MetricName\": \"%S\"", need_sep ? ",\n" : "", name); 399 380 need_sep = true; 400 381 } 401 382 if (expr) { 402 - fix_escape_printf("%s\t\"MetricExpr\": \"%s\"", need_sep ? ",\n" : "", expr); 383 + fix_escape_printf(&buf, "%s\t\"MetricExpr\": \"%S\"", need_sep ? ",\n" : "", expr); 403 384 need_sep = true; 404 385 } 405 386 if (unit) { 406 - fix_escape_printf("%s\t\"ScaleUnit\": \"%s\"", need_sep ? ",\n" : "", unit); 387 + fix_escape_printf(&buf, "%s\t\"ScaleUnit\": \"%S\"", need_sep ? ",\n" : "", unit); 407 388 need_sep = true; 408 389 } 409 390 if (desc) { 410 - fix_escape_printf("%s\t\"BriefDescription\": \"%s\"", need_sep ? ",\n" : "", desc); 391 + fix_escape_printf(&buf, "%s\t\"BriefDescription\": \"%S\"", need_sep ? ",\n" : "", 392 + desc); 411 393 need_sep = true; 412 394 } 413 395 if (long_desc) { 414 - fix_escape_printf("%s\t\"PublicDescription\": \"%s\"", need_sep ? ",\n" : "", 396 + fix_escape_printf(&buf, "%s\t\"PublicDescription\": \"%S\"", need_sep ? ",\n" : "", 415 397 long_desc); 416 398 need_sep = true; 417 399 } 418 400 printf("%s}", need_sep ? "\n" : ""); 401 + strbuf_release(&buf); 419 402 } 420 403 421 404 int cmd_list(int argc, const char **argv)