gfx/angle/src/compiler/DetectCallDepth.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 //
michael@0 2 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
michael@0 3 // Use of this source code is governed by a BSD-style license that can be
michael@0 4 // found in the LICENSE file.
michael@0 5 //
michael@0 6
michael@0 7 #include "compiler/DetectCallDepth.h"
michael@0 8 #include "compiler/InfoSink.h"
michael@0 9
michael@0 10 DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
michael@0 11 : name(fname),
michael@0 12 visit(PreVisit)
michael@0 13 {
michael@0 14 }
michael@0 15
michael@0 16 const TString& DetectCallDepth::FunctionNode::getName() const
michael@0 17 {
michael@0 18 return name;
michael@0 19 }
michael@0 20
michael@0 21 void DetectCallDepth::FunctionNode::addCallee(
michael@0 22 DetectCallDepth::FunctionNode* callee)
michael@0 23 {
michael@0 24 for (size_t i = 0; i < callees.size(); ++i) {
michael@0 25 if (callees[i] == callee)
michael@0 26 return;
michael@0 27 }
michael@0 28 callees.push_back(callee);
michael@0 29 }
michael@0 30
michael@0 31 int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
michael@0 32 {
michael@0 33 ASSERT(visit == PreVisit);
michael@0 34 ASSERT(detectCallDepth);
michael@0 35
michael@0 36 int maxDepth = depth;
michael@0 37 visit = InVisit;
michael@0 38 for (size_t i = 0; i < callees.size(); ++i) {
michael@0 39 switch (callees[i]->visit) {
michael@0 40 case InVisit:
michael@0 41 // cycle detected, i.e., recursion detected.
michael@0 42 return kInfiniteCallDepth;
michael@0 43 case PostVisit:
michael@0 44 break;
michael@0 45 case PreVisit: {
michael@0 46 // Check before we recurse so we don't go too depth
michael@0 47 if (detectCallDepth->checkExceedsMaxDepth(depth))
michael@0 48 return depth;
michael@0 49 int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
michael@0 50 // Check after we recurse so we can exit immediately and provide info.
michael@0 51 if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
michael@0 52 detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
michael@0 53 return callDepth;
michael@0 54 }
michael@0 55 maxDepth = std::max(callDepth, maxDepth);
michael@0 56 break;
michael@0 57 }
michael@0 58 default:
michael@0 59 UNREACHABLE();
michael@0 60 break;
michael@0 61 }
michael@0 62 }
michael@0 63 visit = PostVisit;
michael@0 64 return maxDepth;
michael@0 65 }
michael@0 66
michael@0 67 void DetectCallDepth::FunctionNode::reset()
michael@0 68 {
michael@0 69 visit = PreVisit;
michael@0 70 }
michael@0 71
michael@0 72 DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
michael@0 73 : TIntermTraverser(true, false, true, false),
michael@0 74 currentFunction(NULL),
michael@0 75 infoSink(infoSink),
michael@0 76 maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
michael@0 77 {
michael@0 78 }
michael@0 79
michael@0 80 DetectCallDepth::~DetectCallDepth()
michael@0 81 {
michael@0 82 for (size_t i = 0; i < functions.size(); ++i)
michael@0 83 delete functions[i];
michael@0 84 }
michael@0 85
michael@0 86 bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
michael@0 87 {
michael@0 88 switch (node->getOp())
michael@0 89 {
michael@0 90 case EOpPrototype:
michael@0 91 // Function declaration.
michael@0 92 // Don't add FunctionNode here because node->getName() is the
michael@0 93 // unmangled function name.
michael@0 94 break;
michael@0 95 case EOpFunction: {
michael@0 96 // Function definition.
michael@0 97 if (visit == PreVisit) {
michael@0 98 currentFunction = findFunctionByName(node->getName());
michael@0 99 if (currentFunction == NULL) {
michael@0 100 currentFunction = new FunctionNode(node->getName());
michael@0 101 functions.push_back(currentFunction);
michael@0 102 }
michael@0 103 } else if (visit == PostVisit) {
michael@0 104 currentFunction = NULL;
michael@0 105 }
michael@0 106 break;
michael@0 107 }
michael@0 108 case EOpFunctionCall: {
michael@0 109 // Function call.
michael@0 110 if (visit == PreVisit) {
michael@0 111 FunctionNode* func = findFunctionByName(node->getName());
michael@0 112 if (func == NULL) {
michael@0 113 func = new FunctionNode(node->getName());
michael@0 114 functions.push_back(func);
michael@0 115 }
michael@0 116 if (currentFunction)
michael@0 117 currentFunction->addCallee(func);
michael@0 118 }
michael@0 119 break;
michael@0 120 }
michael@0 121 default:
michael@0 122 break;
michael@0 123 }
michael@0 124 return true;
michael@0 125 }
michael@0 126
michael@0 127 bool DetectCallDepth::checkExceedsMaxDepth(int depth)
michael@0 128 {
michael@0 129 return depth >= maxDepth;
michael@0 130 }
michael@0 131
michael@0 132 void DetectCallDepth::resetFunctionNodes()
michael@0 133 {
michael@0 134 for (size_t i = 0; i < functions.size(); ++i) {
michael@0 135 functions[i]->reset();
michael@0 136 }
michael@0 137 }
michael@0 138
michael@0 139 DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
michael@0 140 {
michael@0 141 currentFunction = NULL;
michael@0 142 resetFunctionNodes();
michael@0 143
michael@0 144 int maxCallDepth = func->detectCallDepth(this, 1);
michael@0 145
michael@0 146 if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
michael@0 147 return kErrorRecursion;
michael@0 148
michael@0 149 if (maxCallDepth >= maxDepth)
michael@0 150 return kErrorMaxDepthExceeded;
michael@0 151
michael@0 152 return kErrorNone;
michael@0 153 }
michael@0 154
michael@0 155 DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
michael@0 156 {
michael@0 157 if (maxDepth != FunctionNode::kInfiniteCallDepth) {
michael@0 158 // Check all functions because the driver may fail on them
michael@0 159 // TODO: Before detectingRecursion, strip unused functions.
michael@0 160 for (size_t i = 0; i < functions.size(); ++i) {
michael@0 161 ErrorCode error = detectCallDepthForFunction(functions[i]);
michael@0 162 if (error != kErrorNone)
michael@0 163 return error;
michael@0 164 }
michael@0 165 } else {
michael@0 166 FunctionNode* main = findFunctionByName("main(");
michael@0 167 if (main == NULL)
michael@0 168 return kErrorMissingMain;
michael@0 169
michael@0 170 return detectCallDepthForFunction(main);
michael@0 171 }
michael@0 172
michael@0 173 return kErrorNone;
michael@0 174 }
michael@0 175
michael@0 176 DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
michael@0 177 const TString& name)
michael@0 178 {
michael@0 179 for (size_t i = 0; i < functions.size(); ++i) {
michael@0 180 if (functions[i]->getName() == name)
michael@0 181 return functions[i];
michael@0 182 }
michael@0 183 return NULL;
michael@0 184 }
michael@0 185

mercurial