xref: /llvm-project/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
1"""
2Tests basic UndefinedBehaviorSanitizer support (detecting an alignment error).
3"""
4
5import os
6import lldb
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test.decorators import *
9import lldbsuite.test.lldbutil as lldbutil
10import json
11
12
13class UbsanBasicTestCase(TestBase):
14    @skipUnlessUndefinedBehaviorSanitizer
15    @no_debug_info_test
16    def test(self):
17        self.build()
18        self.ubsan_tests()
19
20    def setUp(self):
21        # Call super's setUp().
22        TestBase.setUp(self)
23        self.line_align = line_number("main.c", "// align line")
24
25    def ubsan_tests(self):
26        # Load the test
27        exe = self.getBuildArtifact("a.out")
28        target = self.dbg.CreateTarget(exe)
29        self.assertTrue(target, VALID_TARGET)
30        self.registerSanitizerLibrariesWithTarget(target)
31
32        self.runCmd("run")
33
34        process = self.dbg.GetSelectedTarget().process
35        thread = process.GetSelectedThread()
36        frame = thread.GetSelectedFrame()
37
38        # the stop reason of the thread should be breakpoint.
39        self.expect(
40            "thread list",
41            "A ubsan issue should be detected",
42            substrs=["stopped", "stop reason ="],
43        )
44
45        stop_reason = thread.GetStopReason()
46        self.assertStopReason(stop_reason, lldb.eStopReasonInstrumentation)
47
48        # test that the UBSan dylib is present
49        self.expect(
50            "image lookup -n __ubsan_on_report",
51            "__ubsan_on_report should be present",
52            substrs=["1 match found"],
53        )
54
55        # We should be stopped in __ubsan_on_report
56        self.assertIn("__ubsan_on_report", frame.GetFunctionName())
57
58        # The stopped thread backtrace should contain either 'align line'
59        found = False
60        for i in range(thread.GetNumFrames()):
61            frame = thread.GetFrameAtIndex(i)
62            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":
63                if frame.GetLineEntry().GetLine() == self.line_align:
64                    found = True
65        self.assertTrue(found)
66
67        backtraces = thread.GetStopReasonExtendedBacktraces(
68            lldb.eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer
69        )
70        self.assertEqual(backtraces.GetSize(), 1)
71
72        self.expect(
73            "thread info -s",
74            "The extended stop info should contain the UBSan provided fields",
75            substrs=[
76                "col",
77                "description",
78                "filename",
79                "instrumentation_class",
80                "line",
81                "memory_address",
82            ],
83        )
84
85        output_lines = self.res.GetOutput().split("\n")
86        json_line = "\n".join(output_lines[2:])
87        data = json.loads(json_line)
88
89        self.assertEqual(data["instrumentation_class"], "UndefinedBehaviorSanitizer")
90        self.assertEqual(data["description"], "misaligned-pointer-use")
91        self.assertEqual(os.path.basename(data["filename"]), "main.c")
92        self.assertEqual(data["line"], self.line_align)
93
94        for count in range(0, 8):
95            process.Continue()
96            stop_reason = thread.GetStopReason()
97            self.assertEqual(
98                stop_reason,
99                lldb.eStopReasonInstrumentation,
100                "Round {0} wasn't instrumentation".format(count),
101            )
102