diff options
author | Jiri Olsa <jolsa@redhat.com> | 2013-01-24 15:46:43 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-25 10:49:28 -0500 |
commit | e23c1a5578cf32ed3a7ac9dde59a2de0a52ff812 (patch) | |
tree | d58e6e41a4d8ff4f5e437225607e4fdb86cd12d3 /tools/lib | |
parent | a2d28d0c198b65fac28ea6212f5f8edc77b29c27 (diff) |
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>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index bb8b3db0e583..82b0606dcb8a 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -1223,6 +1223,34 @@ static int field_is_long(struct format_field *field) | |||
1223 | return 0; | 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 | static int event_read_fields(struct event_format *event, struct format_field **fields) | 1254 | static int event_read_fields(struct event_format *event, struct format_field **fields) |
1227 | { | 1255 | { |
1228 | struct format_field *field = NULL; | 1256 | struct format_field *field = NULL; |
@@ -1232,6 +1260,8 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1232 | int count = 0; | 1260 | int count = 0; |
1233 | 1261 | ||
1234 | do { | 1262 | do { |
1263 | unsigned int size_dynamic = 0; | ||
1264 | |||
1235 | type = read_token(&token); | 1265 | type = read_token(&token); |
1236 | if (type == EVENT_NEWLINE) { | 1266 | if (type == EVENT_NEWLINE) { |
1237 | free_token(token); | 1267 | free_token(token); |
@@ -1390,6 +1420,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1390 | field->type = new_type; | 1420 | field->type = new_type; |
1391 | strcat(field->type, " "); | 1421 | strcat(field->type, " "); |
1392 | strcat(field->type, field->name); | 1422 | strcat(field->type, field->name); |
1423 | size_dynamic = type_size(field->name); | ||
1393 | free_token(field->name); | 1424 | free_token(field->name); |
1394 | strcat(field->type, brackets); | 1425 | strcat(field->type, brackets); |
1395 | field->name = token; | 1426 | field->name = token; |
@@ -1478,10 +1509,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1478 | if (field->flags & FIELD_IS_ARRAY) { | 1509 | if (field->flags & FIELD_IS_ARRAY) { |
1479 | if (field->arraylen) | 1510 | if (field->arraylen) |
1480 | field->elementsize = field->size / field->arraylen; | 1511 | field->elementsize = field->size / field->arraylen; |
1512 | else if (field->flags & FIELD_IS_DYNAMIC) | ||
1513 | field->elementsize = size_dynamic; | ||
1481 | else if (field->flags & FIELD_IS_STRING) | 1514 | else if (field->flags & FIELD_IS_STRING) |
1482 | field->elementsize = 1; | 1515 | field->elementsize = 1; |
1483 | else | 1516 | else if (field->flags & FIELD_IS_LONG) |
1484 | field->elementsize = event->pevent->long_size; | 1517 | field->elementsize = event->pevent ? |
1518 | event->pevent->long_size : | ||
1519 | sizeof(long); | ||
1485 | } else | 1520 | } else |
1486 | field->elementsize = field->size; | 1521 | field->elementsize = field->size; |
1487 | 1522 | ||