LCOV - code coverage report
Current view: top level - spdk/lib/json - json_parse.c (source / functions) Hit Total Coverage
Test: Combined Lines: 328 354 92.7 %
Date: 2024-12-15 06:38:34 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 434 770 56.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/json.h"
       7                 :            : 
       8                 :            : #include "spdk_internal/utf.h"
       9                 :            : 
      10                 :            : #define SPDK_JSON_MAX_NESTING_DEPTH     64
      11                 :            : 
      12                 :            : static int
      13                 :        492 : hex_value(uint8_t c)
      14                 :            : {
      15                 :            : #define V(x, y) [x] = y + 1
      16                 :            :         static const int8_t val[256] = {
      17                 :            :                 V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
      18                 :            :                 V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
      19                 :            :                 V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
      20                 :            :                 V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
      21                 :            :         };
      22                 :            : #undef V
      23                 :            : 
      24   [ #  #  #  #  :        492 :         return val[c] - 1;
             #  #  #  # ]
      25                 :            : }
      26                 :            : 
      27                 :            : static int
      28                 :        153 : json_decode_string_escape_unicode(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
      29                 :            : {
      30         [ #  # ]:        153 :         uint8_t *str = *strp;
      31                 :            :         int v0, v1, v2, v3;
      32                 :            :         uint32_t val;
      33                 :        153 :         uint32_t surrogate_high = 0;
      34                 :          0 :         int rc;
      35                 :        180 : decode:
      36                 :            :         /* \uXXXX */
      37   [ -  +  #  # ]:        180 :         assert(buf_end > str);
      38                 :            : 
      39   [ +  +  #  #  :        180 :         if (*str++ != '\\') { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      40         [ +  + ]:        174 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      41                 :            : 
      42   [ +  +  #  #  :        171 :         if (*str++ != 'u') { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      43         [ +  + ]:        141 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      44                 :            : 
      45   [ +  +  #  #  :        135 :         if ((v3 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      46         [ +  + ]:        132 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      47                 :            : 
      48   [ +  +  #  #  :        126 :         if ((v2 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      49         [ +  + ]:        123 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      50                 :            : 
      51   [ +  +  #  #  :        120 :         if ((v1 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      52         [ +  + ]:        117 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      53                 :            : 
      54   [ +  +  #  #  :        111 :         if ((v0 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
                   #  # ]
      55         [ +  + ]:        105 :         if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      56                 :            : 
      57   [ -  +  -  +  :        102 :         val = v0 | (v1 << 4) | (v2 << 8) | (v3 << 12);
          -  +  #  #  #  
                #  #  # ]
      58                 :            : 
      59         [ +  + ]:        102 :         if (surrogate_high) {
      60                 :            :                 /* We already parsed the high surrogate, so this should be the low part. */
      61         [ +  + ]:          9 :                 if (!utf16_valid_surrogate_low(val)) {
      62                 :          3 :                         return SPDK_JSON_PARSE_INVALID;
      63                 :            :                 }
      64                 :            : 
      65                 :            :                 /* Convert UTF-16 surrogate pair into codepoint and fall through to utf8_encode. */
      66                 :          6 :                 val = utf16_decode_surrogate_pair(surrogate_high, val);
      67         [ +  + ]:         93 :         } else if (utf16_valid_surrogate_high(val)) {
      68                 :         27 :                 surrogate_high = val;
      69                 :            : 
      70                 :            :                 /*
      71                 :            :                  * We parsed a \uXXXX sequence that decoded to the first half of a
      72                 :            :                  *  UTF-16 surrogate pair, so it must be immediately followed by another
      73                 :            :                  *  \uXXXX escape.
      74                 :            :                  *
      75                 :            :                  * Loop around to get the low half of the surrogate pair.
      76                 :            :                  */
      77         [ -  + ]:         27 :                 if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
      78                 :         27 :                 goto decode;
      79         [ +  + ]:         66 :         } else if (utf16_valid_surrogate_low(val)) {
      80                 :            :                 /*
      81                 :            :                  * We found the second half of surrogate pair without the first half;
      82                 :            :                  *  this is an invalid encoding.
      83                 :            :                  */
      84                 :         12 :                 return SPDK_JSON_PARSE_INVALID;
      85                 :            :         }
      86                 :            : 
      87                 :            :         /*
      88                 :            :          * Convert Unicode escape (or surrogate pair) to UTF-8 in place.
      89                 :            :          *
      90                 :            :          * This is safe (will not write beyond the buffer) because the \uXXXX sequence is 6 bytes
      91                 :            :          *  (or 12 bytes for surrogate pairs), and the longest possible UTF-8 encoding of a
      92                 :            :          *  single codepoint is 4 bytes.
      93                 :            :          */
      94         [ +  + ]:         60 :         if (out) {
      95                 :         30 :                 rc = utf8_encode_unsafe(out, val);
      96                 :          0 :         } else {
      97                 :         30 :                 rc = utf8_codepoint_len(val);
      98                 :            :         }
      99         [ -  + ]:         60 :         if (rc < 0) {
     100                 :          0 :                 return SPDK_JSON_PARSE_INVALID;
     101                 :            :         }
     102                 :            : 
     103         [ #  # ]:         60 :         *strp = str; /* update input pointer */
     104                 :         60 :         return rc; /* return number of bytes decoded */
     105                 :          0 : }
     106                 :            : 
     107                 :            : static int
     108                 :        233 : json_decode_string_escape_twochar(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
     109                 :            : {
     110                 :            :         static const uint8_t escapes[256] = {
     111                 :            :                 ['b'] = '\b',
     112                 :            :                 ['f'] = '\f',
     113                 :            :                 ['n'] = '\n',
     114                 :            :                 ['r'] = '\r',
     115                 :            :                 ['t'] = '\t',
     116                 :            :                 ['/'] = '/',
     117                 :            :                 ['"'] = '"',
     118                 :            :                 ['\\'] = '\\',
     119                 :            :         };
     120         [ #  # ]:        233 :         uint8_t *str = *strp;
     121                 :            :         uint8_t c;
     122                 :            : 
     123   [ -  +  #  # ]:        233 :         assert(buf_end > str);
     124         [ -  + ]:        233 :         if (buf_end - str < 2) {
     125                 :          0 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     126                 :            :         }
     127                 :            : 
     128   [ -  +  #  #  :        233 :         assert(str[0] == '\\');
             #  #  #  # ]
     129                 :            : 
     130   [ #  #  #  #  :        233 :         c = escapes[str[1]];
          #  #  #  #  #  
                      # ]
     131         [ +  + ]:        233 :         if (c) {
     132         [ +  + ]:         80 :                 if (out) {
     133         [ #  # ]:         37 :                         *out = c;
     134                 :          0 :                 }
     135   [ #  #  #  # ]:         80 :                 *strp += 2; /* consumed two bytes */
     136                 :         80 :                 return 1; /* produced one byte */
     137                 :            :         }
     138                 :            : 
     139                 :        153 :         return SPDK_JSON_PARSE_INVALID;
     140                 :          0 : }
     141                 :            : 
     142                 :            : /*
     143                 :            :  * Decode JSON string backslash escape.
     144                 :            :  * \param strp pointer to pointer to first character of escape (the backslash).
     145                 :            :  *  *strp is also advanced to indicate how much input was consumed.
     146                 :            :  *
     147                 :            :  * \return Number of bytes appended to out
     148                 :            :  */
     149                 :            : static int
     150                 :        233 : json_decode_string_escape(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
     151                 :            : {
     152                 :            :         int rc;
     153                 :            : 
     154                 :        233 :         rc = json_decode_string_escape_twochar(strp, buf_end, out);
     155         [ +  + ]:        233 :         if (rc > 0) {
     156                 :         80 :                 return rc;
     157                 :            :         }
     158                 :            : 
     159                 :        153 :         return json_decode_string_escape_unicode(strp, buf_end, out);
     160                 :          0 : }
     161                 :            : 
     162                 :            : /*
     163                 :            :  * Decode JSON string in place.
     164                 :            :  *
     165                 :            :  * \param str_start Pointer to the beginning of the string (the opening " character).
     166                 :            :  *
     167                 :            :  * \return Number of bytes in decoded string (beginning from start).
     168                 :            :  */
     169                 :            : static int
     170                 :    1154421 : json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint32_t flags)
     171                 :            : {
     172                 :    1154421 :         uint8_t *str = str_start;
     173         [ +  - ]:    1154421 :         uint8_t *out = str_start + 1; /* Decode string in place (skip the initial quote) */
     174                 :            :         int rc;
     175                 :            : 
     176         [ +  + ]:    1154421 :         if (buf_end - str_start < 2) {
     177                 :            :                 /*
     178                 :            :                  * Shortest valid string (the empty string) is two bytes (""),
     179                 :            :                  *  so this can't possibly be valid
     180                 :            :                  */
     181         [ #  # ]:         18 :                 *str_end = str;
     182                 :         18 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     183                 :            :         }
     184                 :            : 
     185   [ +  +  +  -  :    1154403 :         if (*str++ != '"') {
                   -  + ]
     186         [ #  # ]:          0 :                 *str_end = str;
     187                 :          0 :                 return SPDK_JSON_PARSE_INVALID;
     188                 :            :         }
     189                 :            : 
     190         [ +  + ]:   12057650 :         while (str < buf_end) {
     191   [ +  +  +  -  :   12057554 :                 if (str[0] == '"') {
                   +  + ]
     192                 :            :                         /*
     193                 :            :                          * End of string.
     194                 :            :                          * Update str_end to point at next input byte and return output length.
     195                 :            :                          */
     196   [ +  -  +  - ]:    1153974 :                         *str_end = str + 1;
     197         [ +  - ]:    1153974 :                         return out - str_start - 1;
     198   [ +  +  +  -  :   10903580 :                 } else if (str[0] == '\\') {
                   -  + ]
     199                 :        233 :                         rc = json_decode_string_escape(&str, buf_end,
     200         [ +  + ]:        233 :                                                        flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE ? out : NULL);
     201   [ -  +  #  # ]:        233 :                         assert(rc != 0);
     202         [ +  + ]:        233 :                         if (rc < 0) {
     203         [ #  # ]:         93 :                                 *str_end = str;
     204                 :         93 :                                 return rc;
     205                 :            :                         }
     206         [ #  # ]:        140 :                         out += rc;
     207   [ +  +  +  -  :   10903347 :                 } else if (str[0] <= 0x1f) {
                   +  - ]
     208                 :            :                         /* control characters must be escaped */
     209         [ #  # ]:        105 :                         *str_end = str;
     210                 :        105 :                         return SPDK_JSON_PARSE_INVALID;
     211                 :            :                 } else {
     212                 :   10903242 :                         rc = utf8_valid(str, buf_end);
     213         [ +  + ]:   10903242 :                         if (rc == 0) {
     214         [ #  # ]:          0 :                                 *str_end = str;
     215                 :          0 :                                 return SPDK_JSON_PARSE_INCOMPLETE;
     216         [ +  + ]:   10903242 :                         } else if (rc < 0) {
     217         [ #  # ]:        135 :                                 *str_end = str;
     218                 :        135 :                                 return SPDK_JSON_PARSE_INVALID;
     219                 :            :                         }
     220                 :            : 
     221   [ +  -  +  +  :   10903107 :                         if (out && out != str && (flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE)) {
                   +  + ]
     222   [ -  +  -  + ]:        113 :                                 memmove(out, str, rc);
     223                 :          0 :                         }
     224         [ +  - ]:   10903107 :                         out += rc;
     225         [ +  - ]:   10903107 :                         str += rc;
     226                 :            :                 }
     227                 :            :         }
     228                 :            : 
     229                 :            :         /* If execution gets here, we ran out of buffer. */
     230         [ #  # ]:         96 :         *str_end = str;
     231                 :         96 :         return SPDK_JSON_PARSE_INCOMPLETE;
     232                 :      28148 : }
     233                 :            : 
     234                 :            : static int
     235                 :     227916 : json_valid_number(uint8_t *start, uint8_t *buf_end)
     236                 :            : {
     237                 :     227916 :         uint8_t *p = start;
     238                 :            :         uint8_t c;
     239                 :            : 
     240         [ -  + ]:     227916 :         if (p >= buf_end) { return -1; }
     241                 :            : 
     242   [ +  -  +  - ]:     227916 :         c = *p++;
     243   [ +  +  +  + ]:     227916 :         if (c >= '1' && c <= '9') { goto num_int_digits; }
     244         [ +  + ]:      69260 :         if (c == '0') { goto num_frac_or_exp; }
     245         [ +  - ]:        158 :         if (c == '-') { goto num_int_first_digit; }
     246         [ #  # ]:          0 :         p--;
     247                 :          0 :         goto done_invalid;
     248                 :            : 
     249                 :        158 : num_int_first_digit:
     250         [ +  + ]:        158 :         if (spdk_likely(p != buf_end)) {
     251   [ #  #  #  # ]:        155 :                 c = *p++;
     252         [ +  + ]:        155 :                 if (c == '0') { goto num_frac_or_exp; }
     253   [ +  +  +  - ]:        131 :                 if (c >= '1' && c <= '9') { goto num_int_digits; }
     254         [ #  # ]:          3 :                 p--;
     255                 :          0 :         }
     256                 :          6 :         goto done_invalid;
     257                 :            : 
     258                 :     154036 : num_int_digits:
     259         [ +  + ]:     368886 :         if (spdk_likely(p != buf_end)) {
     260   [ +  -  +  - ]:     368862 :                 c = *p++;
     261   [ +  +  +  + ]:     368862 :                 if (c >= '0' && c <= '9') { goto num_int_digits; }
     262         [ +  + ]:     158760 :                 if (c == '.') { goto num_frac_first_digit; }
     263   [ +  +  +  + ]:     158628 :                 if (c == 'e' || c == 'E') { goto num_exp_sign; }
     264         [ +  - ]:     158592 :                 p--;
     265                 :       4748 :         }
     266                 :     158616 :         goto done_valid;
     267                 :            : 
     268                 :      66266 : num_frac_or_exp:
     269         [ +  + ]:      69126 :         if (spdk_likely(p != buf_end)) {
     270   [ +  -  +  - ]:      69096 :                 c = *p++;
     271         [ -  + ]:      69096 :                 if (c == '.') { goto num_frac_first_digit; }
     272   [ +  +  -  + ]:      69096 :                 if (c == 'e' || c == 'E') { goto num_exp_sign; }
     273         [ +  - ]:      69066 :                 p--;
     274                 :       2860 :         }
     275                 :      69096 :         goto done_valid;
     276                 :            : 
     277                 :        132 : num_frac_first_digit:
     278         [ +  + ]:        132 :         if (spdk_likely(p != buf_end)) {
     279   [ #  #  #  # ]:        126 :                 c = *p++;
     280   [ +  +  +  + ]:        126 :                 if (c >= '0' && c <= '9') { goto num_frac_digits; }
     281         [ #  # ]:          6 :                 p--;
     282                 :          0 :         }
     283                 :         12 :         goto done_invalid;
     284                 :            : 
     285                 :        492 : num_frac_digits:
     286         [ +  + ]:        492 :         if (spdk_likely(p != buf_end)) {
     287   [ #  #  #  # ]:        462 :                 c = *p++;
     288   [ +  +  +  + ]:        462 :                 if (c >= '0' && c <= '9') { goto num_frac_digits; }
     289   [ +  +  -  + ]:         90 :                 if (c == 'e' || c == 'E') { goto num_exp_sign; }
     290         [ #  # ]:         42 :                 p--;
     291                 :          0 :         }
     292                 :         72 :         goto done_valid;
     293                 :            : 
     294                 :        114 : num_exp_sign:
     295         [ +  - ]:        114 :         if (spdk_likely(p != buf_end)) {
     296   [ #  #  #  # ]:        114 :                 c = *p++;
     297   [ +  +  +  + ]:        114 :                 if (c >= '0' && c <= '9') { goto num_exp_digits; }
     298   [ +  +  +  + ]:         72 :                 if (c == '-' || c == '+') { goto num_exp_first_digit; }
     299         [ #  # ]:          3 :                 p--;
     300                 :          0 :         }
     301                 :          3 :         goto done_invalid;
     302                 :            : 
     303                 :         69 : num_exp_first_digit:
     304         [ +  + ]:         69 :         if (spdk_likely(p != buf_end)) {
     305   [ #  #  #  # ]:         63 :                 c = *p++;
     306   [ +  +  +  - ]:         63 :                 if (c >= '0' && c <= '9') { goto num_exp_digits; }
     307         [ #  # ]:          6 :                 p--;
     308                 :          0 :         }
     309                 :         12 :         goto done_invalid;
     310                 :            : 
     311                 :         99 : num_exp_digits:
     312         [ +  + ]:        189 :         if (spdk_likely(p != buf_end)) {
     313   [ #  #  #  # ]:         99 :                 c = *p++;
     314   [ +  +  +  - ]:         99 :                 if (c >= '0' && c <= '9') { goto num_exp_digits; }
     315         [ #  # ]:          9 :                 p--;
     316                 :          0 :         }
     317                 :         99 :         goto done_valid;
     318                 :            : 
     319                 :     220275 : done_valid:
     320                 :            :         /* Valid end state */
     321                 :     227883 :         return p - start;
     322                 :            : 
     323                 :         33 : done_invalid:
     324                 :            :         /* Invalid end state */
     325         [ +  + ]:         33 :         if (p == buf_end) {
     326                 :            :                 /* Hit the end of the buffer - the stream is incomplete. */
     327                 :         15 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     328                 :            :         }
     329                 :            : 
     330                 :            :         /* Found an invalid character in an invalid end state */
     331                 :         18 :         return SPDK_JSON_PARSE_INVALID;
     332                 :       7608 : }
     333                 :            : 
     334                 :            : static int
     335                 :         60 : json_valid_comment(const uint8_t *start, const uint8_t *buf_end)
     336                 :            : {
     337                 :         60 :         const uint8_t *p = start;
     338                 :            :         bool multiline;
     339                 :            : 
     340   [ -  +  #  # ]:         60 :         assert(buf_end > p);
     341         [ +  + ]:         60 :         if (buf_end - p < 2) {
     342                 :          3 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     343                 :            :         }
     344                 :            : 
     345   [ -  +  #  #  :         57 :         if (p[0] != '/') {
                   #  # ]
     346                 :          0 :                 return SPDK_JSON_PARSE_INVALID;
     347                 :            :         }
     348   [ +  +  #  #  :         57 :         if (p[1] == '*') {
                   #  # ]
     349                 :         27 :                 multiline = true;
     350   [ +  +  #  #  :         30 :         } else if (p[1] == '/') {
                   #  # ]
     351                 :         27 :                 multiline = false;
     352                 :          0 :         } else {
     353                 :          3 :                 return SPDK_JSON_PARSE_INVALID;
     354                 :            :         }
     355         [ #  # ]:         54 :         p += 2;
     356                 :            : 
     357   [ +  +  #  # ]:         54 :         if (multiline) {
     358   [ +  -  #  # ]:        189 :                 while (p != buf_end - 1) {
     359   [ +  +  +  -  :        189 :                         if (p[0] == '*' && p[1] == '/') {
          #  #  #  #  #  
                #  #  # ]
     360                 :            :                                 /* Include the terminating star and slash in the comment */
     361         [ #  # ]:         27 :                                 return p - start + 2;
     362                 :            :                         }
     363         [ #  # ]:        162 :                         p++;
     364                 :            :                 }
     365                 :          0 :         } else {
     366         [ +  + ]:        156 :                 while (p != buf_end) {
     367   [ +  +  +  +  :        150 :                         if (*p == '\r' || *p == '\n') {
             #  #  #  # ]
     368                 :            :                                 /* Do not include the line terminator in the comment */
     369                 :         21 :                                 return p - start;
     370                 :            :                         }
     371         [ #  # ]:        129 :                         p++;
     372                 :            :                 }
     373                 :            :         }
     374                 :            : 
     375                 :          6 :         return SPDK_JSON_PARSE_INCOMPLETE;
     376                 :          0 : }
     377                 :            : 
     378                 :            : struct json_literal {
     379                 :            :         enum spdk_json_val_type type;
     380                 :            :         uint32_t len;
     381                 :            :         uint8_t str[8];
     382                 :            : };
     383                 :            : 
     384                 :            : /*
     385                 :            :  * JSON only defines 3 possible literals; they can be uniquely identified by bits
     386                 :            :  *  3 and 4 of the first character:
     387                 :            :  *   'f' = 0b11[00]110
     388                 :            :  *   'n' = 0b11[01]110
     389                 :            :  *   't' = 0b11[10]100
     390                 :            :  * These two bits can be used as an index into the g_json_literals array.
     391                 :            :  */
     392                 :            : static const struct json_literal g_json_literals[] = {
     393                 :            :         {SPDK_JSON_VAL_FALSE, 5, "false"},
     394                 :            :         {SPDK_JSON_VAL_NULL,  4, "null"},
     395                 :            :         {SPDK_JSON_VAL_TRUE,  4, "true"},
     396                 :            :         {}
     397                 :            : };
     398                 :            : 
     399                 :            : static int
     400                 :      94183 : match_literal(const uint8_t *start, const uint8_t *end, const uint8_t *literal, size_t len)
     401                 :            : {
     402   [ +  +  #  # ]:      94183 :         assert(end >= start);
     403         [ +  + ]:      94183 :         if ((size_t)(end - start) < len) {
     404                 :         18 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     405                 :            :         }
     406                 :            : 
     407   [ +  +  +  +  :      94165 :         if (memcmp(start, literal, len) != 0) {
                   +  + ]
     408                 :          9 :                 return SPDK_JSON_PARSE_INVALID;
     409                 :            :         }
     410                 :            : 
     411                 :      94156 :         return len;
     412                 :       2030 : }
     413                 :            : 
     414                 :            : ssize_t
     415                 :     148648 : spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t num_values,
     416                 :            :                 void **end, uint32_t flags)
     417                 :            : {
     418                 :     148648 :         uint8_t *json_end = json + size;
     419                 :      49716 :         enum spdk_json_val_type containers[SPDK_JSON_MAX_NESTING_DEPTH];
     420                 :      49716 :         size_t con_value[SPDK_JSON_MAX_NESTING_DEPTH];
     421                 :     148648 :         enum spdk_json_val_type con_type = SPDK_JSON_VAL_INVALID;
     422                 :     148648 :         bool trailing_comma = false;
     423                 :     148648 :         size_t depth = 0; /* index into containers */
     424                 :     148648 :         size_t cur_value = 0; /* index into values */
     425                 :            :         size_t con_start_value;
     426                 :     148648 :         uint8_t *data = json;
     427                 :      49716 :         uint8_t *new_data;
     428                 :     148648 :         int rc = 0;
     429                 :            :         const struct json_literal *lit;
     430                 :            :         enum {
     431                 :            :                 STATE_VALUE, /* initial state */
     432                 :            :                 STATE_VALUE_SEPARATOR, /* value separator (comma) */
     433                 :            :                 STATE_NAME, /* "name": value */
     434                 :            :                 STATE_NAME_SEPARATOR, /* colon */
     435                 :            :                 STATE_END, /* parsed the complete value, so only whitespace is valid */
     436                 :     148648 :         } state = STATE_VALUE;
     437                 :            : 
     438                 :            : #define ADD_VALUE(t, val_start_ptr, val_end_ptr) \
     439                 :            :         if (values && cur_value < num_values) { \
     440                 :            :                 values[cur_value].type = t; \
     441                 :            :                 values[cur_value].start = val_start_ptr; \
     442                 :            :                 values[cur_value].len = val_end_ptr - val_start_ptr; \
     443                 :            :         } \
     444                 :            :         cur_value++
     445                 :            : 
     446         [ +  + ]:    7508786 :         while (data < json_end) {
     447         [ +  - ]:    7464135 :                 uint8_t c = *data;
     448                 :            : 
     449   [ +  +  +  +  :    7464135 :                 switch (c) {
          +  +  +  +  +  
                      + ]
     450                 :    3883885 :                 case ' ':
     451                 :            :                 case '\t':
     452                 :            :                 case '\r':
     453                 :            :                 case '\n':
     454                 :            :                         /* Whitespace is allowed between any tokens. */
     455         [ +  - ]:    4128351 :                         data++;
     456                 :    4128351 :                         break;
     457                 :            : 
     458                 :      92153 :                 case 't':
     459                 :            :                 case 'f':
     460                 :            :                 case 'n':
     461                 :            :                         /* true, false, or null */
     462         [ +  + ]:      94183 :                         if (state != STATE_VALUE) { goto done_invalid; }
     463   [ +  -  +  -  :      94183 :                         lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */
                   +  - ]
     464   [ +  +  +  -  :      94183 :                         assert(lit->str[0] == c);
          +  -  +  -  #  
                      # ]
     465   [ +  -  +  -  :      94183 :                         rc = match_literal(data, json_end, lit->str, lit->len);
                   +  - ]
     466         [ +  + ]:      94183 :                         if (rc < 0) { goto done_rc; }
     467   [ +  +  +  +  :      94156 :                         ADD_VALUE(lit->type, data, data + rc);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     468         [ +  - ]:      94156 :                         data += rc;
     469         [ +  + ]:      94156 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     470                 :      94156 :                         trailing_comma = false;
     471                 :      94156 :                         break;
     472                 :            : 
     473                 :    1126273 :                 case '"':
     474   [ +  +  +  + ]:    1154421 :                         if (state != STATE_VALUE && state != STATE_NAME) { goto done_invalid; }
     475                 :    1154421 :                         rc = json_decode_string(data, json_end, &new_data, flags);
     476         [ +  + ]:    1154421 :                         if (rc < 0) {
     477                 :        447 :                                 data = new_data;
     478                 :        447 :                                 goto done_rc;
     479                 :            :                         }
     480                 :            :                         /*
     481                 :            :                          * Start is data + 1 to skip initial quote.
     482                 :            :                          * Length is data + rc - 1 to skip both quotes.
     483                 :            :                          */
     484   [ +  +  +  +  :    1153974 :                         ADD_VALUE(state == STATE_VALUE ? SPDK_JSON_VAL_STRING : SPDK_JSON_VAL_NAME,
          +  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     485                 :            :                                   data + 1, data + rc - 1);
     486                 :    1153974 :                         data = new_data;
     487         [ +  + ]:    1153974 :                         if (state == STATE_NAME) {
     488                 :     781805 :                                 state = STATE_NAME_SEPARATOR;
     489                 :      20226 :                         } else {
     490         [ +  + ]:     372169 :                                 state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     491                 :            :                         }
     492                 :    1153974 :                         trailing_comma = false;
     493                 :    1153974 :                         break;
     494                 :            : 
     495                 :     220314 :                 case '-':
     496                 :            :                 case '0':
     497                 :            :                 case '1':
     498                 :            :                 case '2':
     499                 :            :                 case '3':
     500                 :            :                 case '4':
     501                 :            :                 case '5':
     502                 :            :                 case '6':
     503                 :            :                 case '7':
     504                 :            :                 case '8':
     505                 :            :                 case '9':
     506         [ +  + ]:     227922 :                         if (state != STATE_VALUE) { goto done_invalid; }
     507                 :     227916 :                         rc = json_valid_number(data, json_end);
     508         [ +  + ]:     227916 :                         if (rc < 0) { goto done_rc; }
     509   [ +  +  +  +  :     227883 :                         ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     510         [ +  - ]:     227883 :                         data += rc;
     511         [ +  + ]:     227883 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     512                 :     227883 :                         trailing_comma = false;
     513                 :     227883 :                         break;
     514                 :            : 
     515                 :     236847 :                 case '{':
     516                 :            :                 case '[':
     517         [ -  + ]:     242875 :                         if (state != STATE_VALUE) { goto done_invalid; }
     518         [ +  + ]:     242875 :                         if (depth == SPDK_JSON_MAX_NESTING_DEPTH) {
     519                 :          3 :                                 rc = SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED;
     520                 :          3 :                                 goto done_rc;
     521                 :            :                         }
     522         [ +  + ]:     242872 :                         if (c == '{') {
     523                 :     222689 :                                 con_type = SPDK_JSON_VAL_OBJECT_BEGIN;
     524                 :     222689 :                                 state = STATE_NAME;
     525                 :       5546 :                         } else {
     526                 :      20183 :                                 con_type = SPDK_JSON_VAL_ARRAY_BEGIN;
     527                 :      20183 :                                 state = STATE_VALUE;
     528                 :            :                         }
     529   [ +  -  +  -  :     242872 :                         con_value[depth] = cur_value;
                   +  - ]
     530   [ +  -  +  -  :     242872 :                         containers[depth++] = con_type;
                   +  - ]
     531   [ +  +  +  +  :     242872 :                         ADD_VALUE(con_type, data, data + 1);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     532         [ +  - ]:     242872 :                         data++;
     533                 :     242872 :                         trailing_comma = false;
     534                 :     242872 :                         break;
     535                 :            : 
     536                 :     236202 :                 case '}':
     537                 :            :                 case ']':
     538   [ +  +  +  - ]:     242230 :                         if (trailing_comma) { goto done_invalid; }
     539         [ +  + ]:     242224 :                         if (depth == 0) { goto done_invalid; }
     540   [ +  -  +  -  :     242218 :                         con_type = containers[--depth];
                   +  - ]
     541   [ +  -  +  -  :     242218 :                         con_start_value = con_value[depth];
                   +  - ]
     542   [ +  +  +  + ]:     242218 :                         if (values && con_start_value < num_values) {
     543   [ +  -  +  -  :     121088 :                                 values[con_start_value].len = cur_value - con_start_value - 1;
                   +  - ]
     544                 :       3014 :                         }
     545         [ +  + ]:     242218 :                         if (c == '}') {
     546   [ +  +  +  + ]:     222485 :                                 if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
     547                 :          6 :                                         goto done_invalid;
     548                 :            :                                 }
     549         [ +  + ]:     222479 :                                 if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) {
     550                 :          6 :                                         goto done_invalid;
     551                 :            :                                 }
     552   [ +  +  +  +  :     222473 :                                 ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     553                 :       5546 :                         } else {
     554   [ +  +  +  + ]:      19733 :                                 if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
     555                 :          3 :                                         goto done_invalid;
     556                 :            :                                 }
     557         [ +  + ]:      19730 :                                 if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) {
     558                 :          3 :                                         goto done_invalid;
     559                 :            :                                 }
     560   [ +  +  +  +  :      19727 :                                 ADD_VALUE(SPDK_JSON_VAL_ARRAY_END, data, data + 1);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     561                 :            :                         }
     562   [ +  +  +  -  :     242200 :                         con_type = depth == 0 ? SPDK_JSON_VAL_INVALID : containers[depth - 1];
             +  -  +  - ]
     563         [ +  - ]:     242200 :                         data++;
     564         [ +  + ]:     242200 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     565                 :     242200 :                         trailing_comma = false;
     566                 :     242200 :                         break;
     567                 :            : 
     568                 :     576343 :                 case ',':
     569         [ +  + ]:     592273 :                         if (state != STATE_VALUE_SEPARATOR) { goto done_invalid; }
     570         [ +  - ]:     592255 :                         data++;
     571   [ +  +  +  +  :     592255 :                         assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
                   #  # ]
     572                 :            :                                con_type == SPDK_JSON_VAL_OBJECT_BEGIN);
     573         [ +  + ]:     592255 :                         state = con_type == SPDK_JSON_VAL_ARRAY_BEGIN ? STATE_VALUE : STATE_NAME;
     574                 :     592255 :                         trailing_comma = true;
     575                 :     592255 :                         break;
     576                 :            : 
     577                 :     761552 :                 case ':':
     578         [ +  + ]:     781778 :                         if (state != STATE_NAME_SEPARATOR) { goto done_invalid; }
     579         [ +  - ]:     781778 :                         data++;
     580                 :     781778 :                         state = STATE_VALUE;
     581                 :     781778 :                         break;
     582                 :            : 
     583                 :         69 :                 case '/':
     584         [ +  + ]:         69 :                         if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) {
     585                 :          9 :                                 goto done_invalid;
     586                 :            :                         }
     587                 :         60 :                         rc = json_valid_comment(data, json_end);
     588         [ +  + ]:         60 :                         if (rc < 0) { goto done_rc; }
     589                 :            :                         /* Skip over comment */
     590         [ #  # ]:         48 :                         data += rc;
     591                 :         48 :                         break;
     592                 :            : 
     593                 :         33 :                 default:
     594                 :         33 :                         goto done_invalid;
     595                 :            :                 }
     596                 :            : 
     597         [ +  + ]:    7463517 :                 if (state == STATE_END) {
     598                 :     103379 :                         break;
     599                 :            :                 }
     600                 :            :         }
     601                 :            : 
     602         [ +  + ]:     148030 :         if (state == STATE_END) {
     603                 :            :                 /* Skip trailing whitespace */
     604         [ +  + ]:     137489 :                 while (data < json_end) {
     605         [ +  - ]:      34298 :                         uint8_t c = *data;
     606                 :            : 
     607   [ +  +  +  -  :      34298 :                         if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
             +  -  +  + ]
     608         [ +  - ]:      34110 :                                 data++;
     609                 :       1408 :                         } else {
     610                 :          0 :                                 break;
     611                 :            :                         }
     612                 :            :                 }
     613                 :            : 
     614                 :            :                 /*
     615                 :            :                  * These asserts are just for sanity checking - they are guaranteed by the allowed
     616                 :            :                  *  state transitions.
     617                 :            :                  */
     618   [ +  +  #  # ]:     103379 :                 assert(depth == 0);
     619   [ +  +  +  -  :     103379 :                 assert(trailing_comma == false);
                   #  # ]
     620   [ +  +  #  # ]:     103379 :                 assert(data <= json_end);
     621         [ +  + ]:     103379 :                 if (end) {
     622         [ +  - ]:     103344 :                         *end = data;
     623                 :       1654 :                 }
     624                 :     103379 :                 return cur_value;
     625                 :            :         }
     626                 :            : 
     627                 :            :         /* Invalid end state - ran out of data */
     628                 :      44651 :         rc = SPDK_JSON_PARSE_INCOMPLETE;
     629                 :            : 
     630                 :      44828 : done_rc:
     631   [ +  +  #  # ]:      45269 :         assert(rc < 0);
     632         [ +  - ]:      45269 :         if (end) {
     633         [ +  - ]:      45269 :                 *end = data;
     634                 :        441 :         }
     635                 :      45269 :         return rc;
     636                 :            : 
     637                 :         96 : done_invalid:
     638                 :         96 :         rc = SPDK_JSON_PARSE_INVALID;
     639                 :         96 :         goto done_rc;
     640                 :       2095 : }

Generated by: LCOV version 1.15