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

tools lib traceevent: Handle dynamic array's element size properly

Fixing the dynamic array format field parsing.

Currently the event_read_fields function could segfault while parsing
dynamic array other than string type. The reason is the event->pevent
does not need to be set and gets dereferenced unconditionaly.

Also adding proper initialization of field->elementsize based on the
parsed dynamic type.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1359060403-32422-1-git-send-email-jolsa@redhat.com
[ committer note: Made a char pointer parameter const, as requested by Steven ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
e23c1a55 a2d28d0c

+37 -2
+37 -2
tools/lib/traceevent/event-parse.c
··· 1223 1223 return 0; 1224 1224 } 1225 1225 1226 + static unsigned int type_size(const char *name) 1227 + { 1228 + /* This covers all FIELD_IS_STRING types. */ 1229 + static struct { 1230 + const char *type; 1231 + unsigned int size; 1232 + } table[] = { 1233 + { "u8", 1 }, 1234 + { "u16", 2 }, 1235 + { "u32", 4 }, 1236 + { "u64", 8 }, 1237 + { "s8", 1 }, 1238 + { "s16", 2 }, 1239 + { "s32", 4 }, 1240 + { "s64", 8 }, 1241 + { "char", 1 }, 1242 + { }, 1243 + }; 1244 + int i; 1245 + 1246 + for (i = 0; table[i].type; i++) { 1247 + if (!strcmp(table[i].type, name)) 1248 + return table[i].size; 1249 + } 1250 + 1251 + return 0; 1252 + } 1253 + 1226 1254 static int event_read_fields(struct event_format *event, struct format_field **fields) 1227 1255 { 1228 1256 struct format_field *field = NULL; ··· 1260 1232 int count = 0; 1261 1233 1262 1234 do { 1235 + unsigned int size_dynamic = 0; 1236 + 1263 1237 type = read_token(&token); 1264 1238 if (type == EVENT_NEWLINE) { 1265 1239 free_token(token); ··· 1420 1390 field->type = new_type; 1421 1391 strcat(field->type, " "); 1422 1392 strcat(field->type, field->name); 1393 + size_dynamic = type_size(field->name); 1423 1394 free_token(field->name); 1424 1395 strcat(field->type, brackets); 1425 1396 field->name = token; ··· 1509 1478 if (field->flags & FIELD_IS_ARRAY) { 1510 1479 if (field->arraylen) 1511 1480 field->elementsize = field->size / field->arraylen; 1481 + else if (field->flags & FIELD_IS_DYNAMIC) 1482 + field->elementsize = size_dynamic; 1512 1483 else if (field->flags & FIELD_IS_STRING) 1513 1484 field->elementsize = 1; 1514 - else 1515 - field->elementsize = event->pevent->long_size; 1485 + else if (field->flags & FIELD_IS_LONG) 1486 + field->elementsize = event->pevent ? 1487 + event->pevent->long_size : 1488 + sizeof(long); 1516 1489 } else 1517 1490 field->elementsize = field->size; 1518 1491