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