diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-04-14 18:39:42 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-04-14 16:41:21 -0400 |
commit | d3b63d7ae04879a817bac5c0bf09749f73629d32 (patch) | |
tree | 80501b4ed6110221160b9486dd24b480c3424f41 /tools/perf/util | |
parent | dd259c5db26ccda46409dbf6efc79d5a2b259e38 (diff) |
perf probe: Fix a bug that --line range can be overflow
Since line_finder.lno_s/e are signed int but line_range.start/end
are unsigned int, it is possible to be overflow when converting
line_range->start/end to line_finder->lno_s/e.
This changes line_range.start/end and line_list.line to signed int
and adds overflow checks when setting line_finder.lno_s/e.
LKML-Reference: <20100414223942.14630.72730.stgit@localhost6.localdomain6>
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/probe-event.c | 23 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 6 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 19 |
3 files changed, 24 insertions, 24 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 6d438391bae5..954ca210e4b7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -189,7 +189,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, | |||
189 | #define LINEBUF_SIZE 256 | 189 | #define LINEBUF_SIZE 256 |
190 | #define NR_ADDITIONAL_LINES 2 | 190 | #define NR_ADDITIONAL_LINES 2 |
191 | 191 | ||
192 | static int show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) | 192 | static int show_one_line(FILE *fp, int l, bool skip, bool show_num) |
193 | { | 193 | { |
194 | char buf[LINEBUF_SIZE]; | 194 | char buf[LINEBUF_SIZE]; |
195 | const char *color = PERF_COLOR_BLUE; | 195 | const char *color = PERF_COLOR_BLUE; |
@@ -198,7 +198,7 @@ static int show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) | |||
198 | goto error; | 198 | goto error; |
199 | if (!skip) { | 199 | if (!skip) { |
200 | if (show_num) | 200 | if (show_num) |
201 | fprintf(stdout, "%7u %s", l, buf); | 201 | fprintf(stdout, "%7d %s", l, buf); |
202 | else | 202 | else |
203 | color_fprintf(stdout, color, " %s", buf); | 203 | color_fprintf(stdout, color, " %s", buf); |
204 | } | 204 | } |
@@ -231,7 +231,7 @@ error: | |||
231 | */ | 231 | */ |
232 | int show_line_range(struct line_range *lr) | 232 | int show_line_range(struct line_range *lr) |
233 | { | 233 | { |
234 | unsigned int l = 1; | 234 | int l = 1; |
235 | struct line_node *ln; | 235 | struct line_node *ln; |
236 | FILE *fp; | 236 | FILE *fp; |
237 | int fd, ret; | 237 | int fd, ret; |
@@ -340,16 +340,15 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) | |||
340 | */ | 340 | */ |
341 | ptr = strchr(arg, ':'); | 341 | ptr = strchr(arg, ':'); |
342 | if (ptr) { | 342 | if (ptr) { |
343 | lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0); | 343 | lr->start = (int)strtoul(ptr + 1, &tmp, 0); |
344 | if (*tmp == '+') | 344 | if (*tmp == '+') |
345 | lr->end = lr->start + (unsigned int)strtoul(tmp + 1, | 345 | lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); |
346 | &tmp, 0); | ||
347 | else if (*tmp == '-') | 346 | else if (*tmp == '-') |
348 | lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0); | 347 | lr->end = (int)strtoul(tmp + 1, &tmp, 0); |
349 | else | 348 | else |
350 | lr->end = 0; | 349 | lr->end = INT_MAX; |
351 | pr_debug("Line range is %u to %u\n", lr->start, lr->end); | 350 | pr_debug("Line range is %d to %d\n", lr->start, lr->end); |
352 | if (lr->end && lr->start > lr->end) { | 351 | if (lr->start > lr->end) { |
353 | semantic_error("Start line must be smaller" | 352 | semantic_error("Start line must be smaller" |
354 | " than end line.\n"); | 353 | " than end line.\n"); |
355 | return -EINVAL; | 354 | return -EINVAL; |
@@ -360,8 +359,10 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) | |||
360 | return -EINVAL; | 359 | return -EINVAL; |
361 | } | 360 | } |
362 | tmp = strndup(arg, (ptr - arg)); | 361 | tmp = strndup(arg, (ptr - arg)); |
363 | } else | 362 | } else { |
364 | tmp = strdup(arg); | 363 | tmp = strdup(arg); |
364 | lr->end = INT_MAX; | ||
365 | } | ||
365 | 366 | ||
366 | if (tmp == NULL) | 367 | if (tmp == NULL) |
367 | return -ENOMEM; | 368 | return -ENOMEM; |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index ab5492901708..e7ff0d02c0d4 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -74,15 +74,15 @@ struct perf_probe_event { | |||
74 | /* Line number container */ | 74 | /* Line number container */ |
75 | struct line_node { | 75 | struct line_node { |
76 | struct list_head list; | 76 | struct list_head list; |
77 | unsigned int line; | 77 | int line; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | /* Line range */ | 80 | /* Line range */ |
81 | struct line_range { | 81 | struct line_range { |
82 | char *file; /* File name */ | 82 | char *file; /* File name */ |
83 | char *function; /* Function name */ | 83 | char *function; /* Function name */ |
84 | unsigned int start; /* Start line number */ | 84 | int start; /* Start line number */ |
85 | unsigned int end; /* End line number */ | 85 | int end; /* End line number */ |
86 | int offset; /* Start line offset */ | 86 | int offset; /* Start line offset */ |
87 | char *path; /* Real path name */ | 87 | char *path; /* Real path name */ |
88 | struct list_head line_list; /* Visible lines */ | 88 | struct list_head line_list; /* Visible lines */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e443e69a4d2e..b4c93659929a 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -111,7 +111,7 @@ static int strtailcmp(const char *s1, const char *s2) | |||
111 | /* Line number list operations */ | 111 | /* Line number list operations */ |
112 | 112 | ||
113 | /* Add a line to line number list */ | 113 | /* Add a line to line number list */ |
114 | static int line_list__add_line(struct list_head *head, unsigned int line) | 114 | static int line_list__add_line(struct list_head *head, int line) |
115 | { | 115 | { |
116 | struct line_node *ln; | 116 | struct line_node *ln; |
117 | struct list_head *p; | 117 | struct list_head *p; |
@@ -138,7 +138,7 @@ found: | |||
138 | } | 138 | } |
139 | 139 | ||
140 | /* Check if the line in line number list */ | 140 | /* Check if the line in line number list */ |
141 | static int line_list__has_line(struct list_head *head, unsigned int line) | 141 | static int line_list__has_line(struct list_head *head, int line) |
142 | { | 142 | { |
143 | struct line_node *ln; | 143 | struct line_node *ln; |
144 | 144 | ||
@@ -1146,7 +1146,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) | |||
1146 | if (lf->lr->path == NULL) | 1146 | if (lf->lr->path == NULL) |
1147 | return -ENOMEM; | 1147 | return -ENOMEM; |
1148 | } | 1148 | } |
1149 | line_list__add_line(&lf->lr->line_list, (unsigned int)lineno); | 1149 | line_list__add_line(&lf->lr->line_list, lineno); |
1150 | } | 1150 | } |
1151 | /* Update status */ | 1151 | /* Update status */ |
1152 | if (!list_empty(&lf->lr->line_list)) | 1152 | if (!list_empty(&lf->lr->line_list)) |
@@ -1179,10 +1179,12 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
1179 | dwarf_decl_line(sp_die, &lr->offset); | 1179 | dwarf_decl_line(sp_die, &lr->offset); |
1180 | pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); | 1180 | pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); |
1181 | lf->lno_s = lr->offset + lr->start; | 1181 | lf->lno_s = lr->offset + lr->start; |
1182 | if (!lr->end) | 1182 | if (lf->lno_s < 0) /* Overflow */ |
1183 | lf->lno_s = INT_MAX; | ||
1184 | lf->lno_e = lr->offset + lr->end; | ||
1185 | if (lf->lno_e < 0) /* Overflow */ | ||
1183 | lf->lno_e = INT_MAX; | 1186 | lf->lno_e = INT_MAX; |
1184 | else | 1187 | pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); |
1185 | lf->lno_e = lr->offset + lr->end; | ||
1186 | lr->start = lf->lno_s; | 1188 | lr->start = lf->lno_s; |
1187 | lr->end = lf->lno_e; | 1189 | lr->end = lf->lno_e; |
1188 | if (dwarf_func_inline(sp_die)) { | 1190 | if (dwarf_func_inline(sp_die)) { |
@@ -1244,10 +1246,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
1244 | ret = find_line_range_by_func(&lf); | 1246 | ret = find_line_range_by_func(&lf); |
1245 | else { | 1247 | else { |
1246 | lf.lno_s = lr->start; | 1248 | lf.lno_s = lr->start; |
1247 | if (!lr->end) | 1249 | lf.lno_e = lr->end; |
1248 | lf.lno_e = INT_MAX; | ||
1249 | else | ||
1250 | lf.lno_e = lr->end; | ||
1251 | ret = find_line_range_by_line(NULL, &lf); | 1250 | ret = find_line_range_by_line(NULL, &lf); |
1252 | } | 1251 | } |
1253 | } | 1252 | } |