Bug Summary

File:lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
Warning:line 169, column 9
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 MipsNaClELFStreamer.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 _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/Mips/MCTargetDesc -I /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips/MCTargetDesc -I /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/Mips -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/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/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-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/lib/Target/Mips/MCTargetDesc -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
1//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===//
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// This file implements MCELFStreamer for Mips NaCl. It emits .o object files
11// as required by NaCl's SFI sandbox. It inserts address-masking instructions
12// before dangerous control-flow and memory access instructions. It inserts
13// address-masking instructions after instructions that change the stack
14// pointer. It ensures that the mask and the dangerous instruction are always
15// emitted in the same bundle. It aligns call + branch delay to the bundle end,
16// so that return address is always aligned to the start of next bundle.
17//
18//===----------------------------------------------------------------------===//
19
20#include "Mips.h"
21#include "MipsELFStreamer.h"
22#include "MipsMCNaCl.h"
23#include "llvm/MC/MCAsmBackend.h"
24#include "llvm/MC/MCAssembler.h"
25#include "llvm/MC/MCCodeEmitter.h"
26#include "llvm/MC/MCELFStreamer.h"
27#include "llvm/MC/MCInst.h"
28#include "llvm/Support/ErrorHandling.h"
29#include <cassert>
30
31using namespace llvm;
32
33#define DEBUG_TYPE"mips-mc-nacl" "mips-mc-nacl"
34
35namespace {
36
37const unsigned IndirectBranchMaskReg = Mips::T6;
38const unsigned LoadStoreStackMaskReg = Mips::T7;
39
40/// Extend the generic MCELFStreamer class so that it can mask dangerous
41/// instructions.
42
43class MipsNaClELFStreamer : public MipsELFStreamer {
44public:
45 MipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
46 raw_pwrite_stream &OS,
47 std::unique_ptr<MCCodeEmitter> Emitter)
48 : MipsELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)) {}
49
50 ~MipsNaClELFStreamer() override = default;
51
52private:
53 // Whether we started the sandboxing sequence for calls. Calls are bundled
54 // with branch delays and aligned to the bundle end.
55 bool PendingCall = false;
56
57 bool isIndirectJump(const MCInst &MI) {
58 if (MI.getOpcode() == Mips::JALR) {
59 // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead.
60 // JALR is an indirect branch if the link register is $0.
61 assert(MI.getOperand(0).isReg())(static_cast <bool> (MI.getOperand(0).isReg()) ? void (
0) : __assert_fail ("MI.getOperand(0).isReg()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp"
, 61, __extension__ __PRETTY_FUNCTION__))
;
62 return MI.getOperand(0).getReg() == Mips::ZERO;
63 }
64 return MI.getOpcode() == Mips::JR;
65 }
66
67 bool isStackPointerFirstOperand(const MCInst &MI) {
68 return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg()
69 && MI.getOperand(0).getReg() == Mips::SP);
70 }
71
72 bool isCall(const MCInst &MI, bool *IsIndirectCall) {
73 unsigned Opcode = MI.getOpcode();
74
75 *IsIndirectCall = false;
76
77 switch (Opcode) {
78 default:
79 return false;
80
81 case Mips::JAL:
82 case Mips::BAL:
83 case Mips::BAL_BR:
84 case Mips::BLTZAL:
85 case Mips::BGEZAL:
86 return true;
87
88 case Mips::JALR:
89 // JALR is only a call if the link register is not $0. Otherwise it's an
90 // indirect branch.
91 assert(MI.getOperand(0).isReg())(static_cast <bool> (MI.getOperand(0).isReg()) ? void (
0) : __assert_fail ("MI.getOperand(0).isReg()", "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp"
, 91, __extension__ __PRETTY_FUNCTION__))
;
92 if (MI.getOperand(0).getReg() == Mips::ZERO)
93 return false;
94
95 *IsIndirectCall = true;
96 return true;
97 }
98 }
99
100 void emitMask(unsigned AddrReg, unsigned MaskReg,
101 const MCSubtargetInfo &STI) {
102 MCInst MaskInst;
103 MaskInst.setOpcode(Mips::AND);
104 MaskInst.addOperand(MCOperand::createReg(AddrReg));
105 MaskInst.addOperand(MCOperand::createReg(AddrReg));
106 MaskInst.addOperand(MCOperand::createReg(MaskReg));
107 MipsELFStreamer::EmitInstruction(MaskInst, STI);
108 }
109
110 // Sandbox indirect branch or return instruction by inserting mask operation
111 // before it.
112 void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) {
113 unsigned AddrReg = MI.getOperand(0).getReg();
114
115 EmitBundleLock(false);
116 emitMask(AddrReg, IndirectBranchMaskReg, STI);
117 MipsELFStreamer::EmitInstruction(MI, STI);
118 EmitBundleUnlock();
119 }
120
121 // Sandbox memory access or SP change. Insert mask operation before and/or
122 // after the instruction.
123 void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx,
124 const MCSubtargetInfo &STI, bool MaskBefore,
125 bool MaskAfter) {
126 EmitBundleLock(false);
127 if (MaskBefore) {
128 // Sandbox memory access.
129 unsigned BaseReg = MI.getOperand(AddrIdx).getReg();
130 emitMask(BaseReg, LoadStoreStackMaskReg, STI);
131 }
132 MipsELFStreamer::EmitInstruction(MI, STI);
133 if (MaskAfter) {
134 // Sandbox SP change.
135 unsigned SPReg = MI.getOperand(0).getReg();
136 assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.")(static_cast <bool> ((Mips::SP == SPReg) && "Unexpected stack-pointer register."
) ? void (0) : __assert_fail ("(Mips::SP == SPReg) && \"Unexpected stack-pointer register.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp"
, 136, __extension__ __PRETTY_FUNCTION__))
;
137 emitMask(SPReg, LoadStoreStackMaskReg, STI);
138 }
139 EmitBundleUnlock();
140 }
141
142public:
143 /// This function is the one used to emit instruction data into the ELF
144 /// streamer. We override it to mask dangerous instructions.
145 void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
146 bool) override {
147 // Sandbox indirect jumps.
148 if (isIndirectJump(Inst)) {
1
Taking false branch
149 if (PendingCall)
150 report_fatal_error("Dangerous instruction in branch delay slot!");
151 sandboxIndirectJump(Inst, STI);
152 return;
153 }
154
155 // Sandbox loads, stores and SP changes.
156 unsigned AddrIdx;
2
'AddrIdx' declared without an initial value
157 bool IsStore;
158 bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx,
3
Calling 'isBasePlusOffsetMemoryAccess'
7
Returning from 'isBasePlusOffsetMemoryAccess'
159 &IsStore);
160 bool IsSPFirstOperand = isStackPointerFirstOperand(Inst);
161 if (IsMemAccess || IsSPFirstOperand) {
8
Assuming 'IsSPFirstOperand' is not equal to 0
9
Taking true branch
162 bool MaskBefore = (IsMemAccess
163 && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx)
164 .getReg()));
165 bool MaskAfter = IsSPFirstOperand && !IsStore;
166 if (MaskBefore || MaskAfter) {
10
Taking true branch
167 if (PendingCall)
11
Assuming the condition is false
12
Taking false branch
168 report_fatal_error("Dangerous instruction in branch delay slot!");
169 sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter);
13
2nd function call argument is an uninitialized value
170 return;
171 }
172 // fallthrough
173 }
174
175 // Sandbox calls by aligning call and branch delay to the bundle end.
176 // For indirect calls, emit the mask before the call.
177 bool IsIndirectCall;
178 if (isCall(Inst, &IsIndirectCall)) {
179 if (PendingCall)
180 report_fatal_error("Dangerous instruction in branch delay slot!");
181
182 // Start the sandboxing sequence by emitting call.
183 EmitBundleLock(true);
184 if (IsIndirectCall) {
185 unsigned TargetReg = Inst.getOperand(1).getReg();
186 emitMask(TargetReg, IndirectBranchMaskReg, STI);
187 }
188 MipsELFStreamer::EmitInstruction(Inst, STI);
189 PendingCall = true;
190 return;
191 }
192 if (PendingCall) {
193 // Finish the sandboxing sequence by emitting branch delay.
194 MipsELFStreamer::EmitInstruction(Inst, STI);
195 EmitBundleUnlock();
196 PendingCall = false;
197 return;
198 }
199
200 // None of the sandboxing applies, just emit the instruction.
201 MipsELFStreamer::EmitInstruction(Inst, STI);
202 }
203};
204
205} // end anonymous namespace
206
207namespace llvm {
208
209bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
210 bool *IsStore) {
211 if (IsStore)
4
Taking true branch
212 *IsStore = false;
213
214 switch (Opcode) {
5
Control jumps to the 'default' case at line 215
215 default:
216 return false;
6
Returning without writing to '*AddrIdx'
217
218 // Load instructions with base address register in position 1.
219 case Mips::LB:
220 case Mips::LBu:
221 case Mips::LH:
222 case Mips::LHu:
223 case Mips::LW:
224 case Mips::LWC1:
225 case Mips::LDC1:
226 case Mips::LL:
227 case Mips::LL_R6:
228 case Mips::LWL:
229 case Mips::LWR:
230 *AddrIdx = 1;
231 return true;
232
233 // Store instructions with base address register in position 1.
234 case Mips::SB:
235 case Mips::SH:
236 case Mips::SW:
237 case Mips::SWC1:
238 case Mips::SDC1:
239 case Mips::SWL:
240 case Mips::SWR:
241 *AddrIdx = 1;
242 if (IsStore)
243 *IsStore = true;
244 return true;
245
246 // Store instructions with base address register in position 2.
247 case Mips::SC:
248 case Mips::SC_R6:
249 *AddrIdx = 2;
250 if (IsStore)
251 *IsStore = true;
252 return true;
253 }
254}
255
256bool baseRegNeedsLoadStoreMask(unsigned Reg) {
257 // The contents of SP and thread pointer register do not require masking.
258 return Reg != Mips::SP && Reg != Mips::T8;
259}
260
261MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context,
262 std::unique_ptr<MCAsmBackend> TAB,
263 raw_pwrite_stream &OS,
264 std::unique_ptr<MCCodeEmitter> Emitter,
265 bool RelaxAll) {
266 MipsNaClELFStreamer *S =
267 new MipsNaClELFStreamer(Context, std::move(TAB), OS, std::move(Emitter));
268 if (RelaxAll)
269 S->getAssembler().setRelaxAll(true);
270
271 // Set bundle-alignment as required by the NaCl ABI for the target.
272 S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN);
273
274 return S;
275}
276
277} // end namespace llvm