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

Generated by: LCOV version 1.7