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