From 32085a78c063d80cc152f341343a87c8cfecfd2f Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Thu, 2 Oct 2014 16:46:30 +0200 Subject: [SATYR PATCH] java: ignore suppressed exceptions Java exceptions can form a tree - every exception can have reference to exception that caused it and to a list of exceptions that were suppressed during handling[1]. We cannot take the suppressed exceptions into account without changing the uReport format, therefore this commit makes the java parser ignore them. [1] http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html Fixes rhbz#1034857. Signed-off-by: Martin Milata --- include/utils.h | 3 + lib/java_frame.c | 26 ++++-- lib/utils.c | 16 ++++ tests/java_stacktraces/java-04 | 185 +++++++++++++++++++++++++++++++++++++++++ tests/python/java.py | 12 +++ 5 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 tests/java_stacktraces/java-04 diff --git a/include/utils.h b/include/utils.h index 8d0a6ec..1c7984b 100644 --- a/include/utils.h +++ b/include/utils.h @@ -378,6 +378,9 @@ sr_skip_whitespace(const char *s); char * sr_skip_non_whitespace(const char *s); +bool +sr_skip_to_next_line_location(const char **s, int *line, int *column); + /** * Emit a string of hex representation of bytes. */ diff --git a/lib/java_frame.c b/lib/java_frame.c index da9f26b..ee97572 100644 --- a/lib/java_frame.c +++ b/lib/java_frame.c @@ -28,6 +28,7 @@ #include "stacktrace.h" #include "internal_utils.h" #include +#include #include #define SR_JF_MARK_NATIVE_METHOD "Native Method" @@ -337,6 +338,10 @@ sr_java_frame_parse_exception(const char **input, if (strncmp("... ", cursor, strlen("... ")) == 0) goto current_exception_done; + /* Suppressed exceptions follow after the end of current exception */ + if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) + goto current_exception_done; + /* The top most exception does not have '...' at its end */ if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) goto parse_inner_exception; @@ -363,19 +368,24 @@ sr_java_frame_parse_exception(const char **input, goto exception_parsing_successful; current_exception_done: - sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "\n")); - - if (*cursor == '\n') - { - ++cursor; - /* this adds one line */ - sr_location_add(location, 2, 0); - } + sr_skip_to_next_line_location(&cursor, &location->line, &location->column); mark = cursor; cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); + if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) + { + /* Skip all lines related to the suppressed exception. We can do + * this by skipping all lines that begin with a whitespace - the + * main exception chain always begins without preceding whitespace. + */ + sr_skip_to_next_line_location(&cursor, &location->line, &location->column); + + while (cursor && isspace(*cursor)) + sr_skip_to_next_line_location(&cursor, &location->line, &location->column); + } + if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) { parse_inner_exception: diff --git a/lib/utils.c b/lib/utils.c index 3c036f3..fa3c0a0 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -656,6 +656,22 @@ sr_skip_non_whitespace(const char *s) return (char *) s; } +bool +sr_skip_to_next_line_location(const char **s, int *line, int *column) +{ + *column += sr_skip_char_cspan(s, "\n"); + + if (*s && **s == '\n') + { + *column = 0; + (*line)++; + (*s)++; + return true; + } + + return false; +} + char * sr_bin2hex(char *dst, const char *str, int count) { diff --git a/tests/java_stacktraces/java-04 b/tests/java_stacktraces/java-04 new file mode 100644 index 0000000..6968eb3 --- /dev/null +++ b/tests/java_stacktraces/java-04 @@ -0,0 +1,185 @@ +Exception in thread "main" java.lang.RuntimeException: yes + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.main(WontCatchSuppressedException.java:35) +Caused by: java.lang.RuntimeException: yes + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 1 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 1 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 3 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 1 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 3 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 5 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more +Caused by: java.lang.RuntimeException: yes + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 2 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 2 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:29) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 2 more + Caused by: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 4 more +Caused by: java.lang.RuntimeException: yes + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:27) + ... 3 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more + Suppressed: java.lang.RuntimeException: no + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:23) + at WontCatchSuppressedException.close(WontCatchSuppressedException.java:16) + at WontCatchSuppressedException.die(WontCatchSuppressedException.java:28) + ... 3 more diff --git a/tests/python/java.py b/tests/python/java.py index 3b85c18..1156fb6 100755 --- a/tests/python/java.py +++ b/tests/python/java.py @@ -152,6 +152,18 @@ class TestJavaStacktrace(BindingsTestCase): def test_hash(self): self.assertHashable(self.trace) + def test_suppressed(self): + contents = load_input_contents('../java_stacktraces/java-04') + trace = satyr.JavaStacktrace(contents) + + names = 4*['java.lang.RuntimeException', 'WontCatchSuppressedException.die', 'WontCatchSuppressedException.die'] + names[-1] = 'WontCatchSuppressedException.main' + msgs = 4*['yes', None, None] + + for frame, name, msg in zip(trace.threads[0].frames, names, msgs): + self.assertEqual(frame.name, name) + self.assertEqual(frame.message, msg) + class TestJavaThread(BindingsTestCase): def setUp(self): self.thread = satyr.JavaStacktrace(contents).threads[0] -- 1.9.3