| Index: src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.c
|
| diff --git a/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.c b/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.c
|
| deleted file mode 100644
|
| index ce76968ac5b339740adba8fa01eab522a18e20c2..0000000000000000000000000000000000000000
|
| --- a/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.c
|
| +++ /dev/null
|
| @@ -1,572 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.h"
|
| -
|
| -#include "native_client/src/include/portability_io.h"
|
| -#include "native_client/src/shared/platform/nacl_log.h"
|
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
|
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
|
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h"
|
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h"
|
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_utils.h"
|
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h"
|
| -
|
| -/* To turn on debugging of instruction decoding, change value of
|
| - * DEBUGGING to 1.
|
| - */
|
| -#define DEBUGGING 0
|
| -
|
| -#include "native_client/src/shared/utils/debugging.h"
|
| -
|
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c"
|
| -#include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
|
| -
|
| -/*
|
| - * When true, check both uses and sets of memory. When false, only
|
| - * check sets.
|
| - */
|
| -Bool NACL_FLAGS_read_sandbox = TRUE;
|
| -
|
| -/* Type used to measure number of instructions matched using a validator
|
| - * pattern.
|
| - */
|
| -typedef int NaClPatternLength;
|
| -
|
| -/* Constant denoting that pattern match failed. Used by pattern checking
|
| - * functions that return the number of instructions pattern matched.
|
| - */
|
| -static const NaClPatternLength kNaClPatternMatchFailed = -1;
|
| -
|
| -/* Returns the instruction "distance" elements back from the current
|
| - * instruction of the validator state. Returns NULL if no such instruction
|
| - * exists.
|
| - */
|
| -static INLINE NaClInstState* NaClGetValInstStateAt(NaClValidatorState* state,
|
| - size_t distance) {
|
| - if (distance == 0) {
|
| - return state->cur_inst_state;
|
| - } else if (NaClInstIterHasLookbackStateInline(state->cur_iter, distance)) {
|
| - return NaClInstIterGetLookbackStateInline(state->cur_iter, distance);
|
| - } else {
|
| - return NULL;
|
| - }
|
| -}
|
| -
|
| -/* Returns true if the given register is in {%RSP, %RBP, %RIP, %RBASE}.*/
|
| -static INLINE Bool NaClIsValidBaseRegister(NaClValidatorState* state,
|
| - NaClOpKind reg) {
|
| - return reg == state->base_register ||
|
| - reg == RegRSP ||
|
| - reg == RegRBP ||
|
| - reg == RegRIP;
|
| -}
|
| -
|
| -/* Returns true if the node corresponds to an expression set, or an
|
| - * expression use if we are doing read sandboxing.
|
| - */
|
| -static Bool IsPossibleSandboxingNode(NaClExp* node) {
|
| - return ((NACL_FLAGS_read_sandbox && (node->flags & NACL_EFLAG(ExprUsed))) ||
|
| - (node->flags & NACL_EFLAG(ExprSet)));
|
| -}
|
| -
|
| -/* Returns true if the "distance" instruction, from the current instruction
|
| - * of the validator state is a mov of the form:
|
| - * mov %reg, %reg
|
| - * and %reg is a 32-bit register.
|
| - */
|
| -static Bool NaClIsMov32UsingReg(NaClValidatorState* state,
|
| - size_t distance,
|
| - NaClOpKind reg) {
|
| - NaClExpVector* vector;
|
| - NaClInstState* inst_state;
|
| -
|
| -#ifdef NCVAL_TESTING
|
| - /* Assume we match previous instructions when generating pre/post
|
| - * conditions.
|
| - */
|
| - if (distance > 0) return TRUE;
|
| -#endif
|
| -
|
| - /* Get the instruction to be checked. */
|
| - inst_state = NaClGetValInstStateAt(state, distance);
|
| - if (NULL == inst_state) return FALSE;
|
| -
|
| - /* Check that it is a move on the specified register. */
|
| - vector = NaClInstStateExpVector(inst_state);
|
| - if (!NaClIsMovUsingRegisters(inst_state->decoder_tables,
|
| - inst_state->inst,
|
| - vector,
|
| - reg,
|
| - reg)) return FALSE;
|
| -
|
| - /* Check that this is a 32-bit mov.
|
| - * Note: Since the vector contains a list of operand expressions, the
|
| - * first operand reference is always at index zero, and its first child
|
| - * (where the register set is defined) is at index 1.
|
| - */
|
| - return NaClHasBit(vector->node[1].flags, NACL_EFLAG(ExprSize32));
|
| -}
|
| -
|
| -/* Checks if the given node index for the given instruction is
|
| - * a valid (sandboxed) memory offset, based on NACL rules, returning TRUE iff
|
| - * the memory offset is NACL compliant. That is, of one of
|
| - * the following forms:
|
| - * [%base+%r64*n+d32]
|
| - * where the previous instruction is of the form:
|
| - * op %r32, .. ; zero out top half of r32
|
| - * and r32 is the corresponding 32-bit register for the 64-bit register
|
| - * r64
|
| - * [%base+d32]
|
| - * [%base]
|
| - *
|
| - * where rbase is in { RIP, RSP, RBP, RZP }, and d32 must not exceed 32 bits.
|
| - *
|
| - * parameters are:
|
| - * state - The state of the validator,
|
| - * distance - number of instructions to lookback
|
| - * (within the iterator) in order to retrieve the instruction.
|
| - * node_index - The index of the memory offset within the given
|
| - * instruction vector.
|
| - * use_mov_for_zero_ext - True if zero extending op must be of the
|
| - * form "mov %r32, %r32".
|
| - * print_messages - True if this routine is responsable for printing
|
| - * error messages if the memory offset isn't NACL compliant.
|
| - *
|
| - * Returns the number of (additional) instructions were needed to recognize
|
| - * the pattern, or kNaClPatternMatchFailed if the pattern fails.
|
| - */
|
| -static NaClPatternLength NaClMatchValidMemOffset(
|
| - NaClValidatorState* state,
|
| - size_t distance,
|
| - int node_index,
|
| - Bool use_mov_for_zero_ext,
|
| - Bool print_messages) {
|
| - int base_reg_index;
|
| - NaClOpKind base_reg;
|
| - int index_reg_index;
|
| - NaClExp* index_reg_node;
|
| - NaClOpKind index_reg;
|
| - int scale_index;
|
| - int disp_index;
|
| - NaClInstState* inst;
|
| - NaClExpVector* vector;
|
| - NaClExp* node;
|
| - NaClPatternLength pattern_length = 0;
|
| -
|
| -#ifdef NCVAL_TESTING
|
| - /* Assume we match previous instructions when generating pre/post
|
| - * conditions.
|
| - */
|
| - if (distance > 0) return pattern_length;
|
| -#endif
|
| -
|
| - /* Get the instruction to be checked. */
|
| - inst = NaClGetValInstStateAt(state, distance);
|
| - if (NULL == inst) return kNaClPatternMatchFailed;
|
| -
|
| - /* Check that the node_index of the referenced instruction corresponds to
|
| - * a memory offset.
|
| - */
|
| - vector = NaClInstStateExpVector(inst);
|
| - node = &vector->node[node_index];
|
| - if (ExprMemOffset != node->kind) return kNaClPatternMatchFailed;
|
| -
|
| - DEBUG(NaClLog(LOG_INFO,
|
| - "found MemOffset at node %"NACL_PRIu32" %d\n", node_index,
|
| - (int) distance));
|
| -
|
| - /* Only allow memory offset nodes with address size 64. */
|
| - if (NACL_EMPTY_EFLAGS == (node->flags & NACL_EFLAG(ExprSize64))) {
|
| - if (print_messages) {
|
| - NaClValidatorInstMessage(LOG_ERROR, state, inst,
|
| - "Assignment to non-64 bit memory address\n");
|
| - }
|
| - return kNaClPatternMatchFailed;
|
| - }
|
| - DEBUG(NaClLog(LOG_INFO, "found 64 bit address for MemOffset\n"));
|
| -
|
| - /* Check that the base register is valid. */
|
| - base_reg_index = node_index + 1;
|
| - base_reg = NaClGetExpVectorRegister(vector, base_reg_index);
|
| - DEBUG(NaClLog(LOG_INFO, "base reg = %s\n", NaClOpKindName(base_reg)));
|
| - if (!NaClIsValidBaseRegister(state, base_reg)) {
|
| - if (print_messages) {
|
| - NaClValidatorInstMessage(
|
| - LOG_ERROR, state, inst,
|
| - (base_reg == RegUnknown
|
| - ? "No base register specified in memory offset\n"
|
| - : "Invalid base register in memory offset\n"));
|
| - }
|
| - return kNaClPatternMatchFailed;
|
| - }
|
| - DEBUG(NaClLog(LOG_INFO, " => base register is valid\n"));
|
| -
|
| - /* Check that the index register is either undefined, or defined
|
| - * with the appropriate assignment. Note: We currently don't allow
|
| - * an index register to be used with RIP. Only "RIP + disp32" is allowed.
|
| - */
|
| - index_reg_index = base_reg_index + NaClExpWidth(vector, base_reg_index);
|
| - index_reg_node = &vector->node[index_reg_index];
|
| - index_reg = NaClGetExpRegisterInline(index_reg_node);
|
| - DEBUG(NaClLog(LOG_INFO, "index reg = %s\n", NaClOpKindName(index_reg)));
|
| - if (RegUnknown != index_reg) {
|
| - Bool index_reg_is_good = FALSE;
|
| - if ((base_reg != RegRIP) &&
|
| - NaClHasBit(index_reg_node->flags, NACL_EFLAG(ExprSize64))) {
|
| - if (use_mov_for_zero_ext) {
|
| - index_reg_is_good =
|
| - NaClIsMov32UsingReg(state, distance + 1,
|
| - NaClGet32For64BitReg(index_reg));
|
| - } else {
|
| - index_reg_is_good =
|
| - NaClAssignsRegisterWithZeroExtends64(state, distance + 1,
|
| - index_reg);
|
| - }
|
| - }
|
| - if (index_reg_is_good) {
|
| - pattern_length++;
|
| - } else {
|
| - if (print_messages) {
|
| - NaClValidatorInstMessage(LOG_ERROR, state, inst,
|
| - "Invalid index register in memory offset\n");
|
| - }
|
| - return kNaClPatternMatchFailed;
|
| - }
|
| - } else if (use_mov_for_zero_ext) {
|
| - /* The index register must be defined in this case. Report as error!. */
|
| - if (print_messages) {
|
| - NaClValidatorInstMessage(LOG_ERROR, state, inst,
|
| - "Invalid index register in memory offset\n");
|
| - return kNaClPatternMatchFailed;
|
| - }
|
| - }
|
| -
|
| - /* Check displacement value is valid (i.e. 32 or less bits).
|
| - * Note: scale need not be
|
| - * checked since it can't exceed 8, and is undefined if the index register
|
| - * is undefined.
|
| - */
|
| - scale_index = index_reg_index + NaClExpWidth(vector, index_reg_index);
|
| - disp_index = scale_index + NaClExpWidth(vector, scale_index);
|
| - DEBUG(NaClLog(LOG_INFO, "disp index = %d\n", disp_index));
|
| - if (ExprConstant != vector->node[disp_index].kind) {
|
| - if (print_messages) {
|
| - NaClValidatorInstMessage(LOG_ERROR, state, inst,
|
| - "Invalid displacement in memory offset\n");
|
| - }
|
| - return kNaClPatternMatchFailed;
|
| - }
|
| -
|
| - /* If reached, we matched the pattern, return number of instructions
|
| - * needed for match.
|
| - */
|
| - DEBUG(NaClLog(LOG_INFO, "Memory Offset pattern length = %d\n",
|
| - pattern_length));
|
| -#ifdef NCVAL_TESTING
|
| - if ((0 == distance) && (RegUnknown != index_reg)) {
|
| - /* Report precondition of test.
|
| - * TODO(karl): This should be lifted out of this test, and
|
| - * only applied when pattern matches.
|
| - */
|
| - char* buffer;
|
| - size_t buffer_size;
|
| - char reg_name[kMaxBufferSize];
|
| - NaClOpRegName(NaClGet32For64BitReg(index_reg), reg_name, kMaxBufferSize);
|
| - NaClConditionAppend(state->precond, &buffer, &buffer_size);
|
| - SNPRINTF(buffer, buffer_size, "ZeroExtends(%s)", reg_name);
|
| - }
|
| -#endif
|
| - return pattern_length;
|
| -}
|
| -
|
| -/* Applies the precondition "SafeAddress(addr_reg)" pattern for
|
| - * segment addresses. Applies the match to the "distance" instruction
|
| - * back from the current instruction. Returns true if the instruction
|
| - * is a pair of instructions of the form:
|
| - *
|
| - * mov %r32, %r32 ; zero out top half of r32
|
| - * lea %r64, [%r15+%r64*1] ; rebase address and put in r64
|
| - *
|
| - * where r32 is the corresponding 32-bit register for the 64-bit register
|
| - * r64. Returns true if the precondition is met.
|
| - */
|
| -static Bool NaClMatchLeaSafeAddress(
|
| - NaClValidatorState* state,
|
| - size_t distance,
|
| - NaClOpKind reg64) {
|
| - NaClExpVector* vector;
|
| - NaClOpKind lea_reg;
|
| - int memoff_index;
|
| - NaClPatternLength pattern_length;
|
| - NaClInstState* inst_state;
|
| - const NaClInst* inst;
|
| -
|
| - DEBUG(NaClLog(LOG_INFO, "reg64 = %s, distance = %d\n",
|
| - NaClOpKindName(reg64), (int) distance));
|
| -
|
| -#ifdef NCVAL_TESTING
|
| - /* Don't match previous instructions when pattern matching. */
|
| - if (distance > 0) return TRUE;
|
| -#endif
|
| -
|
| - /* Get the instruction to be checked. */
|
| - inst_state = NaClGetValInstStateAt(state, distance);
|
| - if (NULL == inst_state) return FALSE;
|
| -
|
| - /* Check that it is an LEA instruction. */
|
| - inst = NaClInstStateInst(inst_state);
|
| - if (InstLea != inst->name) return FALSE;
|
| -
|
| - /* Note that first argument of LEA is always a register,
|
| - * (under an OperandReference), and hence is always at
|
| - * index 1.
|
| - */
|
| - vector = NaClInstStateExpVector(inst_state);
|
| - lea_reg = NaClGetExpVectorRegister(vector, 1);
|
| - DEBUG(NaClLog(LOG_INFO, "lea reg = %s\n", NaClOpKindName(lea_reg)));
|
| - if (lea_reg != reg64) return FALSE;
|
| -
|
| - /* Move to second argument which should be a memory address. */
|
| - memoff_index = NaClGetNthExpKind(vector, OperandReference, 2);
|
| - if (-1 == memoff_index) return FALSE;
|
| - memoff_index = NaClGetExpKidIndex(vector, memoff_index, 0);
|
| - if (memoff_index >= (int) vector->number_expr_nodes) return FALSE;
|
| - DEBUG(NaClLog(LOG_INFO, "check mem offset!\n"));
|
| -
|
| - /* Check that memory offset argument of the lea is valid. */
|
| - pattern_length = NaClMatchValidMemOffset(state,
|
| - distance,
|
| - memoff_index,
|
| - TRUE,
|
| - FALSE);
|
| - if (kNaClPatternMatchFailed == pattern_length) return FALSE;
|
| -
|
| - /* If reached, matched pattern! */
|
| - return TRUE;
|
| -}
|
| -
|
| -void NaClMemoryReferenceValidator(NaClValidatorState* state) {
|
| - /* Note: This code assumes that only DS:RSI and ES:RDI allow
|
| - * multiple memory accesses with a single instruction, as defined
|
| - * by the string instructions Movs and Cmps. In such cases, the
|
| - * ES:RDI must appear before the DS:RSI.
|
| - */
|
| - int i;
|
| - NaClInstState* inst_state = state->cur_inst_state;
|
| - NaClExpVector* vector = state->cur_inst_vector;
|
| -
|
| - /* Holds the number of additional instructions in pattern(s) associated with
|
| - * the current instruction of the validator state.
|
| - */
|
| - int pattern_length = 0;
|
| -
|
| - /* Counts number of memory references in the current instruction. */
|
| - int number_memory_refs = 0;
|
| -
|
| - /* Counts the number of unique segment (memory) references in the current
|
| - * instruction.
|
| - */
|
| - int number_segment_addresses = 0;
|
| -
|
| - /* Records first segment reference register, to allow duplication of it.
|
| - */
|
| - NaClOpKind previous_seg_addr = RegUnknown;
|
| -
|
| - DEBUG_OR_ERASE({
|
| - struct Gio* g = NaClLogGetGio();
|
| - NaClLog(LOG_INFO, "-> Validating store\n");
|
| - NaClInstStateInstPrint(g, inst_state);
|
| - NaClInstPrint(g, state->decoder_tables, state->cur_inst);
|
| - NaClExpVectorPrint(g, inst_state);
|
| - });
|
| -
|
| - /* Look for assignments on a memory offset. */
|
| - for (i = 0; i < (int) vector->number_expr_nodes; ++i) {
|
| - /* Note: continue (within this loop) is used to indicate
|
| - * that the node describes a safe memory address.
|
| - */
|
| - NaClPatternLength memoffset_length;
|
| - NaClExp* node = &vector->node[i];
|
| - DEBUG(NaClLog(LOG_INFO, "pattern length = %d\n", pattern_length);
|
| - NaClLog(LOG_INFO, "processing argument %"NACL_PRIu32"\n", i));
|
| - if (state->quit) break;
|
| -
|
| - if (!IsPossibleSandboxingNode(node)) continue;
|
| - DEBUG(NaClLog(LOG_INFO, "found possible sandboxing reference\n"));
|
| -
|
| - /* Check if the node is a safe memory offset (i.e address). */
|
| - memoffset_length = NaClMatchValidMemOffset(state, 0, i, FALSE, TRUE);
|
| - DEBUG(NaClLog(LOG_INFO, "memoffset inst length = %d\n", memoffset_length));
|
| - if (kNaClPatternMatchFailed != memoffset_length) {
|
| - /* Cases 1, 2, or 3 (see nc_memory_protect.h). */
|
| - number_memory_refs++;
|
| - pattern_length += memoffset_length;
|
| - continue;
|
| - }
|
| -
|
| - if (ExprSegmentAddress == node->kind) {
|
| - /* Note that operations like stosb, stosw, stosd, and stosq use
|
| - * segment notation. In 64 bit mode, the second argument must
|
| - * be a register, and be computed (using lea) so that it matches
|
| - * a valid (sandboxed) memory offset. For example:
|
| - *
|
| - * mov %edi, %edi ; zero out top half of rdi
|
| - * lea %rdi, [%r15+%edi*1] ; calculate address, put in rdi
|
| - * stos %eax ; implicity uses %es:(%rdi)
|
| - *
|
| - * Note: we allow only one zero-extending operation for string
|
| - * instructions: an identity MOV.
|
| - */
|
| - int seg_prefix_reg_index;
|
| - NaClOpKind seg_prefix_reg;
|
| - DEBUG(NaClLog(LOG_INFO,
|
| - "found segment assign at node %"NACL_PRIu32"\n", i));
|
| -
|
| - /* Only allow if 64 bit segment addresses. */
|
| - if (NACL_EMPTY_EFLAGS == (node->flags & NACL_EFLAG(ExprSize64))) {
|
| - NaClValidatorInstMessage(
|
| - LOG_ERROR, state, inst_state,
|
| - "Assignment to non-64 bit segment address\n");
|
| - continue;
|
| - }
|
| -
|
| - /* Only allow segment prefix registers that are treated as
|
| - * null prefixes.
|
| - */
|
| - seg_prefix_reg_index = NaClGetExpKidIndex(vector, i, 0);
|
| - seg_prefix_reg = NaClGetExpVectorRegister(vector, seg_prefix_reg_index);
|
| - switch (seg_prefix_reg) {
|
| - /* Note: continue (of the for loop) is used to indicate a good segment
|
| - * address (for node being checked) while break (of the switch) is
|
| - * used to indicate a bad segment address.
|
| - */
|
| - case RegCS:
|
| - case RegDS:
|
| - case RegES:
|
| - case RegSS: {
|
| - NaClOpKind addr_reg;
|
| -
|
| - /* Get the address register of the segment memory address. */
|
| - int addr_reg_index = NaClGetExpKidIndex(vector, i, 1);
|
| - DEBUG(NaClLog(LOG_INFO,
|
| - "matched segment %s, address at index %d\n",
|
| - NaClOpKindName(seg_prefix_reg), addr_reg_index));
|
| - if (-1 == addr_reg_index) break;
|
| - addr_reg =
|
| - NaClGetExpVectorRegister(vector, addr_reg_index);
|
| - if (addr_reg == RegUnknown) break;
|
| -
|
| - /* If addr_reg a previously known register, allow. */
|
| - if (previous_seg_addr == RegUnknown) {
|
| - previous_seg_addr = addr_reg;
|
| - } else if (addr_reg == previous_seg_addr) {
|
| - /* No need to check new pattern, existing pattern
|
| - * should check.
|
| - */
|
| - continue;
|
| - }
|
| -
|
| - /* Check that the address register is an lea address
|
| - * that is safe. */
|
| - if (!NaClMatchLeaSafeAddress(state, pattern_length + 1,
|
| - addr_reg)) break;
|
| -
|
| - /* Case 4 (see nc_memory_protect.h). */
|
| - number_memory_refs++;
|
| - number_segment_addresses++;
|
| - pattern_length += 2;
|
| - DEBUG(NaClLog(LOG_INFO, "updated pattern_length = %d\n",
|
| - pattern_length));
|
| -#ifdef NCVAL_TESTING
|
| - {
|
| - /* Assume that previous instruction is an LEA, since
|
| - * we want to only generate pre/post conditions.
|
| - */
|
| - char* buffer;
|
| - size_t buffer_size;
|
| - char reg_name[kMaxBufferSize];
|
| - NaClOpRegName(addr_reg, reg_name, kMaxBufferSize);
|
| - NaClConditionAppend(state->precond, &buffer, &buffer_size);
|
| - SNPRINTF(buffer, buffer_size, "SafeAddress(%s)", reg_name);
|
| - }
|
| -#endif
|
| - continue;
|
| - }
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - /* If reached, we don't know how to handle the segment address. */
|
| - NaClValidatorInstMessage(LOG_ERROR, state, inst_state,
|
| - "Segment memory reference not allowed\n");
|
| - continue;
|
| - }
|
| -
|
| - /* Don't complain about register set/usage. */
|
| - if (UndefinedExp == node->kind ||
|
| - (ExprRegister == node->kind &&
|
| - RegUnknown == NaClGetExpRegisterInline(node))) {
|
| - /* First rule out case where the index registers of the memory
|
| - * offset may be unknown.
|
| - */
|
| - int parent_index = NaClGetExpParentIndex(vector, i);
|
| - if (parent_index >= 0 &&
|
| - (i == NaClGetExpKidIndex(vector, parent_index, 1))) {
|
| - /* Special case of memory offsets that we allow. That is, memory
|
| - * offsets can optionally define index register. If the index
|
| - * register isn't specified, the value RegUnknown is used as
|
| - * a placeholder (and hence legal).
|
| - */
|
| - } else {
|
| - /* This shouldn't happpen, but if it does, its because either:
|
| - * (1) We couldn't translate the expression, and hence complain; or
|
| - * (2) It is an X87 instruction with a register address, which we
|
| - * don't allow (in case these instructions get generalized in
|
| - * the future).
|
| - */
|
| - NaClValidatorInstMessage(
|
| - LOG_ERROR, state, inst_state,
|
| - "Memory reference not understood, can't verify correctness.\n");
|
| - }
|
| - }
|
| - }
|
| -
|
| - /* Disallow multiple memory references unless pair of special segment refs. */
|
| - if ((number_memory_refs > 1) &&
|
| - (number_segment_addresses != number_memory_refs)) {
|
| - NaClValidatorInstMessage(
|
| - LOG_ERROR, state, inst_state,
|
| - "Multiple memory references not allowed in this context\n");
|
| - }
|
| -
|
| -#ifndef NCVAL_TESTING
|
| - /* Mark all but first instruction of pattern illegal to jump into. */
|
| - if (0 < pattern_length) {
|
| - NaClMarkInstructionsJumpRangeIllegal(state, pattern_length);
|
| - }
|
| -#endif
|
| - DEBUG(NaClLog(LOG_INFO, "<- Validating store\n"));
|
| -}
|
| -
|
| -#ifdef NCVAL_TESTING
|
| -Bool NaClAcceptLeaSafeAddress(struct NaClValidatorState* state) {
|
| - const NaClInst* inst;
|
| -
|
| - /* Check that it is an LEA instruction. */
|
| - inst = NaClInstStateInst(state->cur_inst_state);
|
| - if (InstLea != inst->name) return FALSE;
|
| -
|
| - /* Note that first argument of LEA is always a register,
|
| - * (under an OperandReference), and hence is always at
|
| - * index 1.
|
| - */
|
| - return NaClMatchLeaSafeAddress(
|
| - state, 0,
|
| - NaClGetExpVectorRegister(NaClInstStateExpVector(state->cur_inst_state),
|
| - 1));
|
| -}
|
| -#endif
|
|
|