Bug Summary

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