Bug Summary

File:build/source/lldb/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
Warning:line 335, column 12
5th function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cli-wrapper-mpxtable.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D HAVE_ROUND -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/tools/intel-features/intel-mpx -I /build/source/lldb/tools/intel-features/intel-mpx -I /build/source/lldb/include -I tools/lldb/include -I include -I /build/source/llvm/include -I /usr/include/python3.9 -I /build/source/clang/include -I tools/lldb/../clang/include -I /usr/include/libxml2 -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-stringop-truncation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/lldb/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
1//===-- cli-wrapper-mpxtable.cpp --------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// C++ includes
10#include <cerrno>
11#include <string>
12
13#include "cli-wrapper-mpxtable.h"
14#include "lldb/API/SBCommandInterpreter.h"
15#include "lldb/API/SBCommandReturnObject.h"
16#include "lldb/API/SBMemoryRegionInfo.h"
17#include "lldb/API/SBProcess.h"
18#include "lldb/API/SBTarget.h"
19#include "lldb/API/SBThread.h"
20
21#include "llvm/ADT/Twine.h"
22#include "llvm/TargetParser/Triple.h"
23
24static bool GetPtr(char *cptr, uint64_t &ptr, lldb::SBFrame &frame,
25 lldb::SBCommandReturnObject &result) {
26 if (!cptr) {
27 result.SetError("Bad argument.");
28 result.SetStatus(lldb::eReturnStatusFailed);
29 return false;
30 }
31
32 lldb::SBValue ptr_addr = frame.GetValueForVariablePath(cptr);
33 if (!ptr_addr.IsValid()) {
34 result.SetError("Invalid pointer.");
35 result.SetStatus(lldb::eReturnStatusFailed);
36 return false;
37 }
38 ptr = ptr_addr.GetLoadAddress();
39 return true;
40}
41
42enum {
43 mpx_base_mask_64 = ~(uint64_t)0xFFFULL,
44 mpx_bd_mask_64 = 0xFFFFFFF00000ULL,
45 bd_r_shift_64 = 20,
46 bd_l_shift_64 = 3,
47 bt_r_shift_64 = 3,
48 bt_l_shift_64 = 5,
49 bt_mask_64 = 0x0000000FFFF8ULL,
50
51 mpx_base_mask_32 = 0xFFFFFFFFFFFFF000ULL,
52 mpx_bd_mask_32 = 0xFFFFF000ULL,
53 bd_r_shift_32 = 12,
54 bd_l_shift_32 = 2,
55 bt_r_shift_32 = 2,
56 bt_l_shift_32 = 4,
57 bt_mask_32 = 0x00000FFCULL,
58};
59
60static void PrintBTEntry(lldb::addr_t lbound, lldb::addr_t ubound,
61 uint64_t value, uint64_t meta,
62 lldb::SBCommandReturnObject &result) {
63 const lldb::addr_t one_cmpl64 = ~((lldb::addr_t)0);
64 const lldb::addr_t one_cmpl32 = ~((uint32_t)0);
65
66 if ((lbound == one_cmpl64 || lbound == one_cmpl32) && ubound == 0) {
67 result.Printf("Null bounds on map: pointer value = 0x%" PRIu64"l" "u" "\n", value);
68 } else {
69 result.Printf(" lbound = 0x%" PRIu64"l" "u" ",", lbound);
70 result.Printf(" ubound = 0x%" PRIu64"l" "u" , ubound);
71 result.Printf(" (pointer value = 0x%" PRIu64"l" "u" ",", value);
72 result.Printf(" metadata = 0x%" PRIu64"l" "u" ")\n", meta);
73 }
74}
75
76static bool GetBTEntryAddr(uint64_t bndcfgu, uint64_t ptr,
77 lldb::SBTarget &target, llvm::Triple::ArchType arch,
78 size_t &size, lldb::addr_t &bt_entry_addr,
79 lldb::SBCommandReturnObject &result,
80 lldb::SBError &error) {
81 lldb::addr_t mpx_base_mask;
82 lldb::addr_t mpx_bd_mask;
83 lldb::addr_t bd_r_shift;
84 lldb::addr_t bd_l_shift;
85 lldb::addr_t bt_r_shift;
86 lldb::addr_t bt_l_shift;
87 lldb::addr_t bt_mask;
88
89 if (arch == llvm::Triple::ArchType::x86_64) {
90 mpx_base_mask = mpx_base_mask_64;
91 mpx_bd_mask = mpx_bd_mask_64;
92 bd_r_shift = bd_r_shift_64;
93 bd_l_shift = bd_l_shift_64;
94 bt_r_shift = bt_r_shift_64;
95 bt_l_shift = bt_l_shift_64;
96 bt_mask = bt_mask_64;
97 } else if (arch == llvm::Triple::ArchType::x86) {
98 mpx_base_mask = mpx_base_mask_32;
99 mpx_bd_mask = mpx_bd_mask_32;
100 bd_r_shift = bd_r_shift_32;
101 bd_l_shift = bd_l_shift_32;
102 bt_r_shift = bt_r_shift_32;
103 bt_l_shift = bt_l_shift_32;
104 bt_mask = bt_mask_32;
105 } else {
106 result.SetError("Invalid arch.");
107 result.SetStatus(lldb::eReturnStatusFailed);
108 return false;
109 }
110
111 size = target.GetAddressByteSize();
112 lldb::addr_t mpx_bd_base = bndcfgu & mpx_base_mask;
113 lldb::addr_t bd_entry_offset = ((ptr & mpx_bd_mask) >> bd_r_shift)
114 << bd_l_shift;
115 lldb::addr_t bd_entry_addr = mpx_bd_base + bd_entry_offset;
116
117 std::vector<uint8_t> bd_entry_v(size);
118 size_t ret = target.GetProcess().ReadMemory(
119 bd_entry_addr, static_cast<void *>(bd_entry_v.data()), size, error);
120 if (ret != size || !error.Success()) {
121 result.SetError("Failed access to BD entry.");
122 return false;
123 }
124
125 lldb::SBData data;
126 data.SetData(error, bd_entry_v.data(), bd_entry_v.size(),
127 target.GetByteOrder(), size);
128 lldb::addr_t bd_entry = data.GetAddress(error, 0);
129
130 if (!error.Success()) {
131 result.SetError("Failed access to BD entry.");
132 return false;
133 }
134
135 if ((bd_entry & 0x01) == 0) {
136 result.SetError("Invalid bound directory.");
137 result.SetStatus(lldb::eReturnStatusFailed);
138 return false;
139 }
140
141 // Clear status bit.
142 //
143 bd_entry--;
144
145 lldb::addr_t bt_addr = bd_entry & ~bt_r_shift;
146 lldb::addr_t bt_entry_offset = ((ptr & bt_mask) >> bt_r_shift) << bt_l_shift;
147 bt_entry_addr = bt_addr + bt_entry_offset;
148
149 return true;
150}
151
152static bool GetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::SBTarget &target,
153 llvm::Triple::ArchType arch,
154 lldb::SBCommandReturnObject &result,
155 lldb::SBError &error) {
156 lldb::addr_t bt_entry_addr;
157 size_t size;
158 if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
159 error))
160 return false;
161
162 // bt_entry_v must have space to store the 4 elements of the BT entry (lower
163 // boundary,
164 // upper boundary, pointer value and meta data), which all have the same size
165 // 'size'.
166 //
167 std::vector<uint8_t> bt_entry_v(size * 4);
168 size_t ret = target.GetProcess().ReadMemory(
169 bt_entry_addr, static_cast<void *>(bt_entry_v.data()), size * 4, error);
170
171 if ((ret != (size * 4)) || !error.Success()) {
172 result.SetError("Unsuccessful. Failed access to BT entry.");
173 result.SetStatus(lldb::eReturnStatusFailed);
174 return false;
175 }
176
177 lldb::addr_t lbound;
178 lldb::addr_t ubound;
179 uint64_t value;
180 uint64_t meta;
181 lldb::SBData data;
182 data.SetData(error, bt_entry_v.data(), bt_entry_v.size(),
183 target.GetByteOrder(), size);
184 lbound = data.GetAddress(error, size * 0);
185 ubound = data.GetAddress(error, size * 1);
186 value = data.GetAddress(error, size * 2);
187 meta = data.GetAddress(error, size * 3);
188 // ubound is stored as one's complement.
189 if (arch == llvm::Triple::ArchType::x86) {
190 ubound = (~ubound) & 0x00000000FFFFFFFF;
191 } else {
192 ubound = ~ubound;
193 }
194
195 if (!error.Success()) {
196 result.SetError("Failed access to BT entry.");
197 return false;
198 }
199
200 PrintBTEntry(lbound, ubound, value, meta, result);
201
202 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
203 return true;
204}
205
206static std::vector<uint8_t> uIntToU8(uint64_t input, size_t size) {
207 std::vector<uint8_t> output;
208 for (size_t i = 0; i < size; i++)
209 output.push_back(
210 static_cast<uint8_t>((input & (0xFFULL << (i * 8))) >> (i * 8)));
211
212 return output;
213}
214
215static bool SetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::addr_t lbound,
216 lldb::addr_t ubound, lldb::SBTarget &target,
217 llvm::Triple::ArchType arch,
218 lldb::SBCommandReturnObject &result,
219 lldb::SBError &error) {
220 lldb::addr_t bt_entry_addr;
221 size_t size;
222
223 if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
224 error))
225 return false;
226
227 // bt_entry_v must have space to store only 2 elements of the BT Entry, the
228 // lower boundary and the upper boundary, which both have size 'size'.
229 //
230 std::vector<uint8_t> bt_entry_v(size * 2);
231
232 std::vector<uint8_t> lbound_v = uIntToU8(lbound, size);
233 bt_entry_v.insert(bt_entry_v.begin(), lbound_v.begin(), lbound_v.end());
234 std::vector<uint8_t> ubound_v = uIntToU8(~ubound, size);
235 bt_entry_v.insert(bt_entry_v.begin() + size, ubound_v.begin(),
236 ubound_v.end());
237
238 size_t ret = target.GetProcess().WriteMemory(
239 bt_entry_addr, (void *)(bt_entry_v.data()), size * 2, error);
240 if ((ret != (size * 2)) || !error.Success()) {
241 result.SetError("Failed access to BT entry.");
242 result.SetStatus(lldb::eReturnStatusFailed);
243 return false;
244 }
245
246 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
247 return true;
248}
249
250static bool GetInitInfo(lldb::SBDebugger debugger, lldb::SBTarget &target,
251 llvm::Triple::ArchType &arch, uint64_t &bndcfgu,
252 char *arg, uint64_t &ptr,
253 lldb::SBCommandReturnObject &result,
254 lldb::SBError &error) {
255 target = debugger.GetSelectedTarget();
256 if (!target.IsValid()) {
257 result.SetError("Invalid target.");
258 result.SetStatus(lldb::eReturnStatusFailed);
259 return false;
260 }
261
262 const std::string triple_s(target.GetTriple());
263 const llvm::Triple triple(triple_s);
264
265 arch = triple.getArch();
266
267 if ((arch != llvm::Triple::ArchType::x86) &&
268 (arch != llvm::Triple::ArchType::x86_64)) {
269 result.SetError("Platform not supported.");
270 result.SetStatus(lldb::eReturnStatusFailed);
271 return false;
272 }
273
274 lldb::SBFrame frame =
275 target.GetProcess().GetSelectedThread().GetSelectedFrame();
276 if (!frame.IsValid()) {
277 result.SetError("No valid process, thread or frame.");
278 result.SetStatus(lldb::eReturnStatusFailed);
279 return false;
280 }
281
282 lldb::SBValue bndcfgu_val = frame.FindRegister("bndcfgu");
283 if (!bndcfgu_val.IsValid()) {
284 result.SetError("Cannot access register BNDCFGU. Does the target support "
285 "Intel(R) Memory Protection Extensions (Intel(R) MPX)?");
286 result.SetStatus(lldb::eReturnStatusFailed);
287 return false;
288 }
289
290 lldb::SBData bndcfgu_data = bndcfgu_val.GetData();
291 bndcfgu = bndcfgu_data.GetUnsignedInt64(error, 0);
292 if (!error.Success()) {
293 result.SetError(error, "Invalid read of register BNDCFGU.");
294 return false;
295 }
296
297 if (!GetPtr(arg, ptr, frame, result))
298 return false;
299
300 return true;
301}
302
303class MPXTableShow : public lldb::SBCommandPluginInterface {
304public:
305 bool DoExecute(lldb::SBDebugger debugger, char **command,
306 lldb::SBCommandReturnObject &result) override {
307
308 if (command) {
1
Assuming 'command' is non-null
2
Taking true branch
309 int arg_c = 0;
310 char *arg;
3
'arg' declared without an initial value
311
312 while (*command) {
4
Loop condition is false. Execution continues on line 323
313 if (arg_c >= 1) {
314 result.SetError("Too many arguments. See help.");
315 result.SetStatus(lldb::eReturnStatusFailed);
316 return false;
317 }
318 arg_c++;
319 arg = *command;
320 command++;
321 }
322
323 if (!debugger.IsValid()) {
5
Assuming the condition is false
6
Taking false branch
324 result.SetError("Invalid debugger.");
325 result.SetStatus(lldb::eReturnStatusFailed);
326 return false;
327 }
328
329 lldb::SBTarget target;
330 llvm::Triple::ArchType arch;
331 lldb::SBError error;
332 uint64_t bndcfgu;
333 uint64_t ptr;
334
335 if (!GetInitInfo(debugger, target, arch, bndcfgu, arg, ptr, result,
7
5th function call argument is an uninitialized value
336 error))
337 return false;
338
339 return GetBTEntry(bndcfgu, ptr, target, arch, result, error);
340 }
341
342 result.SetError("Too few arguments. See help.");
343 result.SetStatus(lldb::eReturnStatusFailed);
344 return false;
345 }
346};
347
348class MPXTableSet : public lldb::SBCommandPluginInterface {
349public:
350 bool DoExecute(lldb::SBDebugger debugger, char **command,
351 lldb::SBCommandReturnObject &result) override {
352
353 if (command) {
354 int arg_c = 0;
355 char *arg[3];
356
357 while (*command) {
358 arg[arg_c] = *command;
359 command++;
360 arg_c++;
361 }
362
363 if (arg_c != 3) {
364 result.SetError("Wrong arguments. See help.");
365 return false;
366 }
367
368 if (!debugger.IsValid()) {
369 result.SetError("Invalid debugger.");
370 return false;
371 }
372
373 lldb::SBTarget target;
374 llvm::Triple::ArchType arch;
375 lldb::SBError error;
376 uint64_t bndcfgu;
377 uint64_t ptr;
378
379 if (!GetInitInfo(debugger, target, arch, bndcfgu, arg[0], ptr, result,
380 error))
381 return false;
382
383 char *endptr;
384 errno(*__errno_location ()) = 0;
385 uint64_t lbound = std::strtoul(arg[1], &endptr, 16);
386 if (endptr == arg[1] || errno(*__errno_location ()) == ERANGE34) {
387 result.SetError("Lower Bound: bad argument format.");
388 errno(*__errno_location ()) = 0;
389 return false;
390 }
391
392 uint64_t ubound = std::strtoul(arg[2], &endptr, 16);
393 if (endptr == arg[1] || errno(*__errno_location ()) == ERANGE34) {
394 result.SetError("Upper Bound: bad argument format.");
395 errno(*__errno_location ()) = 0;
396 return false;
397 }
398
399 return SetBTEntry(bndcfgu, ptr, lbound, ubound, target, arch, result,
400 error);
401 }
402
403 result.SetError("Too few arguments. See help.");
404 return false;
405 }
406};
407
408bool MPXPluginInitialize(lldb::SBDebugger &debugger) {
409 lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
410 lldb::SBCommand mpxTable = interpreter.AddMultiwordCommand(
411 "mpx-table", "A utility to access the Intel(R) MPX table entries.");
412
413 const char *mpx_show_help = "Show the Intel(R) MPX table entry of a pointer."
414 "\nmpx-table show <pointer>";
415 mpxTable.AddCommand("show", new MPXTableShow(), mpx_show_help);
416
417 const char *mpx_set_help =
418 "Set the Intel(R) MPX table entry of a pointer.\n"
419 "mpx-table set <pointer> <lower bound> <upper bound>";
420 mpxTable.AddCommand("set", new MPXTableSet(), mpx_set_help);
421
422 return true;
423}