LCOV - code coverage report
Current view: top level - spdk/lib/json - json_parse.c (source / functions) Hit Total Coverage
Test: Combined Lines: 315 324 97.2 %
Date: 2024-07-16 01:31:00 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 285 336 84.8 %

           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                 :            :         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                 :            :         } 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                 :            : }
     106                 :            : 
     107                 :            : static int
     108                 :        231 : 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                 :        231 :         uint8_t *str = *strp;
     121                 :            :         uint8_t c;
     122                 :            : 
     123         [ -  + ]:        231 :         assert(buf_end > str);
     124         [ -  + ]:        231 :         if (buf_end - str < 2) {
     125                 :          0 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     126                 :            :         }
     127                 :            : 
     128         [ -  + ]:        231 :         assert(str[0] == '\\');
     129                 :            : 
     130                 :        231 :         c = escapes[str[1]];
     131         [ +  + ]:        231 :         if (c) {
     132         [ +  + ]:         78 :                 if (out) {
     133                 :         36 :                         *out = c;
     134                 :            :                 }
     135                 :         78 :                 *strp += 2; /* consumed two bytes */
     136                 :         78 :                 return 1; /* produced one byte */
     137                 :            :         }
     138                 :            : 
     139                 :        153 :         return SPDK_JSON_PARSE_INVALID;
     140                 :            : }
     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                 :        231 : json_decode_string_escape(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
     151                 :            : {
     152                 :            :         int rc;
     153                 :            : 
     154                 :        231 :         rc = json_decode_string_escape_twochar(strp, buf_end, out);
     155         [ +  + ]:        231 :         if (rc > 0) {
     156                 :         78 :                 return rc;
     157                 :            :         }
     158                 :            : 
     159                 :        153 :         return json_decode_string_escape_unicode(strp, buf_end, out);
     160                 :            : }
     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                 :    1157619 : json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint32_t flags)
     171                 :            : {
     172                 :    1157619 :         uint8_t *str = str_start;
     173                 :    1157619 :         uint8_t *out = str_start + 1; /* Decode string in place (skip the initial quote) */
     174                 :            :         int rc;
     175                 :            : 
     176         [ +  + ]:    1157619 :         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         [ -  + ]:    1157601 :         if (*str++ != '"') {
     186                 :          0 :                 *str_end = str;
     187                 :          0 :                 return SPDK_JSON_PARSE_INVALID;
     188                 :            :         }
     189                 :            : 
     190         [ +  + ]:   11608792 :         while (str < buf_end) {
     191         [ +  + ]:   11608691 :                 if (str[0] == '"') {
     192                 :            :                         /*
     193                 :            :                          * End of string.
     194                 :            :                          * Update str_end to point at next input byte and return output length.
     195                 :            :                          */
     196                 :    1157172 :                         *str_end = str + 1;
     197                 :    1157172 :                         return out - str_start - 1;
     198         [ +  + ]:   10451522 :                 } else if (str[0] == '\\') {
     199                 :        231 :                         rc = json_decode_string_escape(&str, buf_end,
     200         [ +  + ]:        231 :                                                        flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE ? out : NULL);
     201         [ -  + ]:        231 :                         assert(rc != 0);
     202         [ +  + ]:        231 :                         if (rc < 0) {
     203                 :         93 :                                 *str_end = str;
     204                 :         93 :                                 return rc;
     205                 :            :                         }
     206                 :        138 :                         out += rc;
     207         [ +  + ]:   10451291 :                 } 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                 :   10451186 :                         rc = utf8_valid(str, buf_end);
     213         [ -  + ]:   10451186 :                         if (rc == 0) {
     214                 :          0 :                                 *str_end = str;
     215                 :          0 :                                 return SPDK_JSON_PARSE_INCOMPLETE;
     216         [ +  + ]:   10451186 :                         } else if (rc < 0) {
     217                 :        135 :                                 *str_end = str;
     218                 :        135 :                                 return SPDK_JSON_PARSE_INVALID;
     219                 :            :                         }
     220                 :            : 
     221   [ +  -  +  +  :   10451051 :                         if (out && out != str && (flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE)) {
                   +  + ]
     222   [ -  +  -  + ]:         53 :                                 memmove(out, str, rc);
     223                 :            :                         }
     224                 :   10451051 :                         out += rc;
     225                 :   10451051 :                         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                 :            : }
     233                 :            : 
     234                 :            : static int
     235                 :     214482 : json_valid_number(uint8_t *start, uint8_t *buf_end)
     236                 :            : {
     237                 :     214482 :         uint8_t *p = start;
     238                 :            :         uint8_t c;
     239                 :            : 
     240         [ -  + ]:     214482 :         if (p >= buf_end) { return -1; }
     241                 :            : 
     242                 :     214482 :         c = *p++;
     243   [ +  +  +  - ]:     214482 :         if (c >= '1' && c <= '9') { goto num_int_digits; }
     244         [ +  + ]:      53440 :         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                 :            :         }
     256                 :          6 :         goto done_invalid;
     257                 :            : 
     258                 :     161170 : num_int_digits:
     259         [ +  + ]:     349054 :         if (spdk_likely(p != buf_end)) {
     260                 :     349030 :                 c = *p++;
     261   [ +  +  +  + ]:     349030 :                 if (c >= '0' && c <= '9') { goto num_int_digits; }
     262         [ +  + ]:     161146 :                 if (c == '.') { goto num_frac_first_digit; }
     263   [ +  +  +  + ]:     161014 :                 if (c == 'e' || c == 'E') { goto num_exp_sign; }
     264                 :     160978 :                 p--;
     265                 :            :         }
     266                 :     161002 :         goto done_valid;
     267                 :            : 
     268                 :      53306 : num_frac_or_exp:
     269         [ +  + ]:      53306 :         if (spdk_likely(p != buf_end)) {
     270                 :      53276 :                 c = *p++;
     271         [ -  + ]:      53276 :                 if (c == '.') { goto num_frac_first_digit; }
     272   [ +  +  -  + ]:      53276 :                 if (c == 'e' || c == 'E') { goto num_exp_sign; }
     273                 :      53246 :                 p--;
     274                 :            :         }
     275                 :      53276 :         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                 :            :         }
     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                 :            :         }
     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                 :            :         }
     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                 :            :         }
     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                 :            :         }
     317                 :         99 :         goto done_valid;
     318                 :            : 
     319                 :     214449 : done_valid:
     320                 :            :         /* Valid end state */
     321                 :     214449 :         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                 :            : }
     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                 :            :         } 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                 :            :         } 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                 :            : }
     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                 :      70623 : match_literal(const uint8_t *start, const uint8_t *end, const uint8_t *literal, size_t len)
     401                 :            : {
     402         [ -  + ]:      70623 :         assert(end >= start);
     403         [ +  + ]:      70623 :         if ((size_t)(end - start) < len) {
     404                 :         18 :                 return SPDK_JSON_PARSE_INCOMPLETE;
     405                 :            :         }
     406                 :            : 
     407   [ +  +  -  +  :      70605 :         if (memcmp(start, literal, len) != 0) {
                   +  + ]
     408                 :          9 :                 return SPDK_JSON_PARSE_INVALID;
     409                 :            :         }
     410                 :            : 
     411                 :      70596 :         return len;
     412                 :            : }
     413                 :            : 
     414                 :            : ssize_t
     415                 :     164556 : 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                 :     164556 :         uint8_t *json_end = json + size;
     419                 :      66545 :         enum spdk_json_val_type containers[SPDK_JSON_MAX_NESTING_DEPTH];
     420                 :      66545 :         size_t con_value[SPDK_JSON_MAX_NESTING_DEPTH];
     421                 :     164556 :         enum spdk_json_val_type con_type = SPDK_JSON_VAL_INVALID;
     422                 :     164556 :         bool trailing_comma = false;
     423                 :     164556 :         size_t depth = 0; /* index into containers */
     424                 :     164556 :         size_t cur_value = 0; /* index into values */
     425                 :            :         size_t con_start_value;
     426                 :     164556 :         uint8_t *data = json;
     427                 :      66545 :         uint8_t *new_data;
     428                 :     164556 :         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                 :     164556 :         } 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         [ +  + ]:    7281798 :         while (data < json_end) {
     447                 :    7231809 :                 uint8_t c = *data;
     448                 :            : 
     449   [ +  +  +  +  :    7231809 :                 switch (c) {
          +  +  +  +  +  
                      + ]
     450                 :    3945903 :                 case ' ':
     451                 :            :                 case '\t':
     452                 :            :                 case '\r':
     453                 :            :                 case '\n':
     454                 :            :                         /* Whitespace is allowed between any tokens. */
     455                 :    3945903 :                         data++;
     456                 :    3945903 :                         break;
     457                 :            : 
     458                 :      70623 :                 case 't':
     459                 :            :                 case 'f':
     460                 :            :                 case 'n':
     461                 :            :                         /* true, false, or null */
     462         [ -  + ]:      70623 :                         if (state != STATE_VALUE) { goto done_invalid; }
     463                 :      70623 :                         lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */
     464         [ -  + ]:      70623 :                         assert(lit->str[0] == c);
     465                 :      70623 :                         rc = match_literal(data, json_end, lit->str, lit->len);
     466         [ +  + ]:      70623 :                         if (rc < 0) { goto done_rc; }
     467   [ +  +  +  - ]:      70596 :                         ADD_VALUE(lit->type, data, data + rc);
     468                 :      70596 :                         data += rc;
     469         [ +  + ]:      70596 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     470                 :      70596 :                         trailing_comma = false;
     471                 :      70596 :                         break;
     472                 :            : 
     473                 :    1157619 :                 case '"':
     474   [ +  +  -  + ]:    1157619 :                         if (state != STATE_VALUE && state != STATE_NAME) { goto done_invalid; }
     475                 :    1157619 :                         rc = json_decode_string(data, json_end, &new_data, flags);
     476         [ +  + ]:    1157619 :                         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   [ +  +  +  -  :    1157172 :                         ADD_VALUE(state == STATE_VALUE ? SPDK_JSON_VAL_STRING : SPDK_JSON_VAL_NAME,
                   +  + ]
     485                 :            :                                   data + 1, data + rc - 1);
     486                 :    1157172 :                         data = new_data;
     487         [ +  + ]:    1157172 :                         if (state == STATE_NAME) {
     488                 :     768171 :                                 state = STATE_NAME_SEPARATOR;
     489                 :            :                         } else {
     490         [ +  + ]:     389001 :                                 state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     491                 :            :                         }
     492                 :    1157172 :                         trailing_comma = false;
     493                 :    1157172 :                         break;
     494                 :            : 
     495                 :     214488 :                 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         [ +  + ]:     214488 :                         if (state != STATE_VALUE) { goto done_invalid; }
     507                 :     214482 :                         rc = json_valid_number(data, json_end);
     508         [ +  + ]:     214482 :                         if (rc < 0) { goto done_rc; }
     509   [ +  +  +  - ]:     214449 :                         ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc);
     510                 :     214449 :                         data += rc;
     511         [ +  + ]:     214449 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     512                 :     214449 :                         trailing_comma = false;
     513                 :     214449 :                         break;
     514                 :            : 
     515                 :     256289 :                 case '{':
     516                 :            :                 case '[':
     517         [ -  + ]:     256289 :                         if (state != STATE_VALUE) { goto done_invalid; }
     518         [ +  + ]:     256289 :                         if (depth == SPDK_JSON_MAX_NESTING_DEPTH) {
     519                 :          3 :                                 rc = SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED;
     520                 :          3 :                                 goto done_rc;
     521                 :            :                         }
     522         [ +  + ]:     256286 :                         if (c == '{') {
     523                 :     234645 :                                 con_type = SPDK_JSON_VAL_OBJECT_BEGIN;
     524                 :     234645 :                                 state = STATE_NAME;
     525                 :            :                         } else {
     526                 :      21641 :                                 con_type = SPDK_JSON_VAL_ARRAY_BEGIN;
     527                 :      21641 :                                 state = STATE_VALUE;
     528                 :            :                         }
     529                 :     256286 :                         con_value[depth] = cur_value;
     530                 :     256286 :                         containers[depth++] = con_type;
     531   [ +  +  +  - ]:     256286 :                         ADD_VALUE(con_type, data, data + 1);
     532                 :     256286 :                         data++;
     533                 :     256286 :                         trailing_comma = false;
     534                 :     256286 :                         break;
     535                 :            : 
     536                 :     255644 :                 case '}':
     537                 :            :                 case ']':
     538         [ +  + ]:     255644 :                         if (trailing_comma) { goto done_invalid; }
     539         [ +  + ]:     255638 :                         if (depth == 0) { goto done_invalid; }
     540                 :     255632 :                         con_type = containers[--depth];
     541                 :     255632 :                         con_start_value = con_value[depth];
     542   [ +  +  +  - ]:     255632 :                         if (values && con_start_value < num_values) {
     543                 :     127795 :                                 values[con_start_value].len = cur_value - con_start_value - 1;
     544                 :            :                         }
     545         [ +  + ]:     255632 :                         if (c == '}') {
     546   [ +  +  +  + ]:     234441 :                                 if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
     547                 :          6 :                                         goto done_invalid;
     548                 :            :                                 }
     549         [ +  + ]:     234435 :                                 if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) {
     550                 :          6 :                                         goto done_invalid;
     551                 :            :                                 }
     552   [ +  +  +  - ]:     234429 :                                 ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1);
     553                 :            :                         } else {
     554   [ +  +  +  + ]:      21191 :                                 if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
     555                 :          3 :                                         goto done_invalid;
     556                 :            :                                 }
     557         [ +  + ]:      21188 :                                 if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) {
     558                 :          3 :                                         goto done_invalid;
     559                 :            :                                 }
     560   [ +  +  +  - ]:      21185 :                                 ADD_VALUE(SPDK_JSON_VAL_ARRAY_END, data, data + 1);
     561                 :            :                         }
     562         [ +  + ]:     255614 :                         con_type = depth == 0 ? SPDK_JSON_VAL_INVALID : containers[depth - 1];
     563                 :     255614 :                         data++;
     564         [ +  + ]:     255614 :                         state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
     565                 :     255614 :                         trailing_comma = false;
     566                 :     255614 :                         break;
     567                 :            : 
     568                 :     562997 :                 case ',':
     569         [ +  + ]:     562997 :                         if (state != STATE_VALUE_SEPARATOR) { goto done_invalid; }
     570                 :     562979 :                         data++;
     571   [ +  +  -  + ]:     562979 :                         assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
     572                 :            :                                con_type == SPDK_JSON_VAL_OBJECT_BEGIN);
     573         [ +  + ]:     562979 :                         state = con_type == SPDK_JSON_VAL_ARRAY_BEGIN ? STATE_VALUE : STATE_NAME;
     574                 :     562979 :                         trailing_comma = true;
     575                 :     562979 :                         break;
     576                 :            : 
     577                 :     768144 :                 case ':':
     578         [ -  + ]:     768144 :                         if (state != STATE_NAME_SEPARATOR) { goto done_invalid; }
     579                 :     768144 :                         data++;
     580                 :     768144 :                         state = STATE_VALUE;
     581                 :     768144 :                         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         [ +  + ]:    7231191 :                 if (state == STATE_END) {
     598                 :     113949 :                         break;
     599                 :            :                 }
     600                 :            :         }
     601                 :            : 
     602         [ +  + ]:     163938 :         if (state == STATE_END) {
     603                 :            :                 /* Skip trailing whitespace */
     604         [ +  + ]:     144847 :                 while (data < json_end) {
     605                 :      31088 :                         uint8_t c = *data;
     606                 :            : 
     607   [ +  +  +  -  :      31088 :                         if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
             +  -  +  + ]
     608                 :      30898 :                                 data++;
     609                 :            :                         } else {
     610                 :            :                                 break;
     611                 :            :                         }
     612                 :            :                 }
     613                 :            : 
     614                 :            :                 /*
     615                 :            :                  * These asserts are just for sanity checking - they are guaranteed by the allowed
     616                 :            :                  *  state transitions.
     617                 :            :                  */
     618         [ -  + ]:     113949 :                 assert(depth == 0);
     619         [ -  + ]:     113949 :                 assert(trailing_comma == false);
     620         [ -  + ]:     113949 :                 assert(data <= json_end);
     621         [ +  + ]:     113949 :                 if (end) {
     622                 :     113922 :                         *end = data;
     623                 :            :                 }
     624                 :     113949 :                 return cur_value;
     625                 :            :         }
     626                 :            : 
     627                 :            :         /* Invalid end state - ran out of data */
     628                 :      49989 :         rc = SPDK_JSON_PARSE_INCOMPLETE;
     629                 :            : 
     630                 :      50607 : done_rc:
     631         [ -  + ]:      50607 :         assert(rc < 0);
     632         [ +  - ]:      50607 :         if (end) {
     633                 :      50607 :                 *end = data;
     634                 :            :         }
     635                 :      50607 :         return rc;
     636                 :            : 
     637                 :         96 : done_invalid:
     638                 :         96 :         rc = SPDK_JSON_PARSE_INVALID;
     639                 :         96 :         goto done_rc;
     640                 :            : }

Generated by: LCOV version 1.14