1"""
2Test the AddressSanitizer runtime support for report breakpoint and data extraction.
3"""
4
5
6
7import json
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class AsanTestReportDataCase(TestBase):
15
16    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
17    @expectedFailureNetBSD
18    @skipUnlessAddressSanitizer
19    @skipIf(archs=['i386'], bugnumber="llvm.org/PR36710")
20    def test(self):
21        self.build()
22        self.asan_tests()
23
24    def setUp(self):
25        # Call super's setUp().
26        TestBase.setUp(self)
27        self.line_malloc = line_number('main.c', '// malloc line')
28        self.line_malloc2 = line_number('main.c', '// malloc2 line')
29        self.line_free = line_number('main.c', '// free line')
30        self.line_breakpoint = line_number('main.c', '// break line')
31        self.line_crash = line_number('main.c', '// BOOM line')
32        self.col_crash = 16
33
34    def asan_tests(self):
35        target = self.createTestTarget()
36
37        self.registerSanitizerLibrariesWithTarget(target)
38
39        self.runCmd("run")
40
41        stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
42        if stop_reason == lldb.eStopReasonExec:
43            # On OS X 10.10 and older, we need to re-exec to enable
44            # interceptors.
45            self.runCmd("continue")
46
47        self.expect(
48            "thread list",
49            "Process should be stopped due to ASan report",
50            substrs=[
51                'stopped',
52                'stop reason = Use of deallocated memory'])
53
54        self.assertEqual(
55            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(),
56            lldb.eStopReasonInstrumentation)
57
58        self.expect("bt", "The backtrace should show the crashing line",
59                    substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)])
60
61        self.expect(
62            "thread info -s",
63            "The extended stop info should contain the ASan provided fields",
64            substrs=[
65                "access_size",
66                "access_type",
67                "address",
68                "description",
69                "heap-use-after-free",
70                "pc",
71            ])
72
73        output_lines = self.res.GetOutput().split('\n')
74        json_line = '\n'.join(output_lines[2:])
75        data = json.loads(json_line)
76        self.assertEqual(data["description"], "heap-use-after-free")
77        self.assertEqual(data["instrumentation_class"], "AddressSanitizer")
78        self.assertEqual(data["stop_type"], "fatal_error")
79
80        # now let's try the SB API
81        process = self.dbg.GetSelectedTarget().process
82        thread = process.GetSelectedThread()
83
84        s = lldb.SBStream()
85        self.assertTrue(thread.GetStopReasonExtendedInfoAsJSON(s))
86        s = s.GetData()
87        data2 = json.loads(s)
88        self.assertEqual(data, data2)
89