Bug Summary

File:tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp
Warning:line 224, column 10
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MinidumpTypes.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -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 -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/source/Plugins/Process/minidump -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp -faddrsig
1//===-- MinidumpTypes.cpp ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Project includes
11#include "MinidumpTypes.h"
12
13// Other libraries and framework includes
14// C includes
15// C++ includes
16
17using namespace lldb_private;
18using namespace minidump;
19
20const MinidumpHeader *MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) {
21 const MinidumpHeader *header = nullptr;
22 Status error = consumeObject(data, header);
23
24 const MinidumpHeaderConstants signature =
25 static_cast<const MinidumpHeaderConstants>(
26 static_cast<const uint32_t>(header->signature));
27 const MinidumpHeaderConstants version =
28 static_cast<const MinidumpHeaderConstants>(
29 static_cast<const uint32_t>(header->version) & 0x0000ffff);
30 // the high 16 bits of the version field are implementation specific
31
32 if (error.Fail() || signature != MinidumpHeaderConstants::Signature ||
33 version != MinidumpHeaderConstants::Version)
34 return nullptr;
35
36 return header;
37}
38
39// Minidump string
40llvm::Optional<std::string>
41lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
42 std::string result;
43
44 const uint32_t *source_length_ptr;
45 Status error = consumeObject(data, source_length_ptr);
46
47 // Copy non-aligned source_length data into aligned memory.
48 uint32_t source_length;
49 std::memcpy(&source_length, source_length_ptr, sizeof(source_length));
50
51 if (error.Fail() || source_length > data.size() || source_length % 2 != 0)
52 return llvm::None;
53
54 auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data());
55 // source_length is the length of the string in bytes we need the length of
56 // the string in UTF-16 characters/code points (16 bits per char) that's why
57 // it's divided by 2
58 const auto source_end = source_start + source_length / 2;
59 // resize to worst case length
60 result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT4 * source_length / 2);
61 auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]);
62 const auto result_end = result_start + result.size();
63 llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
64 llvm::strictConversion);
65 const auto result_size =
66 std::distance(reinterpret_cast<llvm::UTF8 *>(&result[0]), result_start);
67 result.resize(result_size); // shrink to actual length
68
69 return result;
70}
71
72// MinidumpThread
73const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
74 const MinidumpThread *thread = nullptr;
75 Status error = consumeObject(data, thread);
76 if (error.Fail())
77 return nullptr;
78
79 return thread;
80}
81
82llvm::ArrayRef<MinidumpThread>
83MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
84 const auto orig_size = data.size();
85 const llvm::support::ulittle32_t *thread_count;
86 Status error = consumeObject(data, thread_count);
87 if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
88 return {};
89
90 // Compilers might end up padding an extra 4 bytes depending on how the
91 // structure is padded by the compiler and the #pragma pack settings.
92 if (4 + *thread_count * sizeof(MinidumpThread) < orig_size)
93 data = data.drop_front(4);
94
95 return llvm::ArrayRef<MinidumpThread>(
96 reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
97}
98
99// MinidumpSystemInfo
100const MinidumpSystemInfo *
101MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &data) {
102 const MinidumpSystemInfo *system_info;
103 Status error = consumeObject(data, system_info);
104 if (error.Fail())
105 return nullptr;
106
107 return system_info;
108}
109
110// MinidumpMiscInfo
111const MinidumpMiscInfo *MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) {
112 const MinidumpMiscInfo *misc_info;
113 Status error = consumeObject(data, misc_info);
114 if (error.Fail())
115 return nullptr;
116
117 return misc_info;
118}
119
120llvm::Optional<lldb::pid_t> MinidumpMiscInfo::GetPid() const {
121 uint32_t pid_flag =
122 static_cast<const uint32_t>(MinidumpMiscInfoFlags::ProcessID);
123 if (flags1 & pid_flag)
124 return llvm::Optional<lldb::pid_t>(process_id);
125
126 return llvm::None;
127}
128
129// Linux Proc Status
130// it's stored as an ascii string in the file
131llvm::Optional<LinuxProcStatus>
132LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) {
133 LinuxProcStatus result;
134 result.proc_status =
135 llvm::StringRef(reinterpret_cast<const char *>(data.data()), data.size());
136 data = data.drop_front(data.size());
137
138 llvm::SmallVector<llvm::StringRef, 0> lines;
139 result.proc_status.split(lines, '\n', 42);
140 // /proc/$pid/status has 41 lines, but why not use 42?
141 for (auto line : lines) {
142 if (line.consume_front("Pid:")) {
143 line = line.trim();
144 if (!line.getAsInteger(10, result.pid))
145 return result;
146 }
147 }
148
149 return llvm::None;
150}
151
152lldb::pid_t LinuxProcStatus::GetPid() const { return pid; }
153
154// Module stuff
155const MinidumpModule *MinidumpModule::Parse(llvm::ArrayRef<uint8_t> &data) {
156 const MinidumpModule *module = nullptr;
157 Status error = consumeObject(data, module);
158 if (error.Fail())
159 return nullptr;
160
161 return module;
162}
163
164llvm::ArrayRef<MinidumpModule>
165MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) {
166 const auto orig_size = data.size();
167 const llvm::support::ulittle32_t *modules_count;
168 Status error = consumeObject(data, modules_count);
169 if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size())
170 return {};
171
172 // Compilers might end up padding an extra 4 bytes depending on how the
173 // structure is padded by the compiler and the #pragma pack settings.
174 if (4 + *modules_count * sizeof(MinidumpModule) < orig_size)
175 data = data.drop_front(4);
176
177 return llvm::ArrayRef<MinidumpModule>(
178 reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count);
179}
180
181// Exception stuff
182const MinidumpExceptionStream *
183MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) {
184 const MinidumpExceptionStream *exception_stream = nullptr;
185 Status error = consumeObject(data, exception_stream);
186 if (error.Fail())
187 return nullptr;
188
189 return exception_stream;
190}
191
192llvm::ArrayRef<MinidumpMemoryDescriptor>
193MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
194 const auto orig_size = data.size();
195 const llvm::support::ulittle32_t *mem_ranges_count;
196 Status error = consumeObject(data, mem_ranges_count);
197 if (error.Fail() ||
198 *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
199 return {};
200
201 // Compilers might end up padding an extra 4 bytes depending on how the
202 // structure is padded by the compiler and the #pragma pack settings.
203 if (4 + *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) < orig_size)
204 data = data.drop_front(4);
205
206 return llvm::makeArrayRef(
207 reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
208 *mem_ranges_count);
209}
210
211std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t>
212MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) {
213 const llvm::support::ulittle64_t *mem_ranges_count;
214 Status error = consumeObject(data, mem_ranges_count);
215 if (error.Fail() ||
1
Assuming the condition is false
3
Taking false branch
216 *mem_ranges_count * sizeof(MinidumpMemoryDescriptor64) > data.size())
2
Assuming the condition is false
217 return {};
218
219 const llvm::support::ulittle64_t *base_rva;
220 error = consumeObject(data, base_rva);
221 if (error.Fail())
4
Assuming the condition is false
5
Taking false branch
222 return {};
223
224 return std::make_pair(
6
2nd function call argument is an uninitialized value
225 llvm::makeArrayRef(
226 reinterpret_cast<const MinidumpMemoryDescriptor64 *>(data.data()),
227 *mem_ranges_count),
228 *base_rva);
229}
230
231std::vector<const MinidumpMemoryInfo *>
232MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) {
233 const MinidumpMemoryInfoListHeader *header;
234 Status error = consumeObject(data, header);
235 if (error.Fail() ||
236 header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) ||
237 header->size_of_entry < sizeof(MinidumpMemoryInfo))
238 return {};
239
240 data = data.drop_front(header->size_of_header -
241 sizeof(MinidumpMemoryInfoListHeader));
242
243 if (header->size_of_entry * header->num_of_entries > data.size())
244 return {};
245
246 std::vector<const MinidumpMemoryInfo *> result;
247 for (uint64_t i = 0; i < header->num_of_entries; ++i) {
248 result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>(
249 data.data() + i * header->size_of_entry));
250 }
251
252 return result;
253}