Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #include "sandbox/win/src/policy_engine_opcodes.h" |
michael@0 | 6 | |
michael@0 | 7 | #include "base/basictypes.h" |
michael@0 | 8 | #include "sandbox/win/src/sandbox_nt_types.h" |
michael@0 | 9 | #include "sandbox/win/src/sandbox_types.h" |
michael@0 | 10 | |
michael@0 | 11 | namespace { |
michael@0 | 12 | const unsigned short kMaxUniStrSize = 0xfffc; |
michael@0 | 13 | |
michael@0 | 14 | bool InitStringUnicode(const wchar_t* source, size_t length, |
michael@0 | 15 | UNICODE_STRING* ustring) { |
michael@0 | 16 | ustring->Buffer = const_cast<wchar_t*>(source); |
michael@0 | 17 | ustring->Length = static_cast<USHORT>(length) * sizeof(wchar_t); |
michael@0 | 18 | if (length > kMaxUniStrSize) { |
michael@0 | 19 | return false; |
michael@0 | 20 | } |
michael@0 | 21 | ustring->MaximumLength = (NULL != source) ? |
michael@0 | 22 | ustring->Length + sizeof(wchar_t) : 0; |
michael@0 | 23 | return true; |
michael@0 | 24 | } |
michael@0 | 25 | |
michael@0 | 26 | } // namespace |
michael@0 | 27 | |
michael@0 | 28 | namespace sandbox { |
michael@0 | 29 | |
michael@0 | 30 | SANDBOX_INTERCEPT NtExports g_nt; |
michael@0 | 31 | |
michael@0 | 32 | // Note: The opcodes are implemented as functions (as opposed to classes derived |
michael@0 | 33 | // from PolicyOpcode) because you should not add more member variables to the |
michael@0 | 34 | // PolicyOpcode class since it would cause object slicing on the target. So to |
michael@0 | 35 | // enforce that (instead of just trusting the developer) the opcodes became |
michael@0 | 36 | // just functions. |
michael@0 | 37 | // |
michael@0 | 38 | // In the code that follows I have keep the evaluation function and the factory |
michael@0 | 39 | // function together to stress the close relationship between both. For example, |
michael@0 | 40 | // only the factory method and the evaluation function know the stored argument |
michael@0 | 41 | // order and meaning. |
michael@0 | 42 | |
michael@0 | 43 | template <int> |
michael@0 | 44 | EvalResult OpcodeEval(PolicyOpcode* opcode, const ParameterSet* pp, |
michael@0 | 45 | MatchContext* match); |
michael@0 | 46 | |
michael@0 | 47 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 48 | // Opcode OpAlwaysFalse: |
michael@0 | 49 | // Does not require input parameter. |
michael@0 | 50 | |
michael@0 | 51 | PolicyOpcode* OpcodeFactory::MakeOpAlwaysFalse(uint32 options) { |
michael@0 | 52 | return MakeBase(OP_ALWAYS_FALSE, options, -1); |
michael@0 | 53 | } |
michael@0 | 54 | |
michael@0 | 55 | template <> |
michael@0 | 56 | EvalResult OpcodeEval<OP_ALWAYS_FALSE>(PolicyOpcode* opcode, |
michael@0 | 57 | const ParameterSet* param, |
michael@0 | 58 | MatchContext* context) { |
michael@0 | 59 | UNREFERENCED_PARAMETER(opcode); |
michael@0 | 60 | UNREFERENCED_PARAMETER(param); |
michael@0 | 61 | UNREFERENCED_PARAMETER(context); |
michael@0 | 62 | return EVAL_FALSE; |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 66 | // Opcode OpAlwaysTrue: |
michael@0 | 67 | // Does not require input parameter. |
michael@0 | 68 | |
michael@0 | 69 | PolicyOpcode* OpcodeFactory::MakeOpAlwaysTrue(uint32 options) { |
michael@0 | 70 | return MakeBase(OP_ALWAYS_TRUE, options, -1); |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | template <> |
michael@0 | 74 | EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode, |
michael@0 | 75 | const ParameterSet* param, |
michael@0 | 76 | MatchContext* context) { |
michael@0 | 77 | UNREFERENCED_PARAMETER(opcode); |
michael@0 | 78 | UNREFERENCED_PARAMETER(param); |
michael@0 | 79 | UNREFERENCED_PARAMETER(context); |
michael@0 | 80 | return EVAL_TRUE; |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 84 | // Opcode OpAction: |
michael@0 | 85 | // Does not require input parameter. |
michael@0 | 86 | // Argument 0 contains the actual action to return. |
michael@0 | 87 | |
michael@0 | 88 | PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, |
michael@0 | 89 | uint32 options) { |
michael@0 | 90 | PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0); |
michael@0 | 91 | if (NULL == opcode) return NULL; |
michael@0 | 92 | opcode->SetArgument(0, action); |
michael@0 | 93 | return opcode; |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | template <> |
michael@0 | 97 | EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode, |
michael@0 | 98 | const ParameterSet* param, |
michael@0 | 99 | MatchContext* context) { |
michael@0 | 100 | UNREFERENCED_PARAMETER(param); |
michael@0 | 101 | UNREFERENCED_PARAMETER(context); |
michael@0 | 102 | int action = 0; |
michael@0 | 103 | opcode->GetArgument(0, &action); |
michael@0 | 104 | return static_cast<EvalResult>(action); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 108 | // Opcode OpNumberMatch: |
michael@0 | 109 | // Requires a unsigned long or void* in selected_param |
michael@0 | 110 | // Argument 0 is the stored number to match. |
michael@0 | 111 | // Argument 1 is the C++ type of the 0th argument. |
michael@0 | 112 | |
michael@0 | 113 | PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(int16 selected_param, |
michael@0 | 114 | unsigned long match, |
michael@0 | 115 | uint32 options) { |
michael@0 | 116 | PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); |
michael@0 | 117 | if (NULL == opcode) return NULL; |
michael@0 | 118 | opcode->SetArgument(0, match); |
michael@0 | 119 | opcode->SetArgument(1, ULONG_TYPE); |
michael@0 | 120 | return opcode; |
michael@0 | 121 | } |
michael@0 | 122 | |
michael@0 | 123 | PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(int16 selected_param, |
michael@0 | 124 | const void* match, |
michael@0 | 125 | uint32 options) { |
michael@0 | 126 | PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); |
michael@0 | 127 | if (NULL == opcode) return NULL; |
michael@0 | 128 | opcode->SetArgument(0, match); |
michael@0 | 129 | opcode->SetArgument(1, VOIDPTR_TYPE); |
michael@0 | 130 | return opcode; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | template <> |
michael@0 | 134 | EvalResult OpcodeEval<OP_NUMBER_MATCH>(PolicyOpcode* opcode, |
michael@0 | 135 | const ParameterSet* param, |
michael@0 | 136 | MatchContext* context) { |
michael@0 | 137 | UNREFERENCED_PARAMETER(context); |
michael@0 | 138 | unsigned long value_ulong = 0; |
michael@0 | 139 | if (param->Get(&value_ulong)) { |
michael@0 | 140 | unsigned long match_ulong = 0; |
michael@0 | 141 | opcode->GetArgument(0, &match_ulong); |
michael@0 | 142 | return (match_ulong != value_ulong)? EVAL_FALSE : EVAL_TRUE; |
michael@0 | 143 | } else { |
michael@0 | 144 | const void* value_ptr = NULL; |
michael@0 | 145 | if (param->Get(&value_ptr)) { |
michael@0 | 146 | const void* match_ptr = NULL; |
michael@0 | 147 | opcode->GetArgument(0, &match_ptr); |
michael@0 | 148 | return (match_ptr != value_ptr)? EVAL_FALSE : EVAL_TRUE; |
michael@0 | 149 | } |
michael@0 | 150 | } |
michael@0 | 151 | return EVAL_ERROR; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 155 | // Opcode OpUlongMatchRange |
michael@0 | 156 | // Requires a unsigned long in selected_param. |
michael@0 | 157 | // Argument 0 is the stored lower bound to match. |
michael@0 | 158 | // Argument 1 is the stored upper bound to match. |
michael@0 | 159 | |
michael@0 | 160 | PolicyOpcode* OpcodeFactory::MakeOpUlongMatchRange(int16 selected_param, |
michael@0 | 161 | unsigned long lower_bound, |
michael@0 | 162 | unsigned long upper_bound, |
michael@0 | 163 | uint32 options) { |
michael@0 | 164 | if (lower_bound > upper_bound) { |
michael@0 | 165 | return false; |
michael@0 | 166 | } |
michael@0 | 167 | PolicyOpcode* opcode = MakeBase(OP_ULONG_MATCH_RANGE, options, |
michael@0 | 168 | selected_param); |
michael@0 | 169 | if (NULL == opcode) return NULL; |
michael@0 | 170 | opcode->SetArgument(0, lower_bound); |
michael@0 | 171 | opcode->SetArgument(1, upper_bound); |
michael@0 | 172 | return opcode; |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | template <> |
michael@0 | 176 | EvalResult OpcodeEval<OP_ULONG_MATCH_RANGE>(PolicyOpcode* opcode, |
michael@0 | 177 | const ParameterSet* param, |
michael@0 | 178 | MatchContext* context) { |
michael@0 | 179 | UNREFERENCED_PARAMETER(context); |
michael@0 | 180 | unsigned long value = 0; |
michael@0 | 181 | if (!param->Get(&value)) return EVAL_ERROR; |
michael@0 | 182 | |
michael@0 | 183 | unsigned long lower_bound = 0; |
michael@0 | 184 | unsigned long upper_bound = 0; |
michael@0 | 185 | opcode->GetArgument(0, &lower_bound); |
michael@0 | 186 | opcode->GetArgument(1, &upper_bound); |
michael@0 | 187 | return((lower_bound <= value) && (upper_bound >= value))? |
michael@0 | 188 | EVAL_TRUE : EVAL_FALSE; |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 192 | // Opcode OpUlongAndMatch: |
michael@0 | 193 | // Requires a unsigned long in selected_param. |
michael@0 | 194 | // Argument 0 is the stored number to match. |
michael@0 | 195 | |
michael@0 | 196 | PolicyOpcode* OpcodeFactory::MakeOpUlongAndMatch(int16 selected_param, |
michael@0 | 197 | unsigned long match, |
michael@0 | 198 | uint32 options) { |
michael@0 | 199 | PolicyOpcode* opcode = MakeBase(OP_ULONG_AND_MATCH, options, selected_param); |
michael@0 | 200 | if (NULL == opcode) return NULL; |
michael@0 | 201 | opcode->SetArgument(0, match); |
michael@0 | 202 | return opcode; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | template <> |
michael@0 | 206 | EvalResult OpcodeEval<OP_ULONG_AND_MATCH>(PolicyOpcode* opcode, |
michael@0 | 207 | const ParameterSet* param, |
michael@0 | 208 | MatchContext* context) { |
michael@0 | 209 | UNREFERENCED_PARAMETER(context); |
michael@0 | 210 | unsigned long value = 0; |
michael@0 | 211 | if (!param->Get(&value)) return EVAL_ERROR; |
michael@0 | 212 | |
michael@0 | 213 | unsigned long number = 0; |
michael@0 | 214 | opcode->GetArgument(0, &number); |
michael@0 | 215 | return (number & value)? EVAL_TRUE : EVAL_FALSE; |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 219 | // Opcode OpWStringMatch: |
michael@0 | 220 | // Requires a wchar_t* in selected_param. |
michael@0 | 221 | // Argument 0 is the byte displacement of the stored string. |
michael@0 | 222 | // Argument 1 is the lenght in chars of the stored string. |
michael@0 | 223 | // Argument 2 is the offset to apply on the input string. It has special values. |
michael@0 | 224 | // as noted in the header file. |
michael@0 | 225 | // Argument 3 is the string matching options. |
michael@0 | 226 | |
michael@0 | 227 | PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(int16 selected_param, |
michael@0 | 228 | const wchar_t* match_str, |
michael@0 | 229 | int start_position, |
michael@0 | 230 | StringMatchOptions match_opts, |
michael@0 | 231 | uint32 options) { |
michael@0 | 232 | if (NULL == match_str) { |
michael@0 | 233 | return NULL; |
michael@0 | 234 | } |
michael@0 | 235 | if ('\0' == match_str[0]) { |
michael@0 | 236 | return NULL; |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | int lenght = lstrlenW(match_str); |
michael@0 | 240 | |
michael@0 | 241 | PolicyOpcode* opcode = MakeBase(OP_WSTRING_MATCH, options, selected_param); |
michael@0 | 242 | if (NULL == opcode) { |
michael@0 | 243 | return NULL; |
michael@0 | 244 | } |
michael@0 | 245 | ptrdiff_t delta_str = AllocRelative(opcode, match_str, wcslen(match_str)+1); |
michael@0 | 246 | if (0 == delta_str) { |
michael@0 | 247 | return NULL; |
michael@0 | 248 | } |
michael@0 | 249 | opcode->SetArgument(0, delta_str); |
michael@0 | 250 | opcode->SetArgument(1, lenght); |
michael@0 | 251 | opcode->SetArgument(2, start_position); |
michael@0 | 252 | opcode->SetArgument(3, match_opts); |
michael@0 | 253 | return opcode; |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | template<> |
michael@0 | 257 | EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode, |
michael@0 | 258 | const ParameterSet* param, |
michael@0 | 259 | MatchContext* context) { |
michael@0 | 260 | if (NULL == context) { |
michael@0 | 261 | return EVAL_ERROR; |
michael@0 | 262 | } |
michael@0 | 263 | const wchar_t* source_str = NULL; |
michael@0 | 264 | if (!param->Get(&source_str)) return EVAL_ERROR; |
michael@0 | 265 | |
michael@0 | 266 | int start_position = 0; |
michael@0 | 267 | int match_len = 0; |
michael@0 | 268 | unsigned int match_opts = 0; |
michael@0 | 269 | opcode->GetArgument(1, &match_len); |
michael@0 | 270 | opcode->GetArgument(2, &start_position); |
michael@0 | 271 | opcode->GetArgument(3, &match_opts); |
michael@0 | 272 | |
michael@0 | 273 | const wchar_t* match_str = opcode->GetRelativeString(0); |
michael@0 | 274 | // Advance the source string to the last successfully evaluated position |
michael@0 | 275 | // according to the match context. |
michael@0 | 276 | source_str = &source_str[context->position]; |
michael@0 | 277 | int source_len = static_cast<int>(g_nt.wcslen(source_str)); |
michael@0 | 278 | |
michael@0 | 279 | if (0 == source_len) { |
michael@0 | 280 | // If we reached the end of the source string there is nothing we can |
michael@0 | 281 | // match against. |
michael@0 | 282 | return EVAL_FALSE; |
michael@0 | 283 | } |
michael@0 | 284 | if (match_len > source_len) { |
michael@0 | 285 | // There can't be a positive match when the target string is bigger than |
michael@0 | 286 | // the source string |
michael@0 | 287 | return EVAL_FALSE; |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | BOOL case_sensitive = (match_opts & CASE_INSENSITIVE) ? TRUE : FALSE; |
michael@0 | 291 | |
michael@0 | 292 | // We have three cases, depending on the value of start_pos: |
michael@0 | 293 | // Case 1. We skip N characters and compare once. |
michael@0 | 294 | // Case 2: We skip to the end and compare once. |
michael@0 | 295 | // Case 3: We match the first substring (if we find any). |
michael@0 | 296 | if (start_position >= 0) { |
michael@0 | 297 | if (kSeekToEnd == start_position) { |
michael@0 | 298 | start_position = source_len - match_len; |
michael@0 | 299 | } else if (match_opts & EXACT_LENGHT) { |
michael@0 | 300 | // A sub-case of case 3 is when the EXACT_LENGHT flag is on |
michael@0 | 301 | // the match needs to be not just substring but full match. |
michael@0 | 302 | if ((match_len + start_position) != source_len) { |
michael@0 | 303 | return EVAL_FALSE; |
michael@0 | 304 | } |
michael@0 | 305 | } |
michael@0 | 306 | |
michael@0 | 307 | // Advance start_pos characters. Warning! this does not consider |
michael@0 | 308 | // utf16 encodings (surrogate pairs) or other Unicode 'features'. |
michael@0 | 309 | source_str += start_position; |
michael@0 | 310 | |
michael@0 | 311 | // Since we skipped, lets reevaluate just the lengths again. |
michael@0 | 312 | if ((match_len + start_position) > source_len) { |
michael@0 | 313 | return EVAL_FALSE; |
michael@0 | 314 | } |
michael@0 | 315 | |
michael@0 | 316 | UNICODE_STRING match_ustr; |
michael@0 | 317 | InitStringUnicode(match_str, match_len, &match_ustr); |
michael@0 | 318 | UNICODE_STRING source_ustr; |
michael@0 | 319 | InitStringUnicode(source_str, match_len, &source_ustr); |
michael@0 | 320 | |
michael@0 | 321 | if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr, |
michael@0 | 322 | case_sensitive)) { |
michael@0 | 323 | // Match! update the match context. |
michael@0 | 324 | context->position += start_position + match_len; |
michael@0 | 325 | return EVAL_TRUE; |
michael@0 | 326 | } else { |
michael@0 | 327 | return EVAL_FALSE; |
michael@0 | 328 | } |
michael@0 | 329 | } else if (start_position < 0) { |
michael@0 | 330 | UNICODE_STRING match_ustr; |
michael@0 | 331 | InitStringUnicode(match_str, match_len, &match_ustr); |
michael@0 | 332 | UNICODE_STRING source_ustr; |
michael@0 | 333 | InitStringUnicode(source_str, match_len, &source_ustr); |
michael@0 | 334 | |
michael@0 | 335 | do { |
michael@0 | 336 | if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr, |
michael@0 | 337 | case_sensitive)) { |
michael@0 | 338 | // Match! update the match context. |
michael@0 | 339 | context->position += (source_ustr.Buffer - source_str) + match_len; |
michael@0 | 340 | return EVAL_TRUE; |
michael@0 | 341 | } |
michael@0 | 342 | ++source_ustr.Buffer; |
michael@0 | 343 | --source_len; |
michael@0 | 344 | } while (source_len >= match_len); |
michael@0 | 345 | } |
michael@0 | 346 | return EVAL_FALSE; |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 350 | // OpcodeMaker (other member functions). |
michael@0 | 351 | |
michael@0 | 352 | PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id, |
michael@0 | 353 | uint32 options, |
michael@0 | 354 | int16 selected_param) { |
michael@0 | 355 | if (memory_size() < sizeof(PolicyOpcode)) { |
michael@0 | 356 | return NULL; |
michael@0 | 357 | } |
michael@0 | 358 | |
michael@0 | 359 | // Create opcode using placement-new on the buffer memory. |
michael@0 | 360 | PolicyOpcode* opcode = new(memory_top_) PolicyOpcode(); |
michael@0 | 361 | |
michael@0 | 362 | // Fill in the standard fields, that every opcode has. |
michael@0 | 363 | memory_top_ += sizeof(PolicyOpcode); |
michael@0 | 364 | opcode->opcode_id_ = opcode_id; |
michael@0 | 365 | opcode->options_ = static_cast<int16>(options); |
michael@0 | 366 | opcode->parameter_ = selected_param; |
michael@0 | 367 | return opcode; |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | ptrdiff_t OpcodeFactory::AllocRelative(void* start, const wchar_t* str, |
michael@0 | 371 | size_t lenght) { |
michael@0 | 372 | size_t bytes = lenght * sizeof(wchar_t); |
michael@0 | 373 | if (memory_size() < bytes) { |
michael@0 | 374 | return 0; |
michael@0 | 375 | } |
michael@0 | 376 | memory_bottom_ -= bytes; |
michael@0 | 377 | if (reinterpret_cast<UINT_PTR>(memory_bottom_) & 1) { |
michael@0 | 378 | // TODO(cpu) replace this for something better. |
michael@0 | 379 | ::DebugBreak(); |
michael@0 | 380 | } |
michael@0 | 381 | memcpy(memory_bottom_, str, bytes); |
michael@0 | 382 | ptrdiff_t delta = memory_bottom_ - reinterpret_cast<char*>(start); |
michael@0 | 383 | return delta; |
michael@0 | 384 | } |
michael@0 | 385 | |
michael@0 | 386 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 387 | // Opcode evaluation dispatchers. |
michael@0 | 388 | |
michael@0 | 389 | // This function is the one and only entry for evaluating any opcode. It is |
michael@0 | 390 | // in charge of applying any relevant opcode options and calling EvaluateInner |
michael@0 | 391 | // were the actual dispatch-by-id is made. It would seem at first glance that |
michael@0 | 392 | // the dispatch should be done by virtual function (vtable) calls but you have |
michael@0 | 393 | // to remember that the opcodes are made in the broker process and copied as |
michael@0 | 394 | // raw memory to the target process. |
michael@0 | 395 | |
michael@0 | 396 | EvalResult PolicyOpcode::Evaluate(const ParameterSet* call_params, |
michael@0 | 397 | size_t param_count, MatchContext* match) { |
michael@0 | 398 | if (NULL == call_params) { |
michael@0 | 399 | return EVAL_ERROR; |
michael@0 | 400 | } |
michael@0 | 401 | const ParameterSet* selected_param = NULL; |
michael@0 | 402 | if (parameter_ >= 0) { |
michael@0 | 403 | if (static_cast<size_t>(parameter_) >= param_count) { |
michael@0 | 404 | return EVAL_ERROR; |
michael@0 | 405 | } |
michael@0 | 406 | selected_param = &call_params[parameter_]; |
michael@0 | 407 | } |
michael@0 | 408 | EvalResult result = EvaluateHelper(selected_param, match); |
michael@0 | 409 | |
michael@0 | 410 | // Apply the general options regardless of the particular type of opcode. |
michael@0 | 411 | if (kPolNone == options_) { |
michael@0 | 412 | return result; |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | if (options_ & kPolNegateEval) { |
michael@0 | 416 | if (EVAL_TRUE == result) { |
michael@0 | 417 | result = EVAL_FALSE; |
michael@0 | 418 | } else if (EVAL_FALSE == result) { |
michael@0 | 419 | result = EVAL_TRUE; |
michael@0 | 420 | } else if (EVAL_ERROR != result) { |
michael@0 | 421 | result = EVAL_ERROR; |
michael@0 | 422 | } |
michael@0 | 423 | } |
michael@0 | 424 | if (NULL != match) { |
michael@0 | 425 | if (options_ & kPolClearContext) { |
michael@0 | 426 | match->Clear(); |
michael@0 | 427 | } |
michael@0 | 428 | if (options_ & kPolUseOREval) { |
michael@0 | 429 | match->options = kPolUseOREval; |
michael@0 | 430 | } |
michael@0 | 431 | } |
michael@0 | 432 | return result; |
michael@0 | 433 | } |
michael@0 | 434 | |
michael@0 | 435 | #define OPCODE_EVAL(op, x, y, z) case op: return OpcodeEval<op>(x, y, z) |
michael@0 | 436 | |
michael@0 | 437 | EvalResult PolicyOpcode::EvaluateHelper(const ParameterSet* parameters, |
michael@0 | 438 | MatchContext* match) { |
michael@0 | 439 | switch (opcode_id_) { |
michael@0 | 440 | OPCODE_EVAL(OP_ALWAYS_FALSE, this, parameters, match); |
michael@0 | 441 | OPCODE_EVAL(OP_ALWAYS_TRUE, this, parameters, match); |
michael@0 | 442 | OPCODE_EVAL(OP_NUMBER_MATCH, this, parameters, match); |
michael@0 | 443 | OPCODE_EVAL(OP_ULONG_MATCH_RANGE, this, parameters, match); |
michael@0 | 444 | OPCODE_EVAL(OP_WSTRING_MATCH, this, parameters, match); |
michael@0 | 445 | OPCODE_EVAL(OP_ULONG_AND_MATCH, this, parameters, match); |
michael@0 | 446 | OPCODE_EVAL(OP_ACTION, this, parameters, match); |
michael@0 | 447 | default: |
michael@0 | 448 | return EVAL_ERROR; |
michael@0 | 449 | } |
michael@0 | 450 | } |
michael@0 | 451 | |
michael@0 | 452 | #undef OPCODE_EVAL |
michael@0 | 453 | |
michael@0 | 454 | } // namespace sandbox |