| 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 | 
|  |