Bug Summary

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