LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - parsing.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 506 379 74.9 %
Date: 2014-06-18 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                 : // This module contains parsing code to be used with sel_universal.
       8                 : // Since sel_universal is a testing tool and parsing in C++ is no fun,
       9                 : // this code merely aims at being maitainable.
      10                 : // Efficiency and proper dealing with bad input are non-goals.
      11                 : 
      12                 : #include <ctype.h>
      13                 : #include <stdio.h>
      14                 : #include <stdlib.h>
      15                 : #include <string.h>
      16                 : 
      17                 : #if NACL_WINDOWS
      18                 : #include <float.h>
      19                 : #define NACL_ISNAN(d) _isnan(d)
      20                 : #else
      21                 : /* Windows doesn't have the following header files. */
      22                 : # include <math.h>
      23                 : #define NACL_ISNAN(d) isnan(d)
      24                 : #endif  /* NACL_WINDOWS */
      25                 : 
      26                 : #include <iomanip>
      27                 : #include <string>
      28                 : #include <vector>
      29                 : #include <sstream>
      30                 : 
      31                 : #include "native_client/src/include/portability_string.h"
      32                 : 
      33                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      34                 : #include "native_client/src/trusted/sel_universal/parsing.h"
      35                 : #include "native_client/src/shared/platform/nacl_log.h"
      36                 : 
      37                 : using std::stringstream;
      38                 : 
      39                 : 
      40              36 : static uint32_t StringToUint32(string s, size_t pos = 0) {
      41              18 :   return strtoul(s.c_str() + pos, 0, 0);
      42                 : }
      43                 : 
      44                 : 
      45             158 : static int32_t StringToInt32(string s, size_t pos = 0) {
      46              79 :   return strtol(s.c_str() + pos, 0, 0);
      47                 : }
      48                 : 
      49                 : 
      50              20 : static int64_t StringToInt64(string s, size_t pos = 0) {
      51              10 :   return STRTOLL(s.c_str() + pos, 0, 0);
      52                 : }
      53                 : 
      54                 : 
      55              96 : static double StringToDouble(string s, size_t pos = 0) {
      56              48 :   return strtod(s.c_str() + pos, 0);
      57                 : }
      58                 : 
      59                 : // remove typing markup, e.g. i(1234) -> 1234
      60               2 : string GetPayload(string token) {
      61               2 :   return token.substr(2, token.size() - 3);
      62                 : }
      63                 : 
      64                 : // convert strings 5 or i(5) to int32
      65               0 : int32_t ExtractInt32(string token) {
      66               0 :   if (token[0] == 'i' && token[1] == '(') {
      67               0 :     return StringToInt32(token, 2);
      68                 :   }
      69               0 :   return StringToInt32(token);
      70               0 : }
      71                 : 
      72                 : // convert strings 5 or l(5) to int64
      73               0 : int64_t ExtractInt64(string token) {
      74               0 :   if (token[0] == 'l' && token[1] == '(') {
      75               0 :     return StringToInt64(token, 2);
      76                 :   }
      77               0 :   return StringToInt64(token);
      78               0 : }
      79                 : 
      80                 : 
      81               0 : NaClDesc* ExtractDesc(string token, NaClCommandLoop* ncl) {
      82               0 :   if (token[0] == 'h' && token[1] == '(') {
      83               0 :     token = GetPayload(token);
      84               0 :   }
      85               0 :   return ncl->FindDescByName(token);
      86               0 : }
      87                 : 
      88                 : 
      89              20 : static int HandleEscapedOctal(const string s, size_t* pos) {
      90              10 :   if (*pos + 2 >= s.size()) {
      91               0 :     NaClLog(LOG_ERROR, "malformed octal escape");
      92               0 :     return -1;
      93                 :   }
      94                 : 
      95              10 :   int ival =  s[*pos] - '0';
      96              10 :   ++*pos;
      97              10 :   ival = ival * 8 + s[*pos] - '0';
      98              10 :   ++*pos;
      99              10 :   ival = ival * 8 + s[*pos] - '0';
     100              10 :   ++*pos;
     101              10 :   return ival;
     102              10 : }
     103                 : 
     104                 : 
     105              28 : static int HexDigit(char c) {
     106              48 :   if (isdigit(c)) return c - '0';
     107               8 :   else return toupper(c) - 'A' + 10;
     108              28 : }
     109                 : 
     110                 : 
     111              28 : static int HandleEscapedHex(const string s, size_t* pos) {
     112              14 :   if (*pos + 1 >= s.size()) {
     113               0 :     NaClLog(LOG_ERROR, "malformed hex escape");
     114               0 :     return -1;
     115                 :   }
     116              14 :   int ival = HexDigit(s[*pos]);
     117              14 :   ++*pos;
     118              14 :   ival = ival * 16 + HexDigit(s[*pos]);
     119              14 :   ++*pos;
     120              14 :   return ival;
     121              14 : }
     122                 : 
     123                 : 
     124                 : // This should be kept in sync with the SRPC logging escaping done in
     125                 : // src/shared/srpc/rpc_log.c to allow easy capture of logs for testing.
     126              78 : static int HandleEscapedChar(const string s, size_t* pos) {
     127              39 :   if (*pos >= s.size()) return -1;
     128              39 :   switch (s[*pos]) {
     129                 :     case '\\':
     130               2 :       ++*pos;
     131               2 :       return '\\';
     132                 :     case '\"':
     133               5 :       ++*pos;
     134               5 :       return '\"';
     135                 :     case '\'':
     136               0 :       ++*pos;
     137               0 :       return '\'';
     138                 :     case 'a':
     139               0 :       ++*pos;
     140               0 :       return '\a';
     141                 :     case 'b':
     142               2 :       ++*pos;
     143               2 :       return '\b';
     144                 :     case 'f':
     145               2 :       ++*pos;
     146               2 :       return '\f';
     147                 :     case 'n':
     148               2 :       ++*pos;
     149               2 :       return '\n';
     150                 :     case 'r':
     151               0 :       ++*pos;
     152               0 :       return '\r';
     153                 :     case 't':
     154               2 :       ++*pos;
     155               2 :       return '\t';
     156                 :     case 'v':
     157               0 :       ++*pos;
     158               0 :       return '\v';
     159                 : 
     160                 :     case '0':
     161                 :     case '1':
     162                 :     case '2':
     163                 :     case '3':
     164                 :     case '4':
     165                 :     case '5':
     166                 :     case '6':
     167                 :     case '7':
     168              20 :       return HandleEscapedOctal(s, pos);
     169                 : 
     170                 :     case 'x':
     171                 :     case 'X':
     172              14 :       ++*pos;
     173              28 :       return HandleEscapedHex(s, pos);
     174                 : 
     175                 :     default:
     176               0 :       NaClLog(LOG_ERROR, "bad escape\n");
     177               0 :       return -1;
     178                 :   }
     179              39 : }
     180                 : 
     181                 : 
     182                 : // Reads one char from *p and advances *p to the next read point in the input.
     183                 : // This handles some meta characters ('\\', '\"', '\b', '\f', '\n', '\t',
     184                 : // and '\v'), \ddd, where ddd is interpreted as an octal character value, and
     185                 : // \[xX]dd, where dd is interpreted as a hexadecimal character value.
     186             134 : static int ReadOneChar(const string s, size_t* pos) {
     187              67 :   if (*pos >= s.size()) {
     188               0 :     return -1;
     189                 :   }
     190                 : 
     191              67 :   if (s[*pos] == '\\') {
     192              39 :     ++*pos;
     193              78 :     return HandleEscapedChar(s, pos);
     194                 :   }
     195                 : 
     196              28 :   int ival = s[*pos];
     197              28 :   ++*pos;
     198              28 :   return ival;
     199              67 : }
     200                 : 
     201                 : // expects "from" to point to leading \" and returns offset to trailing \"
     202                 : // a zero return value indicates an error
     203               8 : static size_t ScanEscapeString(const string s, size_t from) {
     204                 :   // skip initial quotes
     205               4 :   size_t pos = from + 1;
     206               8 :   int ival = ReadOneChar(s, &pos);
     207              13 :   while (-1 != ival) {
     208               9 :     if ('\"' == ival) {
     209               4 :       return pos;
     210                 :     }
     211              10 :     ival = ReadOneChar(s, &pos);
     212               5 :   }
     213               0 :   NaClLog(LOG_ERROR, "unterminated string\n");
     214               0 :   return 0;
     215               4 : }
     216                 : 
     217                 : // input looks like:
     218                 : //   rpc fib i(1) i(1) * I(10)
     219                 : //   rpc rubyEval s("3.times{ puts 'lala' }") * s("")
     220                 : //   rpc double_array D(5,3.1,1.4,4.1,1.5,5.9) * D(5)
     221                 : //   rpc invalid_handle h(-1) *
     222                 : //   rpc char_array C(9,A\b\f\n\t\"\"\\\x7F) * C(9)
     223             116 : void Tokenize(string line, vector<string>* tokens) {
     224              58 :   size_t pos_start = 0;
     225                 : 
     226             407 :   while (pos_start < line.size()) {
     227                 :     // skip over leading white space
     228             582 :     while (pos_start < line.size()) {
     229             291 :       const char c = line[pos_start];
     230             291 :       if (isspace((unsigned char)c)) {
     231               0 :         pos_start++;
     232               0 :       } else {
     233             291 :         break;
     234                 :       }
     235               0 :     }
     236                 : 
     237             291 :     if (pos_start >= line.size()) break;  //  <<< LOOP EXIT
     238                 : 
     239             291 :     size_t pos_end = pos_start;
     240            2012 :     while (pos_end < line.size()) {
     241            1692 :       const char c = line[pos_end];
     242                 : 
     243            1692 :       if (isspace((unsigned char)c)) {
     244             262 :         break;
     245            1430 :       } else if (c == '\"') {
     246                 :         // NOTE: quotes are only really relevant in s("...").
     247               8 :         size_t end = ScanEscapeString(line, pos_end);
     248               4 :         if (end == 0) {
     249               0 :           NaClLog(LOG_ERROR, "unterminated string constant\n");
     250               0 :           return;
     251                 :         }
     252                 : 
     253               4 :         pos_end = end;
     254               4 :       } else {
     255            1426 :         pos_end++;
     256                 :       }
     257            1430 :     }
     258                 : 
     259             582 :     tokens->push_back(line.substr(pos_start, pos_end - pos_start));
     260                 : 
     261             291 :     pos_start = pos_end + 1;
     262             291 :   }
     263              58 : }
     264                 : 
     265                 : 
     266              14 : static size_t FindComma(string s, size_t start) {
     267               7 :   size_t i;
     268              30 :   for (i = start; i < s.size(); ++i) {
     269              15 :     if (s[i] == ',') {
     270               7 :       break;
     271                 :     }
     272               8 :   }
     273               7 :   return i;
     274                 : }
     275                 : 
     276                 : //  input looks like:
     277                 : //     I(5,1,2,3,4,5)
     278                 : //     L(5,1,2,3,4,5)
     279              11 : static uint32_t SplitArray(string s,
     280              11 :                            vector<string>* tokens,
     281              11 :                            bool input,
     282              11 :                            bool check_size = true) {
     283              11 :   tokens->clear();
     284              22 :   uint32_t dim = StringToUint32(s, 2);
     285                 : 
     286              18 :   if (!input) return dim;
     287                 : 
     288               8 :   size_t i = 1 + FindComma(s, 2);
     289               4 :   size_t start = i;
     290                 : 
     291             146 :   for (; i < s.size(); ++i) {
     292             124 :     if (s[i] == ',' || s[i] == ')') {
     293              36 :       tokens->push_back(s.substr(start, i - start));
     294              18 :       start = i + 1;
     295              18 :     }
     296              69 :   }
     297                 : 
     298               7 :   if (check_size && dim != tokens->size()) {
     299               0 :     NaClLog(LOG_ERROR, "array token number mismatch %d vs %d\n",
     300               0 :             static_cast<int>(dim), static_cast<int>(tokens->size()));
     301               0 :     return 0;
     302                 :   }
     303                 : 
     304               4 :   return dim;
     305              11 : }
     306                 : 
     307                 : //  input looks like:
     308                 : //     C(12,\110\145\154\154\157,\x77\x6f\x72\x6C\x64\X2E)
     309                 : //     C(9,A\b\f\n\t\"\"\\\x7F)
     310              14 : static uint32_t SplitArrayChar(string s, vector<string>* tokens, bool input) {
     311               7 :   tokens->clear();
     312              14 :   uint32_t dim = StringToUint32(s, 2);
     313                 : 
     314              11 :   if (!input) return dim;
     315                 : 
     316               6 :   size_t i = 1 + FindComma(s, 2);
     317               3 :   size_t start = i;
     318                 : 
     319              61 :   while (i < s.size() && s[i] != ')') {
     320              52 :      ReadOneChar(s, &i);
     321              52 :      tokens->push_back(s.substr(start, i - start));
     322              26 :      start = i;
     323              26 :   }
     324                 : 
     325               3 :   if (dim != tokens->size()) {
     326               0 :     NaClLog(LOG_ERROR, "array token number mismatch %d vs %d\n",
     327               0 :             static_cast<int>(dim), static_cast<int>(tokens->size()));
     328               0 :     return 0;
     329                 :   }
     330                 : 
     331               3 :   return dim;
     332               7 : }
     333                 : 
     334                 : 
     335                 : // substitute ${var_name} strings in s
     336             582 : string SubstituteVars(string s, NaClCommandLoop* ncl) {
     337             582 :   string result("");
     338             582 :   string var("");
     339             291 :   bool scanning_var_name = false;
     340            5193 :   for (size_t i = 0; i < s.size(); ++i) {
     341            1440 :     if (scanning_var_name) {
     342              46 :       if (s[i] == '{') {
     343               2 :         continue;
     344              42 :       } else if (s[i] == '}') {
     345              10 :         result.append(ncl->GetVariable(var));
     346               2 :         scanning_var_name = false;
     347               2 :       } else {
     348              38 :         var.push_back(s[i]);
     349                 :       }
     350              21 :     } else {
     351            2834 :       if (s[i] == '$') {
     352               2 :         scanning_var_name = true;
     353               2 :         var = "";
     354               2 :       } else {
     355            2830 :         result.push_back(s[i]);
     356                 :       }
     357                 :     }
     358            1438 :   }
     359                 : 
     360             291 :   return result;
     361             873 : }
     362                 : 
     363                 : 
     364               4 : static string UnescapeString(string s) {
     365               8 :   string result("");
     366               4 :   size_t i = 3;
     367              42 :   while (i < s.size() && s[i] != '"') {
     368              24 :     int val = ReadOneChar(s, &i);
     369               6 :     result.push_back(val);
     370               6 :   }
     371                 : 
     372               4 :   return result;
     373               8 : }
     374                 : 
     375                 : // initialize a single srpc arg using the information found in token.
     376                 : // input indicates whether this is an input our an output arg.
     377                 : // Output args are handled slightly different especially in the array case
     378                 : // where the merely allocate space but do not initialize it.
     379             145 : bool ParseArg(NaClSrpcArg* arg,
     380             145 :               string token,
     381             145 :               bool input,
     382             145 :               NaClCommandLoop* ncl) {
     383             145 :   if (token.size() <= 2) {
     384               0 :     NaClLog(LOG_ERROR, "parameter too short: %s\n", token.c_str());
     385               0 :     return false;
     386                 :   }
     387                 : 
     388             145 :   const char type = token[0];
     389             290 :   vector<string> array_tokens;
     390                 : 
     391                 :   // Initialize the argument slot.  This enables freeing on failures.
     392             145 :   memset(arg, 0, sizeof(*arg));
     393                 : 
     394             290 :   NaClLog(3, "TOKEN %s\n", token.c_str());
     395             725 :   if (token[1] != '(' || token[token.size() - 1] != ')') {
     396               0 :     NaClLog(LOG_ERROR, "malformed token '%s'\n", token.c_str());
     397               0 :     return false;
     398                 :   }
     399                 : 
     400             145 :   int dim;
     401             145 :   switch (type) {
     402                 :     case NACL_SRPC_ARG_TYPE_INVALID:
     403               0 :       arg->tag = NACL_SRPC_ARG_TYPE_INVALID;
     404               0 :       break;
     405                 :     case NACL_SRPC_ARG_TYPE_BOOL:
     406               4 :       arg->tag = NACL_SRPC_ARG_TYPE_BOOL;
     407              12 :       arg->u.bval = StringToInt32(token, 2);
     408               4 :       break;
     409                 :     case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
     410               7 :       arg->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
     411              21 :       dim = SplitArrayChar(token, &array_tokens, input);
     412              14 :       arg->arrays.carr = static_cast<char*>(calloc(dim, sizeof(char)));
     413               7 :       if (NULL == arg->arrays.carr) {
     414               0 :         NaClLog(LOG_ERROR, "alloc problem\n");
     415               0 :         return false;
     416                 :       }
     417               7 :       arg->u.count = dim;
     418               7 :       if (input) {
     419              58 :         for (int i = 0; i < dim; ++i) {
     420              26 :           size_t dummy = 0;
     421             104 :           arg->arrays.carr[i] = ReadOneChar(array_tokens[i], &dummy);
     422              26 :         }
     423               3 :       }
     424               7 :       break;
     425                 :     // This is alternative representation for CHAR_ARRAY:
     426                 :     // R stands for "record".
     427                 :     // example: R(8,1:0x44,2:1999,4:0,"a")
     428                 :     // NOTE: commas inside of strings must currently be escaped
     429                 :     case 'R':
     430               1 :       arg->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
     431               3 :       dim = SplitArray(token, &array_tokens, input, false);
     432               2 :       arg->arrays.carr = static_cast<char*>(calloc(dim, sizeof(char)));
     433               1 :       if (NULL == arg->arrays.carr) {
     434               0 :         NaClLog(LOG_ERROR, "alloc problem\n");
     435               0 :         return false;
     436                 :       }
     437               1 :       arg->u.count = dim;
     438               1 :       if (input) {
     439               1 :         int curr = 0;
     440              12 :         for (size_t i = 0; i < array_tokens.size(); ++i) {
     441               6 :           string s = array_tokens[i];
     442               6 :           if (s[0] == '"') {
     443                 :             // the format of the token is: "string"
     444               0 :             size_t p = 1;
     445               0 :             while (p < s.size() && s[p] != '"') {
     446               0 :               if (curr >= dim) {
     447               0 :                 NaClLog(LOG_ERROR, "size overflow in 'R' string parameter\n");
     448               0 :                 return false;
     449                 :               }
     450               0 :               int val = ReadOneChar(s, &p);
     451               0 :               arg->arrays.carr[curr] = (char) val;
     452               0 :               ++curr;
     453               0 :             }
     454               0 :           } else {
     455                 :             // the format of the  token is: <num_bytes_single_digit>:<value>
     456               6 :             int num_bytes = s[0] - '0';
     457              18 :             if (s.size() < 3 || num_bytes < 1 || 8 < num_bytes || s[1] != ':') {
     458               0 :               NaClLog(LOG_ERROR, "poorly formatted 'R' parameter\n");
     459               0 :               return false;
     460                 :             }
     461              12 :             int64_t val = StringToInt64(s, 2);
     462              13 :             while (num_bytes) {
     463               7 :               --num_bytes;
     464               7 :               if (curr >= dim) {
     465               0 :                 NaClLog(LOG_ERROR, "size overflow in 'R' int parameter\n");
     466               0 :                 return false;
     467                 :               }
     468               7 :               arg->arrays.carr[curr] = val & 0xff;
     469               7 :               ++curr;
     470               7 :               val >>= 8;
     471               7 :             }
     472                 :           }
     473               9 :         }
     474                 : 
     475               1 :         if (curr != dim) {
     476               0 :            NaClLog(LOG_ERROR, "size mismatch in 'R' parameter\n");
     477               0 :            return false;
     478                 :         }
     479               1 :       }
     480               1 :       break;
     481                 :     case NACL_SRPC_ARG_TYPE_DOUBLE:
     482              43 :       arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE;
     483             129 :       arg->u.dval = StringToDouble(token, 2);
     484              43 :       break;
     485                 :     case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
     486               2 :       arg->tag = NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY;
     487               6 :       dim = SplitArray(token, &array_tokens, input);
     488               4 :       arg->arrays.darr = static_cast<double*>(calloc(dim, sizeof(double)));
     489               2 :       if (NULL == arg->arrays.darr) {
     490               0 :         NaClLog(LOG_ERROR, "alloc problem\n");
     491               0 :         return false;
     492                 :       }
     493               2 :       arg->u.count = dim;
     494               2 :       if (input) {
     495              12 :         for (int i = 0; i < dim; ++i) {
     496              20 :           arg->arrays.darr[i] = StringToDouble(array_tokens[i]);
     497               5 :         }
     498               1 :       }
     499               2 :       break;
     500                 :     case NACL_SRPC_ARG_TYPE_HANDLE:
     501               4 :       arg->tag = NACL_SRPC_ARG_TYPE_HANDLE;
     502               4 :       if (input) {
     503              10 :         arg->u.hval = ncl->FindDescByName(GetPayload(token));
     504               2 :       }
     505               4 :       break;
     506                 :     case NACL_SRPC_ARG_TYPE_INT:
     507              70 :       arg->tag = NACL_SRPC_ARG_TYPE_INT;
     508             210 :       arg->u.ival = StringToInt32(token, 2);
     509              70 :       break;
     510                 :     case NACL_SRPC_ARG_TYPE_INT_ARRAY:
     511               6 :       arg->tag = NACL_SRPC_ARG_TYPE_INT_ARRAY;
     512              18 :       dim = SplitArray(token, &array_tokens, input);
     513              12 :       arg->arrays.iarr = static_cast<int32_t*>(calloc(dim, sizeof(int32_t)));
     514               6 :       if (NULL == arg->arrays.iarr) {
     515               0 :         return false;
     516                 :       }
     517               6 :       arg->u.count = dim;
     518               6 :       if (input) {
     519              12 :         for (int i = 0; i < dim; ++i) {
     520              20 :           arg->arrays.iarr[i] = StringToInt32(array_tokens[i]);
     521               5 :         }
     522               1 :       }
     523               6 :       break;
     524                 :     case NACL_SRPC_ARG_TYPE_LONG:
     525               2 :       arg->tag = NACL_SRPC_ARG_TYPE_LONG;
     526               6 :       arg->u.lval = StringToInt64(token, 2);
     527               2 :       break;
     528                 :     case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
     529               2 :       arg->tag = NACL_SRPC_ARG_TYPE_LONG_ARRAY;
     530               6 :       dim = SplitArray(token, &array_tokens, input);
     531               4 :       arg->arrays.larr = static_cast<int64_t*>(calloc(dim, sizeof(int64_t)));
     532               2 :       if (NULL == arg->arrays.larr) {
     533               0 :         NaClLog(LOG_ERROR, "alloc problem\n");
     534               0 :         return false;
     535                 :       }
     536               2 :       arg->u.count = dim;
     537               2 :       if (input) {
     538              12 :         for (int i = 0; i < dim; ++i) {
     539              20 :           arg->arrays.larr[i] = StringToInt64(array_tokens[i]);
     540               5 :         }
     541               1 :       }
     542               2 :       break;
     543                 :     case NACL_SRPC_ARG_TYPE_STRING:
     544               4 :       arg->tag = NACL_SRPC_ARG_TYPE_STRING;
     545                 :       arg->arrays.str =
     546              24 :         strdup(UnescapeString(token).c_str());
     547               4 :       if (NULL == arg->arrays.str) {
     548               0 :         NaClLog(LOG_ERROR, "alloc problem\n");
     549               0 :         return false;
     550                 :       }
     551               4 :       break;
     552                 :       /*
     553                 :        * The two cases below are added to avoid warnings, they are only used
     554                 :        * in the plugin code
     555                 :        */
     556                 :     case NACL_SRPC_ARG_TYPE_OBJECT:
     557                 :     case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
     558                 :     default:
     559               0 :       NaClLog(LOG_ERROR, "unsupported srpc arg type\n");
     560               0 :       return false;
     561                 :   }
     562                 : 
     563             145 :   return true;
     564             290 : }
     565                 : 
     566                 : 
     567               0 : bool OneArgEqual(NaClSrpcArg* arg1, NaClSrpcArg* arg2) {
     568               0 :   if (arg1->tag != arg2->tag) return false;
     569                 : 
     570               0 :   switch (arg1->tag) {
     571                 :     case NACL_SRPC_ARG_TYPE_INVALID:
     572               0 :       return true;
     573                 :     case NACL_SRPC_ARG_TYPE_BOOL:
     574               0 :       return arg1->u.bval == arg2->u.bval;
     575                 :     case NACL_SRPC_ARG_TYPE_DOUBLE:
     576                 :       // TOOD(robertm): tolerate small deltas
     577               0 :       return arg1->u.dval == arg2->u.dval;
     578                 :     case NACL_SRPC_ARG_TYPE_HANDLE:
     579               0 :       return arg1->u.hval == arg2->u.hval;
     580                 :     case NACL_SRPC_ARG_TYPE_INT:
     581               0 :       return arg1->u.ival == arg2->u.ival;
     582                 :     case NACL_SRPC_ARG_TYPE_LONG:
     583               0 :       return arg1->u.lval == arg2->u.lval;
     584                 :     case NACL_SRPC_ARG_TYPE_STRING:
     585               0 :       return string(arg1->arrays.str) == string(arg2->arrays.str);
     586                 : 
     587                 :     case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
     588               0 :       if (arg1->u.count != arg2->u.count) return false;
     589               0 :       for (size_t i = 0; i < arg1->u.count; ++i) {
     590               0 :         if ( arg1->arrays.carr[i] != arg2->arrays.carr[i]) return false;
     591               0 :       }
     592               0 :       return true;
     593                 :     case NACL_SRPC_ARG_TYPE_INT_ARRAY:
     594               0 :       if (arg1->u.count != arg2->u.count) return false;
     595               0 :       for (size_t i = 0; i < arg1->u.count; ++i) {
     596               0 :         if ( arg1->arrays.iarr[i] != arg2->arrays.iarr[i]) return false;
     597               0 :       }
     598               0 :       return true;
     599                 :     case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
     600               0 :       if (arg1->u.count != arg2->u.count) return false;
     601               0 :       for (size_t i = 0; i < arg1->u.count; ++i) {
     602               0 :         if ( arg1->arrays.larr[i] != arg2->arrays.larr[i]) return false;
     603               0 :       }
     604               0 :       return true;
     605                 :     case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
     606               0 :       if (arg1->u.count != arg2->u.count) return false;
     607               0 :       for (size_t i = 0; i < arg1->u.count; ++i) {
     608                 :         // TOOD(robertm): tolerate small deltas
     609               0 :         if ( arg1->arrays.darr[i] != arg2->arrays.darr[i]) return false;
     610               0 :       }
     611               0 :       return true;
     612                 :     case NACL_SRPC_ARG_TYPE_OBJECT:
     613                 :     case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
     614                 :     default:
     615               0 :       NaClLog(LOG_FATAL, "unsupported srpc arg type\n");
     616               0 :       return false;
     617                 :   }
     618               0 : }
     619                 : 
     620                 : 
     621               0 : bool AllArgsEqual(NaClSrpcArg** arg1, NaClSrpcArg** arg2) {
     622               0 :   if (NULL != *arg1 && NULL != *arg2) {
     623               0 :     if (!OneArgEqual(*arg1, *arg2)) return false;
     624               0 :     return AllArgsEqual(++arg1, ++arg2);
     625               0 :   } else if (0 == *arg1 && 0 == *arg2) {
     626               0 :     return true;
     627                 :   } else {
     628               0 :     return false;
     629                 :   }
     630               0 : }
     631                 : 
     632                 : 
     633              90 : bool ParseArgs(NaClSrpcArg** args,
     634              90 :                const vector<string>& tokens,
     635              90 :                size_t start,
     636              90 :                bool input,
     637              90 :                NaClCommandLoop* ncl) {
     638             470 :   for (size_t i = 0; args[i] != NULL; ++i) {
     639             290 :     if (!ParseArg(args[i], tokens[start + i], input, ncl)) {
     640               0 :       return false;
     641                 :     }
     642             145 :   }
     643              90 :   return true;
     644              90 : }
     645                 : 
     646                 : 
     647            1100 : static string StringifyOneChar(unsigned char c) {
     648            1100 :   switch (c) {
     649                 :     case '\"':
     650              12 :       return "\\\"";
     651                 :     case '\b':
     652               6 :       return "\\b";
     653                 :     case '\f':
     654               6 :       return "\\f";
     655                 :     case '\n':
     656              10 :       return "\\n";
     657                 :     case '\t':
     658               6 :       return "\\t";
     659                 :     case '\v':
     660               0 :       return "\\v";
     661                 :     case '\\':
     662               6 :       return "\\\\";
     663                 :     default:
     664                 :      // play it safe and escape closing parens which could
     665                 :      // cause problems when this string is read back
     666            3207 :      if (c < ' ' || 126 < c || c == ')') {
     667              24 :           stringstream result;
     668             144 :           result << "\\x" << std::hex << std::setw(2) <<
     669              48 :             std::setfill('0') << int(c);
     670              24 :           return result.str();
     671              24 :       } else {
     672            1053 :         stringstream result;
     673            1053 :         result << c;
     674            1053 :         return result.str();
     675            1053 :       }
     676                 :   }
     677            1100 : }
     678                 : 
     679                 : 
     680              60 : static string DumpDouble(const double* dval) {
     681              60 :   if (NACL_ISNAN(*dval)) {
     682               4 :     return "NaN";
     683                 :   } else {
     684              58 :     stringstream result;
     685              58 :     result << *dval;
     686              58 :     return result.str();
     687              58 :   }
     688              60 : }
     689                 : 
     690                 : 
     691             208 : string DumpArg(const NaClSrpcArg* arg, NaClCommandLoop* ncl) {
     692             208 :   stringstream result;
     693             208 :   uint32_t count;
     694             208 :   uint32_t i;
     695             208 :   char* p;
     696             208 :   switch (arg->tag) {
     697                 :     case NACL_SRPC_ARG_TYPE_INVALID:
     698               0 :       return "X()";
     699                 :     case NACL_SRPC_ARG_TYPE_BOOL:
     700              18 :       result << "b(" << arg->u.bval << ")";
     701              12 :       return result.str();
     702                 :     case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
     703              12 :       count = arg->u.count;
     704              36 :       result << "C(" << count << ",";
     705             222 :       for (i = 0; i < arg->u.count; ++i)
     706             396 :         result << StringifyOneChar(arg->arrays.carr[i]);
     707              12 :       result << ")";
     708              24 :       return result.str();
     709                 :     case NACL_SRPC_ARG_TYPE_DOUBLE:
     710             225 :       result << "d(" << DumpDouble(&arg->u.dval) << ")";
     711              90 :       return result.str();
     712                 :     case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
     713               3 :       count = arg->u.count;
     714               6 :       result << "D(" << count;
     715              36 :       for (i = 0; i < count; ++i) {
     716              60 :         result << "," << DumpDouble(&(arg->arrays.darr[i]));
     717              15 :       }
     718               3 :       result << ")";
     719               6 :       return result.str();
     720                 :     case NACL_SRPC_ARG_TYPE_HANDLE:
     721              48 :       result << "h(" <<  ncl->AddDescUniquify(arg->u.hval, "imported") << ")";
     722              12 :       return result.str();
     723                 :     case NACL_SRPC_ARG_TYPE_INT:
     724             336 :       result << "i(" << arg->u.ival << ")";
     725             224 :       return result.str();
     726                 :     case NACL_SRPC_ARG_TYPE_INT_ARRAY:
     727              11 :       count = arg->u.count;
     728              22 :       result << "I(" << count;
     729             252 :       for (i = 0; i < count; ++i) {
     730             230 :         result << "," << arg->arrays.iarr[i];
     731             115 :       }
     732              11 :       result << ")";
     733              22 :       return result.str();
     734                 :     case NACL_SRPC_ARG_TYPE_LONG:
     735               9 :       result << "l(" << arg->u.lval << ")";
     736               6 :       return result.str();
     737                 :     case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
     738               3 :       count = arg->u.count;
     739               6 :       result << "L(" << count;
     740              36 :       for (i = 0; i < count; ++i) {
     741              30 :         result << "," << arg->arrays.larr[i];
     742              15 :       }
     743               3 :       result << ")";
     744               6 :       return result.str();
     745                 :     case NACL_SRPC_ARG_TYPE_STRING:
     746               7 :       result << "s(\"";
     747            2016 :       for (p = arg->arrays.str; '\0' != *p; ++p)
     748            4004 :         result << StringifyOneChar(*p);
     749               7 :       result << "\")";
     750              14 :       return result.str();
     751                 :     case NACL_SRPC_ARG_TYPE_OBJECT:
     752                 :     case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
     753                 :     default:
     754               0 :       NaClLog(LOG_ERROR, "unknown or unsupported type '%c'\n", arg->tag);
     755               0 :       return "";
     756                 :   }
     757             208 : }
     758                 : 
     759                 : 
     760              90 : void BuildArgVec(NaClSrpcArg* argv[], NaClSrpcArg arg[], size_t count) {
     761             470 :   for (size_t i = 0; i < count; ++i) {
     762             145 :     NaClSrpcArgCtor(&arg[i]);
     763             145 :     argv[i] = &arg[i];
     764             145 :   }
     765              90 :   argv[count] = NULL;
     766              90 : }
     767                 : 
     768                 : 
     769             268 : void FreeArrayArg(NaClSrpcArg* arg) {
     770             268 :   switch (arg->tag) {
     771                 :     case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
     772               8 :       free(arg->arrays.carr);
     773               8 :       break;
     774                 :     case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
     775               2 :       free(arg->arrays.darr);
     776               2 :       break;
     777                 :     case NACL_SRPC_ARG_TYPE_INT_ARRAY:
     778               6 :       free(arg->arrays.iarr);
     779               6 :       break;
     780                 :     case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
     781               2 :       free(arg->arrays.larr);
     782               2 :       break;
     783                 :     case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
     784                 :     case NACL_SRPC_ARG_TYPE_OBJECT:
     785               0 :       NaClLog(LOG_ERROR, "unsupported srpc arg type\n");
     786               0 :       break;
     787                 :     case NACL_SRPC_ARG_TYPE_STRING:
     788               4 :       free(arg->arrays.str);
     789             127 :       break;
     790                 :     case NACL_SRPC_ARG_TYPE_INVALID:
     791                 :     case NACL_SRPC_ARG_TYPE_BOOL:
     792                 :     case NACL_SRPC_ARG_TYPE_DOUBLE:
     793                 :     case NACL_SRPC_ARG_TYPE_HANDLE:
     794                 :     case NACL_SRPC_ARG_TYPE_INT:
     795                 :     case NACL_SRPC_ARG_TYPE_LONG:
     796                 :     default:
     797             123 :       break;
     798                 :   }
     799             145 : }
     800                 : 
     801                 : 
     802              90 : void FreeArrayArgs(NaClSrpcArg** args) {
     803             470 :   for (size_t i = 0; args[i] != NULL; ++i) {
     804             145 :     FreeArrayArg(args[i]);
     805             145 :   }
     806              90 : }

Generated by: LCOV version 1.7