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
15    mydir = TestBase.compute_mydir(__file__)
16
17    @skipUnlessUndefinedBehaviorSanitizer
18    @no_debug_info_test
19    def test(self):
20        self.build()
21        self.ubsan_tests()
22
23    def setUp(self):
24        # Call super's setUp().
25        TestBase.setUp(self)
26        self.line_align = line_number('main.c', '// align line')
27
28    def ubsan_tests(self):
29        # Load the test
30        exe = self.getBuildArtifact("a.out")
31        target = self.dbg.CreateTarget(exe)
32        self.assertTrue(target, VALID_TARGET)
33        self.registerSanitizerLibrariesWithTarget(target)
34
35        self.runCmd("run")
36
37        process = self.dbg.GetSelectedTarget().process
38        thread = process.GetSelectedThread()
39        frame = thread.GetSelectedFrame()
40
41        # the stop reason of the thread should be breakpoint.
42        self.expect("thread list", "A ubsan issue should be detected",
43                    substrs=['stopped', 'stop reason ='])
44
45        stop_reason = thread.GetStopReason()
46        self.assertEqual(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        # We should be stopped in __ubsan_on_report
55        self.assertIn("__ubsan_on_report", frame.GetFunctionName())
56
57        # The stopped thread backtrace should contain either 'align line'
58        found = False
59        for i in range(thread.GetNumFrames()):
60            frame = thread.GetFrameAtIndex(i)
61            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":
62                if frame.GetLineEntry().GetLine() == self.line_align:
63                    found = True
64        self.assertTrue(found)
65
66        backtraces = thread.GetStopReasonExtendedBacktraces(
67            lldb.eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer)
68        self.assertEquals(backtraces.GetSize(), 1)
69
70        self.expect(
71            "thread info -s",
72            "The extended stop info should contain the UBSan provided fields",
73            substrs=[
74                "col",
75                "description",
76                "filename",
77                "instrumentation_class",
78                "line",
79                "memory_address",
80            ])
81
82        output_lines = self.res.GetOutput().split('\n')
83        json_line = '\n'.join(output_lines[2:])
84        data = json.loads(json_line)
85
86        self.assertEqual(data["instrumentation_class"], "UndefinedBehaviorSanitizer")
87        self.assertEqual(data["description"], "misaligned-pointer-use")
88        self.assertEqual(os.path.basename(data["filename"]), "main.c")
89        self.assertEqual(data["line"], self.line_align)
90
91        self.runCmd("continue")
92