LCOV - code coverage report
Current view: directory - src/trusted/validator/x86 - ncinstbuffer_inl.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 73 70 95.9 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /* ncinstbuffer-inl.h - Holds nline functions for commonly used (simple)
       8                 :  * functions in ncinstbuffer.h. Used to speed up code. Inlineed routines
       9                 :  * correspond to the following functions in ncinstbuffer.h, but with an
      10                 :  * 'Inline' suffix:
      11                 :  *
      12                 :  *   NCRemainingMemoryAdvance
      13                 :  *   NCRemainingMemoryReset
      14                 :  *   NCRemainingMemoryLookahead
      15                 :  *   NCRemainingMemoryRead
      16                 :  *   NCInstBytesPeek
      17                 :  *   NCInstByte
      18                 :  *   NCInstBytesRead
      19                 :  *   NCInstBytesReadBytes
      20                 :  *   NCInstBytesReset
      21                 :  *   NCInstBytesInit
      22                 :  *   NCInstBytesByte
      23                 :  *
      24                 :  * See ncinstbuffer.h for comments on how to use the corresponding inline
      25                 :  * functions.
      26                 :  */
      27                 : 
      28                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__
      29                 : #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__
      30                 : 
      31                 : #include "native_client/src/trusted/validator/x86/ncinstbuffer.h"
      32                 : 
      33                 : /* Constant NCBUF_CLEAR_CACHE controls the behaviour of the buffer containing
      34                 :  * the sequence of parsed bytes. Turn it on (1) to fill unused bytes with the
      35                 :  * constant zero, and to allow access to all bytes in the sequence of parsed
      36                 :  * bytes. Turn it off (0) to force access to only include the actual parsed
      37                 :  * bytes.
      38                 :  *
      39                 :  * Note: Ideally, we would like to turn this feature off. However, the current
      40                 :  * instruction parser (in ncdecode.c) and corresponding printer (in
      41                 :  * ncdis_util.c) are problematic. The parser allows a partial match of
      42                 :  * an instruction, without verifying that ALL necessary bytes are there. The
      43                 :  * corresponding printer, assumes that only complete matches (during parsing)
      44                 :  * were performed. The result is that the code sometimes assumes that many
      45                 :  * more bytes were parsed than were actually parsed.
      46                 :  *
      47                 :  * To quickly fix the code so that it doesn't do illegal memory accesses, but
      48                 :  * has consistent behaviour, the flag is currently sets NCBUF_CLEAR_CACHE to 1.
      49                 :  *
      50                 :  * To debug this problem, set the flag NCBUF_CLEAR_CACHE to 0.
      51                 :  *
      52                 :  * TODO(karl) Fix the parser/printer so that NCBUF_CLEAR_CACHE can be set to 0.
      53                 :  */
      54                 : #define NCBUF_CLEAR_CACHE 1
      55                 : 
      56                 : /* Defines the number of bytes in the buffer. */
      57                 : #if NCBUF_CLEAR_CACHE
      58                 : #define NCBUF_BYTES_LENGTH(bytes) MAX_INST_LENGTH
      59                 : #else
      60                 : #define NCBUF_BYTES_LENGTH(bytes) (bytes)->length
      61                 : #endif
      62                 : 
      63                 : /* The constant to return if memory overflow occurs. */
      64                 : # define NC_MEMORY_OVERFLOW 0
      65                 : 
      66                 : /* Returns the next byte in memory, or 0x00 if there are no more
      67                 :  * bytes in memory.
      68                 :  */
      69               9 : static INLINE uint8_t NCRemainingMemoryPeekInline(NCRemainingMemory* memory) {
      70                 :   return (memory->cur_pos >= memory->mlimit)
      71               9 :       ? NC_MEMORY_OVERFLOW : *(memory->cur_pos);
      72               9 : }
      73                 : 
      74                 : /* Starts a new instruction at the current position in the memory
      75                 :  * segment.
      76                 :  */
      77               9 : static INLINE void NCRemainingMemoryAdvanceInline(NCRemainingMemory* memory) {
      78               9 :   memory->mpc = memory->cur_pos;
      79               9 :   memory->read_length = 0;
      80               9 :   memory->overflow_count = 0;
      81               9 : }
      82                 : 
      83                 : /* Moves back to the beginning of the current instruction in
      84                 :  * the memory segment.
      85                 :  */
      86               5 : static INLINE void NCRemainingMemoryResetInline(NCRemainingMemory* memory) {
      87               5 :   memory->cur_pos = memory->mpc;
      88               5 :   memory->next_byte = NCRemainingMemoryPeekInline(memory);
      89               5 :   memory->read_length = 0;
      90               5 :   memory->overflow_count = 0;
      91               5 : }
      92                 : 
      93                 : /* Looks ahead N bytes into the memory, and returns the corresponding
      94                 :  * byte, or 0x00 if at the end of memory. i is zero-based.
      95                 :  */
      96                 : static INLINE uint8_t NCRemainingMemoryLookaheadInline(
      97               5 :     NCRemainingMemory* memory, ssize_t n) {
      98               5 :   if ((memory->cur_pos + n) < memory->mlimit) {
      99               5 :     return memory->cur_pos[n];
     100                 :   } else {
     101               3 :     return NC_MEMORY_OVERFLOW;
     102                 :   }
     103               5 : }
     104                 : 
     105                 : /* Reads and returns the next byte in the memory segment. Returns 0x00 if at
     106                 :  * the end of the memory segment.
     107                 :  */
     108               6 : static INLINE uint8_t NCRemainingMemoryReadInline(NCRemainingMemory* memory) {
     109               6 :   uint8_t byte = memory->next_byte;
     110               6 :   if (memory->cur_pos == memory->mlimit) {
     111                 :     /* If reached, next_byte already set to 0 by last read. */
     112               4 :     if (0 == memory->overflow_count) {
     113               4 :       memory->error_fn(NCRemainingMemoryOverflow, memory);
     114                 :     }
     115               4 :     memory->overflow_count++;
     116               4 :   } else {
     117               6 :     memory->read_length++;
     118               6 :     memory->cur_pos++;
     119               6 :     memory->next_byte = NCRemainingMemoryPeekInline(memory);
     120                 :   }
     121               6 :   return byte;
     122               6 : }
     123                 : 
     124                 : /* Peek ahead and return the nth (zero based) byte from the current position
     125                 :  * in the sequence of bytes being parsed.
     126                 :  */
     127               2 : static INLINE uint8_t NCInstBytesPeekInline(NCInstBytes* bytes, ssize_t n) {
     128               2 :   return NCRemainingMemoryLookaheadInline(bytes->memory, n);
     129               2 : }
     130                 : 
     131                 : /* Peek at the nth character in the sequence of bytes being parsed (independent
     132                 :  * of the current position).
     133                 :  */
     134               1 : static INLINE uint8_t NCInstByteInline(NCInstBytes* bytes, ssize_t n) {
     135               1 :   if (n < bytes->length)  {
     136               1 :     return bytes->byte[n];
     137                 :   } else {
     138               0 :     return NCRemainingMemoryLookaheadInline(bytes->memory, n - bytes->length);
     139                 :   }
     140               1 : }
     141                 : 
     142                 : /* Reads a byte from the memory segment and adds it to the instruction buffer.
     143                 :  * Returns the read byte.
     144                 :  * Note: Assumes that NCInstBytesInitMemory has already been called to associate
     145                 :  * memory.
     146                 :  */
     147               5 : static INLINE uint8_t NCInstBytesReadInline(NCInstBytes* bytes) {
     148               5 :   uint8_t byte = NCRemainingMemoryReadInline(bytes->memory);
     149               5 :   if (bytes->length < MAX_INST_LENGTH) {
     150               5 :     bytes->byte[bytes->length++] = byte;
     151               5 :   } else {
     152               1 :     bytes->memory->error_fn(NCInstBufferOverflow, bytes->memory);
     153                 :   }
     154               5 :   return byte;
     155               5 : }
     156                 : 
     157                 : /* Reads n bytes from the memory segment and adds it to the instruction buffer.
     158                 :  * Note: Assumes that NCInstBytesInitMemory has already been called to associate
     159                 :  * memory.
     160                 :  */
     161               4 : static INLINE void NCInstBytesReadBytesInline(ssize_t n, NCInstBytes* bytes) {
     162                 :   ssize_t i;
     163               4 :   for (i = 0; i < n; ++i) {
     164               4 :     NCInstBytesReadInline(bytes);
     165               4 :   }
     166               4 : }
     167                 : 
     168                 : /* Resets bytes back to the beginning of the current instruction. */
     169               3 : static INLINE void NCInstBytesResetInline(NCInstBytes* buffer) {
     170                 : #if NCBUF_CLEAR_CACHE
     171                 :   int i;
     172               3 :   for (i = 0; i < MAX_INST_LENGTH; ++i) {
     173               3 :     buffer->byte[i] = 0;
     174               3 :   }
     175                 : #endif
     176               3 :   NCRemainingMemoryResetInline(buffer->memory);
     177               3 :   buffer->length = 0;
     178               3 : }
     179                 : 
     180                 : /* Initializes the instruction buffer as the empty buffer, and
     181                 :  * advances the memory segment so that one is beginning the
     182                 :  * parsing of the current instruction at the current position
     183                 :  * in the memory segment.
     184                 :  * Note: Assumes that NCInstBytesInitMemory has already been called to associate
     185                 :  * memory.
     186                 :  */
     187               4 : static INLINE void NCInstBytesInitInline(NCInstBytes* buffer) {
     188                 : #if NCBUF_CLEAR_CACHE
     189                 :   int i;
     190               4 :   for (i = 0; i < MAX_INST_LENGTH; ++i) {
     191               4 :     buffer->byte[i] = 0;
     192               4 :   }
     193                 : #endif
     194               4 :   NCRemainingMemoryAdvanceInline(buffer->memory);
     195               4 :   buffer->length = 0;
     196               4 : }
     197                 : 
     198                 : /* Returns the indexed byte pointed to by the instruction buffer pointer. */
     199               4 : static INLINE uint8_t NCInstBytesByteInline(const NCInstBytesPtr* ptr, int n) {
     200               4 :   int index = ptr->pos + n;
     201               4 :   if (index < NCBUF_BYTES_LENGTH(ptr->bytes)) {
     202               4 :     return ptr->bytes->byte[index];
     203                 :   } else {
     204               0 :     ptr->bytes->memory->error_fn(NCInstBufferOverflow, ptr->bytes->memory);
     205               0 :     return 0;
     206                 :   }
     207               4 : }
     208                 : 
     209                 : #endif  /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__ */

Generated by: LCOV version 1.7