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