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

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

