run_burl_normalize:
   26|  1.60k|						size_t in_len) {
   27|  1.60k|    int qs;
   28|  1.60k|    buffer_copy_string_len(psrc, in, in_len);
   29|  1.60k|    qs = burl_normalize(psrc, ptmp, flags);
   30|  1.60k|}
LLVMFuzzerTestOneInput:
   32|  1.61k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   33|  1.61k|    if (size <= 4) {
  ------------------
  |  Branch (33:9): [True: 4, False: 1.60k]
  ------------------
   34|      4|        return 0;
   35|      4|    }
   36|  1.60k|    int flags = ((int*)data)[0];
   37|  1.60k|    data += 4;
   38|  1.60k|    size -= 4;
   39|  1.60k|    char *new_str = (char *)malloc(size+1);
   40|  1.60k|    if (new_str == NULL){
  ------------------
  |  Branch (40:9): [True: 0, False: 1.60k]
  ------------------
   41|      0|        return 0;
   42|      0|    }
   43|  1.60k|    memcpy(new_str, data, size);
   44|  1.60k|    new_str[size] = '\0';
   45|       |
   46|       |    /* main fuzzer entrypoint for library */
   47|  1.60k|    buffer *psrc = buffer_init();
   48|  1.60k|    buffer *ptmp = buffer_init();
   49|  1.60k|    run_burl_normalize(psrc, ptmp, flags, __LINE__, new_str, size);
   50|  1.60k|    buffer_urldecode_path(psrc);
   51|       |
   52|  1.60k|    buffer_free(psrc);
   53|  1.60k|    buffer_free(ptmp);
   54|  1.60k|    free(new_str);
   55|  1.60k|    return 0;     
   56|  1.60k|}

buffer_init:
   14|  3.21k|buffer* buffer_init(void) {
   15|       |  #if 0 /* buffer_init() and chunk_init() can be hot,
   16|       |	 * so avoid the additional hop of indirection */
   17|       |	return ck_calloc(1, sizeof(buffer));
   18|       |  #else
   19|  3.21k|	buffer * const b = calloc(1, sizeof(*b));
   20|  3.21k|	force_assert(b);
  ------------------
  |  |  448|  3.21k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.21k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.21k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.21k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   21|  3.21k|	return b;
   22|  3.21k|  #endif
   23|  3.21k|}
buffer_free:
   25|  3.21k|void buffer_free(buffer *b) {
   26|  3.21k|	if (NULL == b) return;
  ------------------
  |  Branch (26:6): [True: 0, False: 3.21k]
  ------------------
   27|  3.21k|	free(b->ptr);
   28|  3.21k|	free(b);
   29|  3.21k|}
buffer_string_prepare_copy:
   82|  1.23k|char* buffer_string_prepare_copy(buffer * const b, const size_t size) {
   83|  1.23k|    b->used = 0;
   84|       |  #ifdef __COVERITY__ /*(b->ptr is not NULL if b->size is not 0)*/
   85|       |    force_assert(size >= b->size || b->ptr);
   86|       |  #endif
   87|  1.23k|    return (size < b->size)
  ------------------
  |  Branch (87:12): [True: 0, False: 1.23k]
  ------------------
   88|  1.23k|      ? b->ptr
   89|  1.23k|      : buffer_alloc_replace(b, size);
   90|  1.23k|}
buffer_extend:
  127|    138|{
  128|       |    /* extend buffer to append x (reallocate by power-2 (or larger), if needed)
  129|       |     * (combine buffer_string_prepare_append() and buffer_commit())
  130|       |     * (future: might make buffer.h static inline func for HTTP/1.1 performance)
  131|       |     * pre-sets '\0' byte and b->used (unlike buffer_string_prepare_append())*/
  132|       |  #if 0
  133|       |    char * const s = buffer_string_prepare_append(b, x);
  134|       |    b->used += x + (0 == b->used);
  135|       |  #else
  136|    138|    const uint32_t len = b->used ? b->used-1 : 0;
  ------------------
  |  Branch (136:26): [True: 138, False: 0]
  ------------------
  137|    138|    char * const s = (b->size - len >= x + 1)
  ------------------
  |  Branch (137:22): [True: 138, False: 0]
  ------------------
  138|    138|      ? b->ptr + len
  139|    138|      : buffer_string_prepare_append_resize(b, x);
  140|    138|    b->used = len+x+1;
  141|    138|  #endif
  142|    138|    s[x] = '\0';
  143|    138|    return s;
  144|    138|}
buffer_copy_string_len:
  172|  2.98k|void buffer_copy_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) {
  173|  2.98k|    b->used = len + 1;
  174|  2.98k|    char * const restrict d = (len < b->size)
  ------------------
  |  Branch (174:31): [True: 913, False: 2.06k]
  ------------------
  175|  2.98k|      ? b->ptr
  176|  2.98k|      : buffer_alloc_replace(b, len);
  177|  2.98k|    d[len] = '\0';
  178|  2.98k|    memcpy(d, s, len);
  179|  2.98k|}
buffer_append_string_len:
  198|    138|void buffer_append_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) {
  199|    138|    memcpy(buffer_extend(b, len), s, len);
  200|    138|}
hex2int:
  386|  99.2M|char hex2int(unsigned char hex) {
  387|  99.2M|	unsigned char n;
  388|  99.2M|	return li_cton(hex,n) ? (char)n : 0xFF;
  ------------------
  |  |  381|  99.2M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (381:4): [True: 85.7M, False: 13.5M]
  |  |  |  Branch (381:30): [True: 13.5M, False: 0]
  |  |  |  Branch (381:31): [True: 13.5M, False: 0]
  |  |  ------------------
  ------------------
  389|  99.2M|}
buffer_urldecode_path:
  792|  1.60k|void buffer_urldecode_path(buffer * const b) {
  793|  1.60k|    const size_t len = buffer_clen(b);
  794|  1.60k|    char *src = len ? memchr(b->ptr, '%', len) : NULL;
  ------------------
  |  Branch (794:17): [True: 1.60k, False: 5]
  ------------------
  795|  1.60k|    if (NULL == src) return;
  ------------------
  |  Branch (795:9): [True: 334, False: 1.27k]
  ------------------
  796|       |
  797|  1.27k|    char *dst = src;
  798|  49.6M|    do {
  799|       |        /* *src == '%' */
  800|  49.6M|        unsigned char high = ((unsigned char *)src)[1];
  801|  49.6M|        unsigned char low = high ? hex2int(((unsigned char *)src)[2]) : 0xFF;
  ------------------
  |  Branch (801:29): [True: 49.6M, False: 0]
  ------------------
  802|  49.6M|        if (0xFF != (high = hex2int(high)) && 0xFF != low) {
  ------------------
  |  Branch (802:13): [True: 49.6M, False: 0]
  |  Branch (802:47): [True: 49.6M, False: 0]
  ------------------
  803|  49.6M|            high = (high << 4) | low;   /* map ctrls to '_' */
  804|  49.6M|            *dst = (high >= 32 && high != 127) ? high : '_';
  ------------------
  |  Branch (804:21): [True: 10.6M, False: 38.9M]
  |  Branch (804:35): [True: 9.58M, False: 1.09M]
  ------------------
  805|  49.6M|            src += 2;
  806|  49.6M|        } /* else ignore this '%'; leave as-is and move on */
  807|       |
  808|  53.4M|        while ((*++dst = *++src) != '%' && *src) ;
  ------------------
  |  Branch (808:16): [True: 3.78M, False: 49.6M]
  |  Branch (808:44): [True: 3.77M, False: 1.27k]
  ------------------
  809|  49.6M|    } while (*src);
  ------------------
  |  Branch (809:14): [True: 49.6M, False: 1.27k]
  ------------------
  810|  1.27k|    b->used = (dst - b->ptr) + 1;
  811|  1.27k|}
buffer_path_simplify:
  859|    378|{
  860|    378|    char *out = b->ptr;
  861|    378|    char * const end = b->ptr + b->used - 1;
  862|       |
  863|    378|    if (__builtin_expect( (buffer_is_blank(b)), 0)) {
  ------------------
  |  Branch (863:9): [True: 0, False: 378]
  ------------------
  864|      0|        buffer_blank(b);
  865|      0|        return;
  866|      0|    }
  867|       |
  868|       |  #if defined(_WIN32) || defined(__CYGWIN__)
  869|       |    /* cygwin is treating \ and / the same, so we have to that too */
  870|       |    for (char *p = b->ptr; *p; p++) {
  871|       |        if (*p == '\\') *p = '/';
  872|       |    }
  873|       |  #endif
  874|       |
  875|    378|    *end = '/'; /*(end of path modified to avoid need to check '\0')*/
  876|       |
  877|    378|    char *walk = out;
  878|    378|    if (__builtin_expect( (*walk == '/'), 1)) {
  ------------------
  |  Branch (878:9): [True: 140, False: 238]
  ------------------
  879|       |        /* scan to detect (potential) need for path simplification
  880|       |         * (repeated '/' or "/.") */
  881|    528|        do {
  882|    528|            if (*++walk == '.' || *walk == '/')
  ------------------
  |  Branch (882:17): [True: 76, False: 452]
  |  Branch (882:35): [True: 64, False: 388]
  ------------------
  883|    140|                break;
  884|   418k|            do { ++walk; } while (*walk != '/');
  ------------------
  |  Branch (884:35): [True: 417k, False: 388]
  ------------------
  885|    388|        } while (walk != end);
  ------------------
  |  Branch (885:18): [True: 388, False: 0]
  ------------------
  886|    140|        if (__builtin_expect( (walk == end), 1)) {
  ------------------
  |  Branch (886:13): [True: 0, False: 140]
  ------------------
  887|       |            /* common case: no repeated '/' or "/." */
  888|      0|            *end = '\0'; /* overwrite extra '/' added to end of path */
  889|      0|            return;
  890|      0|        }
  891|    140|        out = walk-1;
  892|    140|    }
  893|    238|    else {
  894|    238|        if (walk[0] == '.' && walk[1] == '/')
  ------------------
  |  Branch (894:13): [True: 110, False: 128]
  |  Branch (894:31): [True: 53, False: 57]
  ------------------
  895|     53|            *out = *++walk;
  896|    185|        else if (walk[0] == '.' && walk[1] == '.' && walk[2] == '/')
  ------------------
  |  Branch (896:18): [True: 57, False: 128]
  |  Branch (896:36): [True: 29, False: 28]
  |  Branch (896:54): [True: 3, False: 26]
  ------------------
  897|      3|            *out = *(walk += 2);
  898|    182|        else {
  899|  8.47M|            while (*++walk != '/') ;
  ------------------
  |  Branch (899:20): [True: 8.47M, False: 182]
  ------------------
  900|    182|            out = walk;
  901|    182|        }
  902|    238|        ++walk;
  903|    238|    }
  904|       |
  905|  29.1k|    while (walk <= end) {
  ------------------
  |  Branch (905:12): [True: 28.9k, False: 195]
  ------------------
  906|       |        /* previous char is '/' at this point (or start of string w/o '/') */
  907|  28.9k|        if (__builtin_expect( (walk[0] == '/'), 0)) {
  ------------------
  |  Branch (907:13): [True: 3.26k, False: 25.6k]
  ------------------
  908|       |            /* skip repeated '/' (e.g. "///" -> "/") */
  909|  3.26k|            if (++walk < end)
  ------------------
  |  Branch (909:17): [True: 3.19k, False: 69]
  ------------------
  910|  3.19k|                continue;
  911|     69|            else {
  912|     69|                ++out;
  913|     69|                break;
  914|     69|            }
  915|  3.26k|        }
  916|  25.6k|        else if (__builtin_expect( (walk[0] == '.'), 0)) {
  ------------------
  |  Branch (916:18): [True: 15.8k, False: 9.80k]
  ------------------
  917|       |            /* handle "./" and "../" */
  918|  15.8k|            if (walk[1] == '.' && walk[2] == '/') {
  ------------------
  |  Branch (918:17): [True: 11.4k, False: 4.40k]
  |  Branch (918:35): [True: 1.49k, False: 9.96k]
  ------------------
  919|       |                /* handle "../" */
  920|  3.65M|                while (out > b->ptr && *--out != '/') ;
  ------------------
  |  Branch (920:24): [True: 3.65M, False: 690]
  |  Branch (920:40): [True: 3.65M, False: 806]
  ------------------
  921|  1.49k|                *out = '/'; /*(in case path had not started with '/')*/
  922|  1.49k|                if ((walk += 3) >= end) {
  ------------------
  |  Branch (922:21): [True: 58, False: 1.43k]
  ------------------
  923|     58|                    ++out;
  924|     58|                    break;
  925|     58|                }
  926|  1.43k|                else
  927|  1.43k|                    continue;
  928|  1.49k|            }
  929|  14.3k|            else if (walk[1] == '/') {
  ------------------
  |  Branch (929:22): [True: 2.16k, False: 12.2k]
  ------------------
  930|       |                /* handle "./" */
  931|  2.16k|                if ((walk += 2) >= end) {
  ------------------
  |  Branch (931:21): [True: 56, False: 2.10k]
  ------------------
  932|     56|                    ++out;
  933|     56|                    break;
  934|     56|                }
  935|  2.10k|                continue;
  936|  2.16k|            }
  937|  12.2k|            else {
  938|       |                /* accept "." if not part of "../" or "./" */
  939|  12.2k|                *++out = '.';
  940|  12.2k|                ++walk;
  941|  12.2k|            }
  942|  15.8k|        }
  943|       |
  944|  24.7M|        while ((*++out = *walk++) != '/') ;
  ------------------
  |  Branch (944:16): [True: 24.7M, False: 22.0k]
  ------------------
  945|  22.0k|    }
  946|    378|    *out = *end = '\0'; /* overwrite extra '/' added to end of path */
  947|    378|    b->used = (out - b->ptr) + 1;
  948|       |    /*buffer_truncate(b, out - b->ptr);*/
  949|    378|}
buffer.c:buffer_alloc_replace:
   71|  3.30k|static char* buffer_alloc_replace(buffer * const restrict b, const size_t size) {
   72|       |    /*(discard old data so realloc() does not copy)*/
   73|  3.30k|    if (NULL != b->ptr) {
  ------------------
  |  Branch (73:9): [True: 448, False: 2.85k]
  ------------------
   74|    448|        free(b->ptr);
   75|    448|        b->ptr = NULL;
   76|    448|    }
   77|       |    /*(note: if size larger than one lshift, use size instead of power-2)*/
   78|  3.30k|    const size_t bsize2x = (b->size & ~1uL) << 1;
   79|  3.30k|    return buffer_realloc(b, bsize2x > size ? bsize2x-1 : size);
  ------------------
  |  Branch (79:30): [True: 224, False: 3.08k]
  ------------------
   80|  3.30k|}
buffer.c:buffer_realloc:
   49|  3.30k|static char* buffer_realloc(buffer * const restrict b, const size_t len) {
   50|  3.30k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
   51|  3.30k|    size_t sz = (len + 1 + BUFFER_PIECE_SIZE-1) & ~(BUFFER_PIECE_SIZE-1);
  ------------------
  |  |   50|  3.30k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
  ------------------
                  size_t sz = (len + 1 + BUFFER_PIECE_SIZE-1) & ~(BUFFER_PIECE_SIZE-1);
  ------------------
  |  |   50|  3.30k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
  ------------------
   52|  3.30k|    force_assert(sz > len);
  ------------------
  |  |  448|  3.30k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.30k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.30k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.30k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   53|  3.30k|    if ((sz & (sz-1)) && sz < INT_MAX) {/* not power-2; huge val not expected */
  ------------------
  |  Branch (53:9): [True: 1.06k, False: 2.23k]
  |  Branch (53:26): [True: 1.06k, False: 0]
  ------------------
   54|       |        /*(optimizer should recognize this and use ffs or clz or equivalent)*/
   55|  1.06k|        const size_t psz = sz;
   56|  7.39k|        for (sz = 256; sz < psz; sz <<= 1) ;
  ------------------
  |  Branch (56:24): [True: 6.33k, False: 1.06k]
  ------------------
   57|  1.06k|    }
   58|  3.30k|    sz |= 1; /*(extra +1 for '\0' when needed buffer size is exact power-2)*/
   59|       |
   60|  3.30k|    b->size = sz;
   61|  3.30k|    b->ptr = realloc(b->ptr, sz);
   62|       |
   63|  3.30k|    force_assert(NULL != b->ptr);
  ------------------
  |  |  448|  3.30k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.30k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.30k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.30k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   64|  3.30k|    return b->ptr;
   65|  3.30k|}

burl.c:buffer_truncate:
  349|    417|static inline void buffer_truncate(buffer *b, uint32_t len) {
  350|    417|    b->ptr[len] = '\0'; /* b->ptr must exist; use buffer_blank() for trunc 0 */
  351|    417|    b->used = len + 1;
  352|    417|}
burl.c:light_isalnum:
  232|  21.7k|static inline int light_isalnum(int c) {
  233|  21.7k|	return light_isdigit(c) || light_isalpha(c);
  ------------------
  |  Branch (233:9): [True: 450, False: 21.3k]
  |  Branch (233:29): [True: 650, False: 20.6k]
  ------------------
  234|  21.7k|}
burl.c:light_isdigit:
  214|  21.7k|static inline int light_isdigit(int c) {
  215|  21.7k|	return ((uint32_t)c-'0' <= '9'-'0');
  216|  21.7k|}
burl.c:light_isalpha:
  226|  21.3k|static inline int light_isalpha(int c) {
  227|  21.3k|	return (((uint32_t)c | 0x20)-'a' <= 'z'-'a');
  228|  21.3k|}
burl.c:buffer_clen:
  323|  5.93k|static inline uint32_t buffer_clen (const buffer *b) {
  324|  5.93k|    return b->used - (0 != b->used);
  325|  5.93k|}
buffer.c:buffer_clen:
  323|  1.60k|static inline uint32_t buffer_clen (const buffer *b) {
  324|  1.60k|    return b->used - (0 != b->used);
  325|  1.60k|}
buffer.c:buffer_is_blank:
  315|    378|static inline int buffer_is_blank(const buffer *b) {
  316|    378|    return b->used < 2; /* buffer_is_blank() || buffer_is_unset() */
  317|    378|}

burl_normalize:
  344|  1.60k|{
  345|  1.60k|    int qs;
  346|       |
  347|       |  #if defined(_WIN32) || defined(__CYGWIN__)
  348|       |    /* Windows and Cygwin treat '\\' as '/' if '\\' is present in path;
  349|       |     * convert to '/' for consistency before percent-encoding
  350|       |     * normalization which will convert '\\' to "%5C" in the URL.
  351|       |     * (Clients still should not be sending '\\' unencoded in requests.) */
  352|       |    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_BACKSLASH_TRANS) {
  353|       |        for (char *p = b->ptr; *p != '?' && *p != '\0'; ++p) {
  354|       |            if (*p == '\\') *p = '/';
  355|       |            if (p[0] == '%' && p[1] == '5' && (p[2] | 0x20) == 'c') {
  356|       |                p[1] = '2';
  357|       |                p[2] = 'F';
  358|       |                p += 2;
  359|       |            }
  360|       |        }
  361|       |    }
  362|       |  #endif
  363|       |
  364|  1.60k|    qs = (flags & HTTP_PARSEOPT_URL_NORMALIZE_REQUIRED)
  ------------------
  |  Branch (364:10): [True: 883, False: 723]
  ------------------
  365|  1.60k|      ? burl_normalize_basic_required(b, t)
  366|  1.60k|      : burl_normalize_basic_unreserved(b, t);
  367|  1.60k|    if (-2 == qs) {
  ------------------
  |  Branch (367:9): [True: 506, False: 1.10k]
  ------------------
  368|    506|        if (flags & HTTP_PARSEOPT_URL_NORMALIZE_INVALID_UTF8_REJECT) return -2;
  ------------------
  |  Branch (368:13): [True: 111, False: 395]
  ------------------
  369|    395|        qs = burl_scan_qmark(b);
  370|    395|    }
  371|       |
  372|  1.49k|    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_CTRLS_REJECT) {
  ------------------
  |  Branch (372:9): [True: 350, False: 1.14k]
  ------------------
  373|    350|        if (burl_contains_ctrls(b)) return -2;
  ------------------
  |  Branch (373:13): [True: 90, False: 260]
  ------------------
  374|    350|    }
  375|       |
  376|  1.40k|    if (flags & (HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE
  ------------------
  |  Branch (376:9): [True: 1.15k, False: 253]
  ------------------
  377|  1.40k|                |HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT)) {
  378|  1.15k|        qs = burl_normalize_2F_to_slash(b, qs, flags);
  379|  1.15k|        if (-2 == qs) return -2;
  ------------------
  |  Branch (379:13): [True: 27, False: 1.12k]
  ------------------
  380|  1.15k|    }
  381|       |
  382|  1.37k|    if (flags & (HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REMOVE
  ------------------
  |  Branch (382:9): [True: 1.10k, False: 275]
  ------------------
  383|  1.37k|                |HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT)) {
  384|  1.10k|        qs = burl_normalize_path(b, t, qs, flags);
  385|  1.10k|        if (-2 == qs) return -2;
  ------------------
  |  Branch (385:13): [True: 13, False: 1.09k]
  ------------------
  386|  1.10k|    }
  387|       |
  388|  1.36k|    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_QUERY_20_PLUS) {
  ------------------
  |  Branch (388:9): [True: 819, False: 546]
  ------------------
  389|    819|        if (qs >= 0) burl_normalize_qs20_to_plus(b, qs);
  ------------------
  |  Branch (389:13): [True: 395, False: 424]
  ------------------
  390|    819|    }
  391|       |
  392|  1.36k|    return qs;
  393|  1.37k|}
burl.c:burl_normalize_basic_required:
  179|    883|{
  180|    883|    const unsigned char * const s = (unsigned char *)b->ptr;
  181|    883|    const int used = (int)buffer_clen(b);
  182|    883|    unsigned int n1, n2, x;
  183|    883|    int qs = -1;
  184|    883|    int invalid_utf8 = 0;
  185|       |
  186|   488k|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (186:21): [True: 488k, False: 198]
  ------------------
  187|   488k|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (187:13): [True: 467k, False: 20.3k]
  ------------------
  188|   467k|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = i;
  ------------------
  |  Branch (188:17): [True: 12.0k, False: 455k]
  |  Branch (188:56): [True: 222, False: 11.8k]
  ------------------
  189|   467k|        }
  190|  20.3k|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  40.2k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 15.3k, False: 4.59k]
  |  |  |  Branch (43:30): [True: 4.51k, False: 74]
  |  |  |  Branch (43:31): [True: 4.51k, False: 74]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  40.2k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 10.3k, False: 9.49k]
  |  |  |  Branch (43:30): [True: 9.44k, False: 52]
  |  |  |  Branch (43:31): [True: 9.44k, False: 52]
  |  |  ------------------
  ------------------
  |  Branch (190:18): [True: 19.9k, False: 495]
  ------------------
  191|  19.7k|                 && (encoded_chars_http_uri_reqd[(x = (n1 << 4) | n2)]
  ------------------
  |  Branch (191:22): [True: 6.52k, False: 13.2k]
  ------------------
  192|  13.2k|                     || (qs < 0
  ------------------
  |  Branch (192:25): [True: 13.1k, False: 64]
  |  Branch (192:26): [True: 1.05k, False: 12.1k]
  ------------------
  193|  13.2k|                         ? (x == '/' || x == '?')
  ------------------
  |  Branch (193:29): [True: 682, False: 373]
  |  Branch (193:41): [True: 347, False: 26]
  ------------------
  194|  19.7k|                         : (x == '&' || x == '=' || x == ';' || x == '+')))) {
  ------------------
  |  Branch (194:29): [True: 6.79k, False: 5.40k]
  |  Branch (194:41): [True: 3.35k, False: 2.04k]
  |  Branch (194:53): [True: 480, False: 1.56k]
  |  Branch (194:65): [True: 1.53k, False: 38]
  ------------------
  195|  19.7k|            invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  19.7k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  19.7k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 748, False: 18.9k]
  |  |  |  |  ------------------
  |  |  |  |  261|  19.7k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 64, False: 18.8k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  196|  19.7k|            if (s[i+1] >= 'a') b->ptr[i+1] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (196:17): [True: 3.66k, False: 16.0k]
  ------------------
  197|  19.7k|            if (s[i+2] >= 'a') b->ptr[i+2] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (197:17): [True: 4.85k, False: 14.8k]
  ------------------
  198|  19.7k|            i+=2;
  199|  19.7k|        }
  200|    685|        else if (s[i] == '#') { /* ignore fragment */
  ------------------
  |  Branch (200:18): [True: 2, False: 683]
  ------------------
  201|      2|            buffer_truncate(b, (size_t)i);
  202|      2|            break;
  203|      2|        }
  204|    683|        else {
  205|    683|            qs = burl_normalize_basic_required_fix(b, t, i, qs);
  206|    683|            break;
  207|    683|        }
  208|   488k|    }
  209|       |
  210|    883|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (210:12): [True: 854, False: 29]
  ------------------
  211|    883|}
burl.c:burl_normalize_basic_required_fix:
  135|    683|{
  136|    683|    int j = i;
  137|    683|    const int used = (int)buffer_clen(b);
  138|    683|    const unsigned char * const s = (unsigned char *)b->ptr;
  139|    683|    unsigned char * const p =
  140|    683|      (unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
  141|    683|    unsigned int n1, n2;
  142|    683|    int invalid_utf8 = 0;
  143|    683|    memcpy(p, s, (size_t)i);
  144|  28.9M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (144:12): [True: 28.9M, False: 670]
  ------------------
  145|  28.9M|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (145:13): [True: 1.89M, False: 27.0M]
  ------------------
  146|  1.89M|            p[j] = s[i];
  147|  1.89M|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = j;
  ------------------
  |  Branch (147:17): [True: 10.9k, False: 1.88M]
  |  Branch (147:56): [True: 163, False: 10.7k]
  ------------------
  148|  1.89M|        }
  149|  27.0M|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  27.0M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 18.9k, False: 8.17k]
  |  |  |  Branch (43:30): [True: 3.62k, False: 4.55k]
  |  |  |  Branch (43:31): [True: 3.62k, False: 4.55k]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  22.5k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 10.1k, False: 12.4k]
  |  |  |  Branch (43:30): [True: 10.8k, False: 1.56k]
  |  |  |  Branch (43:31): [True: 10.8k, False: 1.56k]
  |  |  ------------------
  ------------------
  |  Branch (149:18): [True: 27.1k, False: 27.0M]
  ------------------
  150|  21.0k|            const unsigned int x = (n1 << 4) | n2;
  151|  21.0k|            if (!encoded_chars_http_uri_reqd[x]
  ------------------
  |  Branch (151:17): [True: 15.1k, False: 5.88k]
  ------------------
  152|  15.1k|                && (qs < 0
  ------------------
  |  Branch (152:20): [True: 2.42k, False: 12.7k]
  |  Branch (152:21): [True: 2.29k, False: 12.8k]
  ------------------
  153|  15.1k|                    ? (x != '/' && x != '?')
  ------------------
  |  Branch (153:24): [True: 1.33k, False: 961]
  |  Branch (153:36): [True: 910, False: 427]
  ------------------
  154|  15.1k|                    : (x != '&' && x != '=' && x != ';' && x != '+'))) {
  ------------------
  |  Branch (154:24): [True: 6.78k, False: 6.06k]
  |  Branch (154:36): [True: 3.98k, False: 2.79k]
  |  Branch (154:48): [True: 2.92k, False: 1.06k]
  |  Branch (154:60): [True: 1.51k, False: 1.41k]
  ------------------
  155|  2.42k|                p[j] = x;
  156|  2.42k|            }
  157|  18.6k|            else {
  158|  18.6k|                p[j]   = '%';
  159|  18.6k|                p[++j] = hex_chars_uc[n1]; /*(s[i+1] & 0xdf)*/
  160|  18.6k|                p[++j] = hex_chars_uc[n2]; /*(s[i+2] & 0xdf)*/
  161|  18.6k|                invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  18.6k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  18.6k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 1.45k, False: 17.1k]
  |  |  |  |  ------------------
  |  |  |  |  261|  18.6k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 157, False: 16.9k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  162|  18.6k|            }
  163|  21.0k|            i+=2;
  164|  21.0k|        }
  165|  27.0M|        else if (s[i] == '#') break; /* ignore fragment */
  ------------------
  |  Branch (165:18): [True: 13, False: 27.0M]
  ------------------
  166|  27.0M|        else {
  167|  27.0M|            p[j]   = '%';
  168|  27.0M|            p[++j] = hex_chars_uc[(s[i] >> 4) & 0xF];
  169|  27.0M|            p[++j] = hex_chars_uc[s[i] & 0xF];
  170|  27.0M|            invalid_utf8 |= li_utf8_invalid_byte(s[i]);
  ------------------
  |  |   49|  27.0M|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  27.0M|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 1.69M, False: 25.3M]
  |  |  |  |  ------------------
  |  |  |  |  261|  27.0M|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 747, False: 25.3M]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  171|  27.0M|        }
  172|  28.9M|    }
  173|    683|    buffer_copy_string_len(b, (char *)p, (size_t)j);
  174|    683|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (174:12): [True: 420, False: 263]
  ------------------
  175|    683|}
burl.c:burl_normalize_basic_unreserved:
  101|    723|{
  102|    723|    const unsigned char * const s = (unsigned char *)b->ptr;
  103|    723|    const int used = (int)buffer_clen(b);
  104|    723|    unsigned int n1, n2, x;
  105|    723|    int qs = -1;
  106|    723|    int invalid_utf8 = 0;
  107|       |
  108|   397k|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (108:21): [True: 397k, False: 168]
  ------------------
  109|   397k|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (109:13): [True: 393k, False: 3.51k]
  ------------------
  110|   393k|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = i;
  ------------------
  |  Branch (110:17): [True: 518, False: 393k]
  |  Branch (110:56): [True: 74, False: 444]
  ------------------
  111|   393k|        }
  112|  3.51k|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  6.64k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 1.03k, False: 2.09k]
  |  |  |  Branch (43:30): [True: 2.03k, False: 61]
  |  |  |  Branch (43:31): [True: 2.03k, False: 61]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  6.58k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 1.11k, False: 1.94k]
  |  |  |  Branch (43:30): [True: 1.89k, False: 50]
  |  |  |  Branch (43:31): [True: 1.89k, False: 50]
  |  |  ------------------
  ------------------
  |  Branch (112:18): [True: 3.12k, False: 390]
  ------------------
  113|  3.01k|                 && !burl_is_unreserved((x = (n1 << 4) | n2))) {
  ------------------
  |  Branch (113:21): [True: 2.96k, False: 54]
  ------------------
  114|  2.96k|            invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  2.96k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  2.96k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 876, False: 2.08k]
  |  |  |  |  ------------------
  |  |  |  |  261|  2.96k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 320, False: 1.76k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  115|  2.96k|            if (s[i+1] >= 'a') b->ptr[i+1] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (115:17): [True: 1.88k, False: 1.07k]
  ------------------
  116|  2.96k|            if (s[i+2] >= 'a') b->ptr[i+2] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (116:17): [True: 1.17k, False: 1.78k]
  ------------------
  117|  2.96k|            i+=2;
  118|  2.96k|        }
  119|    555|        else if (s[i] == '#') { /* ignore fragment */
  ------------------
  |  Branch (119:18): [True: 1, False: 554]
  ------------------
  120|      1|            buffer_truncate(b, (size_t)i);
  121|      1|            break;
  122|      1|        }
  123|    554|        else {
  124|    554|            qs = burl_normalize_basic_unreserved_fix(b, t, i, qs);
  125|    554|            break;
  126|    554|        }
  127|   397k|    }
  128|       |
  129|    723|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (129:12): [True: 694, False: 29]
  ------------------
  130|    723|}
burl.c:burl_is_unreserved:
   53|  21.7k|{
   54|  21.7k|    return (light_isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~');
  ------------------
  |  Branch (54:13): [True: 1.10k, False: 20.6k]
  |  Branch (54:33): [True: 334, False: 20.3k]
  |  Branch (54:45): [True: 331, False: 20.0k]
  |  Branch (54:57): [True: 787, False: 19.2k]
  |  Branch (54:69): [True: 383, False: 18.8k]
  ------------------
   55|  21.7k|}
burl.c:burl_normalize_basic_unreserved_fix:
   60|    554|{
   61|    554|    int j = i;
   62|    554|    const int used = (int)buffer_clen(b);
   63|    554|    const unsigned char * const s = (unsigned char *)b->ptr;
   64|    554|    unsigned char * const p =
   65|    554|      (unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
   66|    554|    unsigned int n1, n2;
   67|    554|    int invalid_utf8 = 0;
   68|    554|    memcpy(p, s, (size_t)i);
   69|  25.0M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (69:12): [True: 25.0M, False: 549]
  ------------------
   70|  25.0M|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (70:13): [True: 1.26M, False: 23.7M]
  ------------------
   71|  1.26M|            p[j] = s[i];
   72|  1.26M|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = j;
  ------------------
  |  Branch (72:17): [True: 4.98k, False: 1.26M]
  |  Branch (72:56): [True: 137, False: 4.84k]
  ------------------
   73|  1.26M|        }
   74|  23.7M|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  23.8M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 15.0k, False: 19.1k]
  |  |  |  Branch (43:30): [True: 8.83k, False: 10.2k]
  |  |  |  Branch (43:31): [True: 8.83k, False: 10.2k]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  23.8k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 4.09k, False: 19.7k]
  |  |  |  Branch (43:30): [True: 14.6k, False: 5.09k]
  |  |  |  Branch (43:31): [True: 14.6k, False: 5.09k]
  |  |  ------------------
  ------------------
  |  Branch (74:18): [True: 34.1k, False: 23.7M]
  ------------------
   75|  18.7k|            const unsigned int x = (n1 << 4) | n2;
   76|  18.7k|            if (burl_is_unreserved(x)) {
  ------------------
  |  Branch (76:17): [True: 2.88k, False: 15.8k]
  ------------------
   77|  2.88k|                p[j] = x;
   78|  2.88k|            }
   79|  15.8k|            else {
   80|  15.8k|                p[j]   = '%';
   81|  15.8k|                p[++j] = hex_chars_uc[n1]; /*(s[i+1] & 0xdf)*/
   82|  15.8k|                p[++j] = hex_chars_uc[n2]; /*(s[i+2] & 0xdf)*/
   83|  15.8k|                invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  15.8k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  15.8k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 4.09k, False: 11.8k]
  |  |  |  |  ------------------
  |  |  |  |  261|  15.8k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 1.03k, False: 10.7k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   84|  15.8k|            }
   85|  18.7k|            i+=2;
   86|  18.7k|        }
   87|  23.7M|        else if (s[i] == '#') break; /* ignore fragment */
  ------------------
  |  Branch (87:18): [True: 5, False: 23.7M]
  ------------------
   88|  23.7M|        else {
   89|  23.7M|            p[j]   = '%';
   90|  23.7M|            p[++j] = hex_chars_uc[(s[i] >> 4) & 0xF];
   91|  23.7M|            p[++j] = hex_chars_uc[s[i] & 0xF];
   92|  23.7M|            invalid_utf8 |= li_utf8_invalid_byte(s[i]);
  ------------------
  |  |   49|  23.7M|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  23.7M|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 81.0k, False: 23.6M]
  |  |  |  |  ------------------
  |  |  |  |  261|  23.7M|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 2.04k, False: 23.6M]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   93|  23.7M|        }
   94|  25.0M|    }
   95|    554|    buffer_copy_string_len(b, (char *)p, (size_t)j);
   96|    554|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (96:12): [True: 366, False: 188]
  ------------------
   97|    554|}
burl.c:burl_scan_qmark:
  337|    395|static int burl_scan_qmark (const buffer * const b) {
  338|    395|    const char * const qmark = strchr(b->ptr, '?');
  339|    395|    return qmark ? (int)(qmark - b->ptr) : -1;
  ------------------
  |  Branch (339:12): [True: 210, False: 185]
  ------------------
  340|    395|}
burl.c:burl_contains_ctrls:
  215|    350|{
  216|    350|    const char * const s = b->ptr;
  217|    350|    const int used = (int)buffer_clen(b);
  218|  9.41M|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (218:21): [True: 9.41M, False: 260]
  ------------------
  219|  9.41M|        if (s[i] == '%' && (s[i+1] < '2' || (s[i+1] == '7' && s[i+2] == 'F')))
  ------------------
  |  Branch (219:13): [True: 2.96M, False: 6.45M]
  |  Branch (219:29): [True: 79, False: 2.96M]
  |  Branch (219:46): [True: 433, False: 2.96M]
  |  Branch (219:63): [True: 11, False: 422]
  ------------------
  220|     90|            return 1;
  221|  9.41M|    }
  222|    260|    return 0;
  223|    350|}
burl.c:burl_normalize_2F_to_slash:
  282|  1.15k|{
  283|       |    /*("%2F" must already have been uppercased during normalization)*/
  284|  1.15k|    const char * const s = b->ptr;
  285|  1.15k|    const int used = qs < 0 ? (int)buffer_clen(b) : qs;
  ------------------
  |  Branch (285:22): [True: 691, False: 461]
  ------------------
  286|  74.2M|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (286:21): [True: 74.2M, False: 971]
  ------------------
  287|  74.2M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
  ------------------
  |  Branch (287:13): [True: 24.6M, False: 49.5M]
  |  Branch (287:28): [True: 7.28k, False: 24.6M]
  |  Branch (287:45): [True: 181, False: 7.10k]
  ------------------
  288|    181|            return !(flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT)
  ------------------
  |  Branch (288:20): [True: 154, False: 27]
  ------------------
  289|    181|              ? burl_normalize_2F_to_slash_fix(b, qs, i)     /* _DECODE */
  290|    181|              : -2; /*(flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT)*/
  291|    181|        }
  292|  74.2M|    }
  293|    971|    return qs;
  294|  1.15k|}
burl.c:burl_normalize_2F_to_slash_fix:
  258|    154|{
  259|    154|    char * const s = b->ptr;
  260|    154|    const int blen = (int)buffer_clen(b);
  261|    154|    const int used = qs < 0 ? blen : qs;
  ------------------
  |  Branch (261:22): [True: 94, False: 60]
  ------------------
  262|    154|    int j = i;
  263|  10.2M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (263:12): [True: 10.2M, False: 154]
  ------------------
  264|  10.2M|        s[j] = s[i];
  265|  10.2M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
  ------------------
  |  Branch (265:13): [True: 3.39M, False: 6.86M]
  |  Branch (265:28): [True: 13.7k, False: 3.37M]
  |  Branch (265:45): [True: 4.44k, False: 9.27k]
  ------------------
  266|  4.44k|            s[j] = '/';
  267|  4.44k|            i+=2;
  268|  4.44k|        }
  269|  10.2M|    }
  270|    154|    if (qs >= 0) {
  ------------------
  |  Branch (270:9): [True: 60, False: 94]
  ------------------
  271|     60|        const int qslen = blen - qs;
  272|     60|        memmove(s+j, s+qs, (size_t)qslen);
  273|     60|        qs = j;
  274|     60|        j += qslen;
  275|     60|    }
  276|    154|    buffer_truncate(b, j);
  277|    154|    return qs;
  278|    154|}
burl.c:burl_normalize_path:
  298|  1.10k|{
  299|  1.10k|    const unsigned char * const s = (unsigned char *)b->ptr;
  300|  1.10k|    const int used = (int)buffer_clen(b);
  301|  1.10k|    int path_simplify = 0;
  302|  5.06k|    for (int i = 0, len = qs < 0 ? used : qs; i < len; ++i) {
  ------------------
  |  Branch (302:27): [True: 674, False: 429]
  |  Branch (302:47): [True: 4.35k, False: 712]
  ------------------
  303|  4.35k|        if (s[i] == '.' && (s[i+1] != '.' || ++i)
  ------------------
  |  Branch (303:13): [True: 2.36k, False: 1.99k]
  |  Branch (303:29): [True: 870, False: 1.49k]
  |  Branch (303:46): [True: 1.49k, False: 0]
  ------------------
  304|  2.36k|            && (s[i+1] == '/' || s[i+1] == '?' || s[i+1] == '\0')) {
  ------------------
  |  Branch (304:17): [True: 97, False: 2.26k]
  |  Branch (304:34): [True: 46, False: 2.22k]
  |  Branch (304:51): [True: 78, False: 2.14k]
  ------------------
  305|    221|            path_simplify = 1;
  306|    221|            break;
  307|    221|        }
  308|  68.9M|        while (i < len && s[i] != '/') ++i;
  ------------------
  |  Branch (308:16): [True: 68.9M, False: 540]
  |  Branch (308:27): [True: 68.9M, False: 3.59k]
  ------------------
  309|  4.13k|        if (s[i] == '/' && s[i+1] == '/') { /*(s[len] != '/')*/
  ------------------
  |  Branch (309:13): [True: 3.59k, False: 540]
  |  Branch (309:28): [True: 170, False: 3.42k]
  ------------------
  310|    170|            path_simplify = 1;
  311|    170|            break;
  312|    170|        }
  313|  4.13k|    }
  314|       |
  315|  1.10k|    if (path_simplify) {
  ------------------
  |  Branch (315:9): [True: 391, False: 712]
  ------------------
  316|    391|        if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT) return -2;
  ------------------
  |  Branch (316:13): [True: 13, False: 378]
  ------------------
  317|    378|        if (qs >= 0) {
  ------------------
  |  Branch (317:13): [True: 138, False: 240]
  ------------------
  318|    138|            buffer_copy_string_len(t, b->ptr+qs, used - qs);
  319|    138|            buffer_truncate(b, qs);
  320|    138|        }
  321|       |
  322|    378|        buffer_path_simplify(b);
  323|       |
  324|    378|        if (qs >= 0) {
  ------------------
  |  Branch (324:13): [True: 138, False: 240]
  ------------------
  325|    138|            qs = (int)buffer_clen(b);
  326|    138|            buffer_append_string_len(b, BUF_PTR_LEN(t));
  ------------------
  |  |  297|    138|#define BUF_PTR_LEN(x)       (x)->ptr, buffer_clen(x)
  ------------------
  327|    138|        }
  328|    378|    }
  329|       |
  330|  1.09k|    return qs;
  331|  1.10k|}
burl.c:burl_normalize_qs20_to_plus:
  244|    395|{
  245|    395|    const char * const s = b->ptr;
  246|    395|    const int used = qs < 0 ? 0 : (int)buffer_clen(b);
  ------------------
  |  Branch (246:22): [True: 0, False: 395]
  ------------------
  247|    395|    int i;
  248|    395|    if (qs < 0) return;
  ------------------
  |  Branch (248:9): [True: 0, False: 395]
  ------------------
  249|  6.52M|    for (i = qs+1; i < used; ++i) {
  ------------------
  |  Branch (249:20): [True: 6.52M, False: 273]
  ------------------
  250|  6.52M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == '0') break;
  ------------------
  |  Branch (250:13): [True: 2.13M, False: 4.39M]
  |  Branch (250:28): [True: 12.2k, False: 2.12M]
  |  Branch (250:45): [True: 122, False: 12.1k]
  ------------------
  251|  6.52M|    }
  252|    395|    if (i != used) burl_normalize_qs20_to_plus_fix(b, i);
  ------------------
  |  Branch (252:9): [True: 122, False: 273]
  ------------------
  253|    395|}
burl.c:burl_normalize_qs20_to_plus_fix:
  228|    122|{
  229|    122|    char * const s = b->ptr;
  230|    122|    const int used = (int)buffer_clen(b);
  231|    122|    int j = i;
  232|  8.63M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (232:12): [True: 8.63M, False: 122]
  ------------------
  233|  8.63M|        s[j] = s[i];
  234|  8.63M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == '0') {
  ------------------
  |  Branch (234:13): [True: 2.80M, False: 5.82M]
  |  Branch (234:28): [True: 8.17k, False: 2.79M]
  |  Branch (234:45): [True: 1.91k, False: 6.26k]
  ------------------
  235|  1.91k|            s[j] = '+';
  236|  1.91k|            i+=2;
  237|  1.91k|        }
  238|  8.63M|    }
  239|    122|    buffer_truncate(b, j);
  240|    122|}

