QueryParser.cpp:_ZN3uWSL20getDecodedQueryValueENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEES4_:
   28|    842|    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|    842|        if (!key.length()) {
  ------------------
  |  Branch (31:13): [True: 421, False: 421]
  ------------------
   32|    421|            return {};
   33|    421|        }
   34|       |
   35|       |        /* Start with the whole querystring including initial '?' */
   36|    421|        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.32k|        while (queryString.length()) {
  ------------------
  |  Branch (39:16): [True: 2.09k, False: 223]
  ------------------
   40|       |            /* Find boundaries of this statement */
   41|  2.09k|            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.09k|            if (statement.length() && statement[0] == key[0]) {
  ------------------
  |  Branch (44:17): [True: 1.27k, False: 819]
  |  Branch (44:39): [True: 917, False: 362]
  ------------------
   45|       |                /* Equal sign must be present and not in the end of statement */
   46|    917|                auto equality = statement.find('=');
   47|    917|                if (equality != std::string_view::npos) {
  ------------------
  |  Branch (47:21): [True: 907, False: 10]
  ------------------
   48|       |
   49|    907|                    std::string_view statementKey = statement.substr(0, equality);
   50|    907|                    std::string_view statementValue = statement.substr(equality + 1);
   51|       |
   52|       |                    /* String comparison */
   53|    907|                    if (key == statementKey) {
  ------------------
  |  Branch (53:25): [True: 188, False: 719]
  ------------------
   54|       |
   55|       |                        /* Decode value inplace, put null at end if before length of original */
   56|    188|                        char *in = (char *) statementValue.data();
   57|       |
   58|       |                        /* Write offset */
   59|    188|                        unsigned int out = 0;
   60|       |
   61|       |                        /* Walk over all chars until end or null char, decoding in place */
   62|  2.68M|                        for (unsigned int i = 0; i < statementValue.length() && in[i]; i++) {
  ------------------
  |  Branch (62:50): [True: 2.68M, False: 82]
  |  Branch (62:81): [True: 2.68M, False: 79]
  ------------------
   63|       |                                /* Only bother with '%' */
   64|  2.68M|                                if (in[i] == '%') {
  ------------------
  |  Branch (64:37): [True: 81.3k, False: 2.60M]
  ------------------
   65|       |                                    /* Do we have enough data for two bytes hex? */
   66|  81.3k|                                    if (i + 2 >= statementValue.length()) {
  ------------------
  |  Branch (66:41): [True: 27, False: 81.2k]
  ------------------
   67|     27|                                        return {};
   68|     27|                                    }
   69|       |
   70|       |                                    /* Two bytes hex */
   71|  81.2k|                                    int hex1 = in[i + 1] - '0';
   72|  81.2k|                                    if (hex1 > 9) {
  ------------------
  |  Branch (72:41): [True: 68.9k, False: 12.3k]
  ------------------
   73|  68.9k|                                        hex1 &= 223;
   74|  68.9k|                                        hex1 -= 7;
   75|  68.9k|                                    }
   76|       |
   77|  81.2k|                                    int hex2 = in[i + 2] - '0';
   78|  81.2k|                                    if (hex2 > 9) {
  ------------------
  |  Branch (78:41): [True: 51.1k, False: 30.1k]
  ------------------
   79|  51.1k|                                        hex2 &= 223;
   80|  51.1k|                                        hex2 -= 7;
   81|  51.1k|                                    }
   82|       |
   83|  81.2k|                                    *((unsigned char *) &in[out]) = (unsigned char) (hex1 * 16 + hex2);
   84|  81.2k|                                    i += 2;
   85|  2.60M|                                } else {
   86|       |                                    /* Is this even a rule? */
   87|  2.60M|                                    if (in[i] == '+') {
  ------------------
  |  Branch (87:41): [True: 752, False: 2.60M]
  ------------------
   88|    752|                                        in[out] = ' ';
   89|  2.60M|                                    } else {
   90|  2.60M|                                        in[out] = in[i];
   91|  2.60M|                                    }
   92|  2.60M|                                }
   93|       |
   94|       |                                /* We always only write one char */
   95|  2.68M|                                out++;
   96|  2.68M|                        }
   97|       |
   98|       |                        /* If decoded string is shorter than original, put null char to stop next read */
   99|    161|                        if (out < statementValue.length()) {
  ------------------
  |  Branch (99:29): [True: 121, False: 40]
  ------------------
  100|    121|                            in[out] = 0;
  101|    121|                        }
  102|       |
  103|    161|                        return statementValue.substr(0, out);
  104|    188|                    }
  105|    907|                } else {
  106|       |                    /* This querystring is invalid, cannot parse it */
  107|     10|                    return {nullptr, 0};
  108|     10|                }
  109|    917|            }
  110|       |
  111|  1.90k|            queryString.remove_prefix(statement.length() + 1);
  112|  1.90k|        }
  113|       |
  114|       |        /* Nothing found is given as nullptr, while empty string is given as some pointer to the given buffer */
  115|    223|        return {nullptr, 0};
  116|    421|    }

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

