QueryParser.cpp:_ZN3uWSL20getDecodedQueryValueENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEES4_:
   28|    838|    static inline std::string_view getDecodedQueryValue(std::string_view key, std::string_view rawQuery) {
   29|       |
   30|       |        /* Can't have a value without a key */
   31|    838|        if (!key.length()) {
  ------------------
  |  Branch (31:13): [True: 419, False: 419]
  ------------------
   32|    419|            return {};
   33|    419|        }
   34|       |
   35|       |        /* Start with the whole querystring including initial '?' */
   36|    419|        std::string_view queryString = rawQuery;
   37|       |
   38|       |        /* List of key, value could be cached for repeated fetches similar to how headers are, todo! */
   39|  2.25k|        while (queryString.length()) {
  ------------------
  |  Branch (39:16): [True: 2.05k, False: 195]
  ------------------
   40|       |            /* Find boundaries of this statement */
   41|  2.05k|            std::string_view statement = queryString.substr(1, queryString.find('&', 1) - 1);
   42|       |
   43|       |            /* Only bother if first char of key match (early exit) */
   44|  2.05k|            if (statement.length() && statement[0] == key[0]) {
  ------------------
  |  Branch (44:17): [True: 1.65k, False: 406]
  |  Branch (44:39): [True: 1.40k, False: 244]
  ------------------
   45|       |                /* Equal sign must be present and not in the end of statement */
   46|  1.40k|                auto equality = statement.find('=');
   47|  1.40k|                if (equality != std::string_view::npos) {
  ------------------
  |  Branch (47:21): [True: 1.38k, False: 18]
  ------------------
   48|       |
   49|  1.38k|                    std::string_view statementKey = statement.substr(0, equality);
   50|  1.38k|                    std::string_view statementValue = statement.substr(equality + 1);
   51|       |
   52|       |                    /* String comparison */
   53|  1.38k|                    if (key == statementKey) {
  ------------------
  |  Branch (53:25): [True: 206, False: 1.18k]
  ------------------
   54|       |
   55|       |                        /* Decode value inplace, put null at end if before length of original */
   56|    206|                        char *in = (char *) statementValue.data();
   57|       |
   58|       |                        /* Write offset */
   59|    206|                        unsigned int out = 0;
   60|       |
   61|       |                        /* Walk over all chars until end or null char, decoding in place */
   62|  2.52M|                        for (unsigned int i = 0; i < statementValue.length() && in[i]; i++) {
  ------------------
  |  Branch (62:50): [True: 2.52M, False: 86]
  |  Branch (62:81): [True: 2.52M, False: 92]
  ------------------
   63|       |                                /* Only bother with '%' */
   64|  2.52M|                                if (in[i] == '%') {
  ------------------
  |  Branch (64:37): [True: 57.2k, False: 2.46M]
  ------------------
   65|       |                                    /* Do we have enough data for two bytes hex? */
   66|  57.2k|                                    if (i + 2 >= statementValue.length()) {
  ------------------
  |  Branch (66:41): [True: 28, False: 57.2k]
  ------------------
   67|     28|                                        return {};
   68|     28|                                    }
   69|       |
   70|       |                                    /* Two bytes hex */
   71|  57.2k|                                    int hex1 = in[i + 1] - '0';
   72|  57.2k|                                    if (hex1 > 9) {
  ------------------
  |  Branch (72:41): [True: 46.5k, False: 10.7k]
  ------------------
   73|  46.5k|                                        hex1 &= 223;
   74|  46.5k|                                        hex1 -= 7;
   75|  46.5k|                                    }
   76|       |
   77|  57.2k|                                    int hex2 = in[i + 2] - '0';
   78|  57.2k|                                    if (hex2 > 9) {
  ------------------
  |  Branch (78:41): [True: 36.7k, False: 20.4k]
  ------------------
   79|  36.7k|                                        hex2 &= 223;
   80|  36.7k|                                        hex2 -= 7;
   81|  36.7k|                                    }
   82|       |
   83|  57.2k|                                    *((unsigned char *) &in[out]) = (unsigned char) (hex1 * 16 + hex2);
   84|  57.2k|                                    i += 2;
   85|  2.46M|                                } else {
   86|       |                                    /* Is this even a rule? */
   87|  2.46M|                                    if (in[i] == '+') {
  ------------------
  |  Branch (87:41): [True: 589, False: 2.46M]
  ------------------
   88|    589|                                        in[out] = ' ';
   89|  2.46M|                                    } else {
   90|  2.46M|                                        in[out] = in[i];
   91|  2.46M|                                    }
   92|  2.46M|                                }
   93|       |
   94|       |                                /* We always only write one char */
   95|  2.52M|                                out++;
   96|  2.52M|                        }
   97|       |
   98|       |                        /* If decoded string is shorter than original, put null char to stop next read */
   99|    178|                        if (out < statementValue.length()) {
  ------------------
  |  Branch (99:29): [True: 141, False: 37]
  ------------------
  100|    141|                            in[out] = 0;
  101|    141|                        }
  102|       |
  103|    178|                        return statementValue.substr(0, out);
  104|    206|                    }
  105|  1.38k|                } else {
  106|       |                    /* This querystring is invalid, cannot parse it */
  107|     18|                    return {nullptr, 0};
  108|     18|                }
  109|  1.40k|            }
  110|       |
  111|  1.83k|            queryString.remove_prefix(statement.length() + 1);
  112|  1.83k|        }
  113|       |
  114|       |        /* Nothing found is given as nullptr, while empty string is given as some pointer to the given buffer */
  115|    195|        return {nullptr, 0};
  116|    419|    }

LLVMFuzzerTestOneInput:
    5|    419|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    6|       |
    7|    419|    std::string modifiableInput((char *) data, size);
    8|       |
    9|    419|    uWS::getDecodedQueryValue("", modifiableInput);
   10|    419|    uWS::getDecodedQueryValue("hello", modifiableInput);
   11|       |
   12|    419|    return 0;
   13|    419|}

