fuzz.c:_ZL9mock_initP11mg_tcpip_if:
    1|  5.56k|static bool mock_init(struct mg_tcpip_if *ifp) {
    2|  5.56k|  (void) ifp;
    3|  5.56k|  return true;
    4|  5.56k|}
fuzz.c:_ZL7mock_txPKvmP11mg_tcpip_if:
    6|  6.68k|static size_t mock_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
    7|  6.68k|  (void) buf, (void) len, (void) ifp;
    8|  6.68k|  return len;
    9|  6.68k|}
fuzz.c:_ZL7mock_rxPvmP11mg_tcpip_if:
   11|  5.56k|static size_t mock_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
   12|  5.56k|  (void) buf, (void) len, (void) ifp;
   13|  5.56k|  return 0;
   14|  5.56k|}
fuzz.c:_ZL9mock_pollP11mg_tcpip_ifb:
   16|  5.56k|static bool mock_poll(struct mg_tcpip_if *ifp, bool s1) {
   17|  5.56k|  (void) ifp;
   18|  5.56k|  return s1;
   19|  5.56k|}

LLVMFuzzerTestOneInput:
   72|  5.56k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   73|  5.56k|  mg_log_set(MG_LL_INFO);
  ------------------
  |  | 1721|  5.56k|#define mg_log_set(level_) mg_log_level = (level_)
  ------------------
   74|       |
   75|  5.56k|  struct mg_dns_message dm;
   76|  5.56k|  mg_dns_parse(data, size, &dm);
   77|  5.56k|  mg_dns_parse(NULL, 0, &dm);
   78|       |
   79|  5.56k|  struct mg_http_message hm;
   80|  5.56k|  if (mg_http_parse((const char *) data, size, &hm) > 0) {
  ------------------
  |  Branch (80:7): [True: 1.92k, False: 3.63k]
  ------------------
   81|  1.92k|    mg_crc32(0, hm.method.buf, hm.method.len);
   82|  1.92k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   83|  1.92k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   84|  59.7k|    for (size_t i = 0; i < sizeof(hm.headers) / sizeof(hm.headers[0]); i++) {
  ------------------
  |  Branch (84:24): [True: 57.8k, False: 1.92k]
  ------------------
   85|  57.8k|      struct mg_str *k = &hm.headers[i].name, *v = &hm.headers[i].value;
   86|  57.8k|      mg_crc32(0, k->buf, k->len);
   87|  57.8k|      mg_crc32(0, v->buf, v->len);
   88|  57.8k|    }
   89|  1.92k|  }
   90|  5.56k|  mg_http_parse(NULL, 0, &hm);
   91|       |
   92|  5.56k|  struct mg_str body = mg_str_n((const char *) data, size);
   93|  5.56k|  char tmp[256];
   94|  5.56k|  mg_http_get_var(&body, "key", tmp, sizeof(tmp));
   95|  5.56k|  mg_http_get_var(&body, "key", NULL, 0);
   96|  5.56k|  mg_url_decode((char *) data, size, tmp, sizeof(tmp), 1);
   97|  5.56k|  mg_url_decode((char *) data, size, tmp, 1, 1);
   98|  5.56k|  mg_url_decode(NULL, 0, tmp, 1, 1);
   99|       |
  100|  5.56k|  struct mg_mqtt_message mm;
  101|  5.56k|  if (mg_mqtt_parse(data, size, 0, &mm) == MQTT_OK) {
  ------------------
  |  Branch (101:7): [True: 2.31k, False: 3.24k]
  ------------------
  102|  2.31k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
  103|  2.31k|    mg_crc32(0, mm.data.buf, mm.data.len);
  104|  2.31k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
  105|  2.31k|  }
  106|  5.56k|  mg_mqtt_parse(NULL, 0, 0, &mm);
  107|  5.56k|  if (mg_mqtt_parse(data, size, 5, &mm) == MQTT_OK) {
  ------------------
  |  Branch (107:7): [True: 2.16k, False: 3.39k]
  ------------------
  108|  2.16k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
  109|  2.16k|    mg_crc32(0, mm.data.buf, mm.data.len);
  110|  2.16k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
  111|  2.16k|    {
  112|  2.16k|      struct mg_mqtt_prop prop;
  113|  2.16k|      size_t ofs = 0;
  114|  8.25k|      while ((ofs = mg_mqtt_next_prop(&mm, &prop, ofs)) > 0) {
  ------------------
  |  Branch (114:14): [True: 6.08k, False: 2.16k]
  ------------------
  115|  6.08k|          mg_crc32(0, prop.key.buf, prop.key.len);
  116|  6.08k|          mg_crc32(0, prop.val.buf, prop.val.len);
  117|  6.08k|      }
  118|  2.16k|    }
  119|  2.16k|  }
  120|  5.56k|  mg_mqtt_parse(NULL, 0, 5, &mm);
  121|       |
  122|  5.56k|  mg_sntp_parse(data, size);
  123|  5.56k|  mg_sntp_parse(NULL, 0);
  124|       |
  125|  5.56k|  char buf[size * 4 / 3 + 5];  // At least 4 chars and nul termination
  126|  5.56k|  mg_base64_decode((char *) data, size, buf, sizeof(buf));
  127|  5.56k|  mg_base64_decode(NULL, 0, buf, sizeof(buf));
  128|  5.56k|  mg_base64_encode(data, size, buf, sizeof(buf));
  129|  5.56k|  mg_base64_encode(NULL, 0, buf, sizeof(buf));
  130|       |
  131|  5.56k|  mg_match(mg_str_n((char *) data, size), mg_str_n((char *) data, size), NULL);
  132|       |
  133|  5.56k|  struct mg_str entry, s = mg_str_n((char *) data, size);
  134|  1.03M|  while (mg_span(s, &entry, &s, ',')) entry.len = 0;
  ------------------
  |  Branch (134:10): [True: 1.03M, False: 5.56k]
  ------------------
  135|       |
  136|  5.56k|  int n;
  137|  5.56k|  mg_json_get(mg_str_n((char *) data, size), "$", &n);
  138|  5.56k|  mg_json_get(mg_str_n((char *) data, size), "$.a.b", &n);
  139|  5.56k|  mg_json_get(mg_str_n((char *) data, size), "$[0]", &n);
  140|       |
  141|       |  // Test built-in TCP/IP stack
  142|  5.56k|  if (size > 0) {
  ------------------
  |  Branch (142:7): [True: 5.56k, False: 0]
  ------------------
  143|  5.56k|    static size_t t;
  144|  5.56k|    struct mg_tcpip_if mif = {.ip = 1,
  145|  5.56k|                              .mask = 255,
  146|  5.56k|                              .gw = 1,
  147|  5.56k|                              .gw_ready = true,
  148|  5.56k|                              .state = MG_TCPIP_STATE_READY,
  ------------------
  |  | 4763|  5.56k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  149|       |#if MG_ENABLE_IPV6
  150|       |                              .ip6[0] = 1,
  151|       |                              .prefix[0] = 1,
  152|       |                              .prefix_len = 64,
  153|       |                              .gw6[0] = 1,
  154|       |                              .gw6_ready = true,
  155|       |                              .state6 = MG_TCPIP_STATE_READY,  // so mg_send() works and RS stops
  156|       |#endif
  157|  5.56k|                              .driver = &mg_tcpip_driver_mock};
  158|  5.56k|    struct mg_mgr mgr;
  159|       |
  160|  5.56k|    if (t >= MG_TCPIP_L2_USER) t = 0; // defined in l2.h
  ------------------
  |  Branch (160:9): [True: 1.85k, False: 3.70k]
  ------------------
  161|  5.56k|    mif.l2type = (enum mg_l2type) t++; // configure to a L2 type
  162|       |
  163|  5.56k|    mg_mgr_init(&mgr);
  164|  5.56k|    mg_tcpip_init(&mgr, &mif);
  165|       |
  166|       |    // Make a copy of the random data, in order to modify it
  167|  5.56k|    void *pkt = malloc(size);
  168|  5.56k|    struct eth *eth = (struct eth *) pkt;
  169|  5.56k|    memcpy(pkt, data, size);
  170|  5.56k|    if ((mif.l2type == MG_TCPIP_L2_ETH || mif.l2type == MG_TCPIP_L2_PPPoE) && size > sizeof(*eth)) {
  ------------------
  |  Branch (170:10): [True: 1.85k, False: 3.70k]
  |  Branch (170:43): [True: 1.85k, False: 1.85k]
  |  Branch (170:79): [True: 2.66k, False: 1.04k]
  ------------------
  171|  2.66k|      static size_t i, v;
  172|  2.66k|      static struct fuzz_l3_state l3;
  173|  2.66k|      uint8_t *ethpay = (uint8_t *) (eth + 1);
  174|  2.66k|      size_t ethhdrsz = sizeof(*eth);
  175|  2.66k|      uint16_t etype;
  176|       |      // eth_types[] exists in l2_eth.c
  177|  2.66k|      memcpy(eth->dst, mif.mac, 6);  // Set valid destination MAC
  178|       |      // send all handled eth types, then 2 random ones
  179|  2.66k|      if (i >= (sizeof(eth_types) / sizeof(eth_types[0]) + 2)) i = 0;
  ------------------
  |  Branch (179:11): [True: 0, False: 2.66k]
  ------------------
  180|  2.66k|      if (i < (sizeof(eth_types) / sizeof(eth_types[0]))) eth->type = mg_htons(eth_types[i++]);
  ------------------
  |  | 2037|      5|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (180:11): [True: 5, False: 2.65k]
  ------------------
  181|  2.66k|      etype = mg_ntohs(eth->type);
  182|  2.66k|      if (v >= 10) v = 0; // 802.1Q tag 3 out of 10 frames
  ------------------
  |  Branch (182:11): [True: 265, False: 2.39k]
  ------------------
  183|  2.66k|      if (v < 3) mif.l2data.eth.vlan_id = 123;
  ------------------
  |  Branch (183:11): [True: 798, False: 1.86k]
  ------------------
  184|  2.66k|      if (size > sizeof(*eth) + sizeof(struct qtag)) {
  ------------------
  |  Branch (184:11): [True: 2.42k, False: 231]
  ------------------
  185|  2.42k|        struct qtag *qtag = (struct qtag *) &eth->type;
  186|  2.42k|        if (v == 0) {
  ------------------
  |  Branch (186:13): [True: 242, False: 2.18k]
  ------------------
  187|       |          // v=0: configured for VLAN 123, untagged frame, discard path
  188|  2.18k|        } else if (v == 1) {
  ------------------
  |  Branch (188:20): [True: 243, False: 1.94k]
  ------------------
  189|       |          // v=1: configured for VLAN 123, tagged VLAN 123, accept path
  190|    243|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2037|    243|#define mg_htons(x) mg_ntohs(x)
  ------------------
  191|    243|          qtag->tci = mg_htons(123);
  ------------------
  |  | 2037|    243|#define mg_htons(x) mg_ntohs(x)
  ------------------
  192|    243|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2003|    243|  do {                                    \
  |  | 2004|    243|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2005|    243|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2006|    243|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2006:12): [Folded, False: 243]
  |  |  ------------------
  ------------------
  193|    243|          ethhdrsz += sizeof(*qtag);
  194|    243|          ethpay += sizeof(*qtag);
  195|  1.94k|        } else if (v == 2) {
  ------------------
  |  Branch (195:20): [True: 243, False: 1.70k]
  ------------------
  196|       |          // v=2: configured for VLAN 123, tagged random VLAN, mismatch path
  197|    243|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2037|    243|#define mg_htons(x) mg_ntohs(x)
  ------------------
  198|    243|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2003|    243|  do {                                    \
  |  | 2004|    243|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2005|    243|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2006|    243|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2006:12): [Folded, False: 243]
  |  |  ------------------
  ------------------
  199|    243|          ethhdrsz += sizeof(*qtag);
  200|    243|          ethpay += sizeof(*qtag);
  201|  1.70k|        } else if (v == 3) {
  ------------------
  |  Branch (201:20): [True: 243, False: 1.45k]
  ------------------
  202|       |          // v=3: unconfigured VLAN, tagged frame, discard path
  203|    243|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2037|    243|#define mg_htons(x) mg_ntohs(x)
  ------------------
  204|    243|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2003|    243|  do {                                    \
  |  | 2004|    243|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2005|    243|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 1976|    243|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2006|    243|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2006:12): [Folded, False: 243]
  |  |  ------------------
  ------------------
  205|    243|          ethhdrsz += sizeof(*qtag);
  206|    243|          ethpay += sizeof(*qtag);
  207|    243|        } // else unconfigured VLAN, untagged frame, normal path
  208|  2.42k|      }
  209|  2.66k|      ++v;
  210|  2.66k|      if (etype == 0x8863 && size > (ethhdrsz + sizeof(struct pppoe))) { // PPPoE disc
  ------------------
  |  Branch (210:11): [True: 80, False: 2.58k]
  |  Branch (210:30): [True: 74, False: 6]
  ------------------
  211|     74|        static size_t j;
  212|     74|        uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6384|     74|#define MG_PPPoE_PADO 0x07
  ------------------
                      uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6386|     74|#define MG_PPPoE_PADS 0x65
  ------------------
                      uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6387|     74|#define MG_PPPoE_PADT 0xa7
  ------------------
  213|     74|        struct pppoe *pppoe = (struct pppoe *) ethpay;
  214|     74|        pppoe->vertype = 0x11;
  215|       |        // send all handled PPPoE codes, then 2 random ones
  216|     74|        if (j >= (sizeof(pppoe_codes) / sizeof(pppoe_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (216:13): [True: 0, False: 74]
  ------------------
  217|     74|        if (j < (sizeof(pppoe_codes) / sizeof(pppoe_codes[0]))) pppoe->code = (pppoe_codes[j++]);
  ------------------
  |  Branch (217:13): [True: 3, False: 71]
  ------------------
  218|     74|        if (pppoe->code == MG_PPPoE_PADO) {
  ------------------
  |  | 6384|     74|#define MG_PPPoE_PADO 0x07
  ------------------
  |  Branch (218:13): [True: 10, False: 64]
  ------------------
  219|     10|          static size_t k;
  220|       |          // send id=0, then 2 random ids
  221|     10|          if (k >= 3) k = 0;
  ------------------
  |  Branch (221:15): [True: 3, False: 7]
  ------------------
  222|     10|          if (k == 0) pppoe->id = 0;
  ------------------
  |  Branch (222:15): [True: 4, False: 6]
  ------------------
  223|     10|          ++k;
  224|     64|        } else if (pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6386|     64|#define MG_PPPoE_PADS 0x65
  ------------------
  |  Branch (224:20): [True: 1, False: 63]
  ------------------
  225|      1|          static size_t k;
  226|       |          // send id=x, then 2 random ids
  227|      1|          if (k >= 3) k = 0;
  ------------------
  |  Branch (227:15): [True: 0, False: 1]
  ------------------
  228|      1|          if (k == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (228:15): [True: 1, False: 0]
  ------------------
  229|      1|          ++k;
  230|     63|        } else if (pppoe->code == MG_PPPoE_PADT) { // keep separate so they do not correlate too much
  ------------------
  |  | 6387|     63|#define MG_PPPoE_PADT 0xa7
  ------------------
  |  Branch (230:20): [True: 14, False: 49]
  ------------------
  231|     14|          static size_t k;
  232|       |          // send id=x, then 2 random ids
  233|     14|          if (k >= 3) k = 0;
  ------------------
  |  Branch (233:15): [True: 4, False: 10]
  ------------------
  234|     14|          if (k == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (234:15): [True: 5, False: 9]
  ------------------
  235|     14|          ++k;
  236|     14|        }
  237|  2.58k|      } else if (etype == 0x8864 && size > (ethhdrsz + sizeof(struct pppoe))) { // PPPoE sess
  ------------------
  |  Branch (237:18): [True: 55, False: 2.53k]
  |  Branch (237:37): [True: 52, False: 3]
  ------------------
  238|       |        // PPP rx is covered via HDLC too; PPPoE tx wrapping may remain unexercised.
  239|     52|        struct pppoe *pppoe = (struct pppoe *) ethpay;
  240|     52|        static size_t k, l;
  241|       |        // send code=0, then 2 random codes
  242|     52|        if (k >= 3) k = 0;
  ------------------
  |  Branch (242:13): [True: 17, False: 35]
  ------------------
  243|     52|        if (k == 0)  {
  ------------------
  |  Branch (243:13): [True: 18, False: 34]
  ------------------
  244|     18|          static size_t m;
  245|     18|          pppoe->code = 0;
  246|       |          // send id=x, then 2 random ids
  247|     18|          if (m >= 3) m = 0;
  ------------------
  |  Branch (247:15): [True: 5, False: 13]
  ------------------
  248|     18|          if (m == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (248:15): [True: 6, False: 12]
  ------------------
  249|     18|          ++m;
  250|     18|        }
  251|     52|        ++k;
  252|       |        // set s_state to valid and invalid
  253|     52|        if (l >= 2) l = 0;
  ------------------
  |  Branch (253:13): [True: 25, False: 27]
  ------------------
  254|     52|        if (l == 0) s_state = MG_PPPoE_ST_SESS; // defined in l2_ppp.c
  ------------------
  |  | 6391|     26|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (254:13): [True: 26, False: 26]
  ------------------
  255|     52|        if (l == 1) s_state = MG_PPPoE_ST_REQ;
  ------------------
  |  | 6390|     26|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
  |  Branch (255:13): [True: 26, False: 26]
  ------------------
  256|     52|        ++l;
  257|       |        // PPP exercised in other block
  258|     52|      }
  259|       |      // build proper layer-3 datagrams, to be able to exercise layers above
  260|  2.53k|      else if (etype == 0x800 && size > (ethhdrsz + sizeof(struct ip))) {         // IPv4
  ------------------
  |  Branch (260:16): [True: 122, False: 2.41k]
  |  Branch (260:34): [True: 112, False: 10]
  ------------------
  261|    112|        fuzz_ip4(ethpay, size - ethhdrsz, &l3);
  262|  2.42k|      } else if (etype == 0x806) {      // ARP
  ------------------
  |  Branch (262:18): [True: 80, False: 2.34k]
  ------------------
  263|       |
  264|  2.34k|      } else if (etype == 0x86dd && size > (ethhdrsz + sizeof(struct ip6))) {     // IPv6
  ------------------
  |  Branch (264:18): [True: 30, False: 2.31k]
  |  Branch (264:37): [True: 28, False: 2]
  ------------------
  265|     28|        fuzz_ip6(ethpay, size - ethhdrsz, &l3);
  266|     28|      }
  267|  2.90k|    } else if (mif.l2type == MG_TCPIP_L2_PPP && size > (sizeof(struct hdlc_) + sizeof(struct ppp) + 2)) {
  ------------------
  |  Branch (267:16): [True: 1.85k, False: 1.04k]
  |  Branch (267:49): [True: 1.55k, False: 294]
  ------------------
  268|  1.55k|      static size_t i;
  269|  1.55k|      static struct fuzz_l3_state l3;
  270|  1.55k|      uint16_t ppp_protos[] = {
  271|  1.55k|          MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6355|  1.55k|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6356|  1.55k|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6353|  1.55k|#define MG_PPP_PROTO_IP 0x0021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6357|  1.55k|#define MG_PPP_PROTO_IPV6CP 0x8057
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6354|  1.55k|#define MG_PPP_PROTO_IPV6 0x0057
  ------------------
  272|  1.55k|      };
  273|  1.55k|      struct hdlc_ *hdlc = (struct hdlc_ *) pkt;
  274|  1.55k|      struct ppp *ppp = (struct ppp *) (hdlc + 1);
  275|  1.55k|      size_t len = size - sizeof(*hdlc) - sizeof(*ppp) - 2;
  276|  1.55k|      hdlc->addr = MG_PPP_ADDR;
  ------------------
  |  | 6350|  1.55k|#define MG_PPP_ADDR 0xff
  ------------------
  277|  1.55k|      hdlc->ctrl = MG_PPP_CTRL;
  ------------------
  |  | 6351|  1.55k|#define MG_PPP_CTRL 0x03
  ------------------
  278|  1.55k|      s_lcpup = true;
  279|       |      // send all handled PPP protocols, then 2 random ones
  280|  1.55k|      if (i >= (sizeof(ppp_protos) / sizeof(ppp_protos[0]) + 2)) i = 0;
  ------------------
  |  Branch (280:11): [True: 0, False: 1.55k]
  ------------------
  281|  1.55k|      if (i < (sizeof(ppp_protos) / sizeof(ppp_protos[0]))) ppp->proto = mg_htons(ppp_protos[i++]);
  ------------------
  |  | 2037|      5|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (281:11): [True: 5, False: 1.55k]
  ------------------
  282|  1.55k|      if (ppp->proto == mg_htons(MG_PPP_PROTO_LCP) && len >= sizeof(struct lcp)) {
  ------------------
  |  | 2037|  3.11k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (282:11): [True: 39, False: 1.52k]
  |  Branch (282:55): [True: 38, False: 1]
  ------------------
  283|     38|        static size_t j, k;
  284|     38|        uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6361|     38|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6362|     38|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6365|     38|#define MG_PPP_LCP_CFG_TERM_REQ 5
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6368|     38|#define MG_PPP_LCP_ECHO_REQ 9
  ------------------
  285|     38|        struct lcp *lcp = (struct lcp *) (ppp + 1);
  286|       |        // send all handled LCP codes, then 2 random ones
  287|     38|        if (j >= (sizeof(lcp_codes) / sizeof(lcp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (287:13): [True: 0, False: 38]
  ------------------
  288|     38|        if (j < (sizeof(lcp_codes) / sizeof(lcp_codes[0]))) lcp->code = lcp_codes[j++];
  ------------------
  |  Branch (288:13): [True: 4, False: 34]
  ------------------
  289|       |        // send valid length, then 2 random lengths
  290|     38|        if (k >= 3) k = 0;
  ------------------
  |  Branch (290:13): [True: 12, False: 26]
  ------------------
  291|     38|        if (k == 0) lcp->len = mg_htons((uint16_t) sizeof(*lcp));
  ------------------
  |  | 2037|     13|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (291:13): [True: 13, False: 25]
  ------------------
  292|     38|        ++k;
  293|  1.52k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPCP) && len >= 10) {
  ------------------
  |  | 2037|  3.04k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (293:18): [True: 36, False: 1.48k]
  |  Branch (293:63): [True: 28, False: 8]
  ------------------
  294|     28|        static size_t j, k, m;
  295|     28|        uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6371|     28|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6372|     28|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6373|     28|#define MG_PPP_IPCP_CFG_NACK 3
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6374|     28|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
  296|     28|        struct ipcp *ipcp = (struct ipcp *) (ppp + 1);
  297|     28|        uint8_t *opts = (uint8_t *) (ipcp + 1);
  298|       |        // send all handled IPCP codes, then 2 random ones
  299|     28|        if (j >= (sizeof(ipcp_codes) / sizeof(ipcp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (299:13): [True: 0, False: 28]
  ------------------
  300|     28|        if (j < (sizeof(ipcp_codes) / sizeof(ipcp_codes[0]))) ipcp->code = ipcp_codes[j++];
  ------------------
  |  Branch (300:13): [True: 4, False: 24]
  ------------------
  301|       |        // send valid length, then 2 random lengths
  302|     28|        if (m >= 3) m = 0;
  ------------------
  |  Branch (302:13): [True: 9, False: 19]
  ------------------
  303|     28|        if (m == 0) ipcp->len = mg_htons(10);
  ------------------
  |  | 2037|     10|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (303:13): [True: 10, False: 18]
  ------------------
  304|     28|        ++m;
  305|       |        // send valid IPADDR option, then 2 random option types
  306|     28|        if (k >= 3) k = 0;
  ------------------
  |  Branch (306:13): [True: 9, False: 19]
  ------------------
  307|     28|        if (k == 0) {
  ------------------
  |  Branch (307:13): [True: 10, False: 18]
  ------------------
  308|     10|          static size_t l;
  309|     10|          opts[0] = MG_PPP_IPCP_OPT_IPADDR;
  ------------------
  |  | 6375|     10|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  310|       |          // for valid option type, send valid length, then random length
  311|     10|          if (l >= 2) l = 0;
  ------------------
  |  Branch (311:15): [True: 4, False: 6]
  ------------------
  312|     10|          if (l == 0) opts[1] = 6;
  ------------------
  |  Branch (312:15): [True: 5, False: 5]
  ------------------
  313|     10|          ++l;
  314|     10|        }
  315|     28|        ++k;
  316|  1.49k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IP) && len >= sizeof(struct ip)) {
  ------------------
  |  | 2037|  2.98k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (316:18): [True: 60, False: 1.43k]
  |  Branch (316:61): [True: 52, False: 8]
  ------------------
  317|     52|        fuzz_ip4(ppp + 1, len, &l3);
  318|  1.44k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPV6CP) && len >= 14) {
  ------------------
  |  | 2037|  2.88k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (318:18): [True: 11, False: 1.43k]
  |  Branch (318:65): [True: 10, False: 1]
  ------------------
  319|     10|        static size_t j, k, m;
  320|     10|        uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6377|     10|#define MG_PPP_IPV6CP_CFG_REQ 1
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6378|     10|#define MG_PPP_IPV6CP_CFG_ACK 2
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6379|     10|#define MG_PPP_IPV6CP_CFG_NACK 3
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6380|     10|#define MG_PPP_IPV6CP_CFG_REJECT 4
  ------------------
  321|     10|        struct ipv6cp *ipv6cp = (struct ipv6cp *) (ppp + 1);
  322|     10|        uint8_t *opts = (uint8_t *) (ipv6cp + 1);
  323|       |        // send all handled IPV6CP codes, then 2 random ones
  324|     10|        if (j >= (sizeof(ipv6cp_codes) / sizeof(ipv6cp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (324:13): [True: 0, False: 10]
  ------------------
  325|     10|        if (j < (sizeof(ipv6cp_codes) / sizeof(ipv6cp_codes[0]))) ipv6cp->code = ipv6cp_codes[j++];
  ------------------
  |  Branch (325:13): [True: 4, False: 6]
  ------------------
  326|       |        // send valid length, then 2 random lengths
  327|     10|        if (m >= 3) m = 0;
  ------------------
  |  Branch (327:13): [True: 3, False: 7]
  ------------------
  328|     10|        if (m == 0) ipv6cp->len = mg_htons(14);
  ------------------
  |  | 2037|      4|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (328:13): [True: 4, False: 6]
  ------------------
  329|     10|        ++m;
  330|       |        // send valid IFCID option, then 2 random option types
  331|     10|        if (k >= 3) k = 0;
  ------------------
  |  Branch (331:13): [True: 3, False: 7]
  ------------------
  332|     10|        if (k == 0) {
  ------------------
  |  Branch (332:13): [True: 4, False: 6]
  ------------------
  333|      4|          static size_t l;
  334|      4|          opts[0] = MG_PPP_IPV6CP_OPT_IFCID;
  ------------------
  |  | 6381|      4|#define MG_PPP_IPV6CP_OPT_IFCID 1
  ------------------
  335|       |          // for valid option type, send valid length, then random length
  336|      4|          if (l >= 2) l = 0;
  ------------------
  |  Branch (336:15): [True: 1, False: 3]
  ------------------
  337|      4|          if (l == 0) {
  ------------------
  |  Branch (337:15): [True: 2, False: 2]
  ------------------
  338|      2|            static size_t o;
  339|      2|            opts[1] = 10;
  340|       |            // for valid option length, send non-zero IFCID, then 2 random IFCIDs
  341|      2|            if (o >= 3) o = 0;
  ------------------
  |  Branch (341:17): [True: 0, False: 2]
  ------------------
  342|      2|            if (o == 0) opts[9] = 1;
  ------------------
  |  Branch (342:17): [True: 1, False: 1]
  ------------------
  343|      2|            ++o;
  344|      2|          }
  345|      4|          ++l;
  346|      4|        }
  347|     10|        ++k;
  348|  1.43k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPV6) && len >= sizeof(struct ip6)) {
  ------------------
  |  | 2037|  2.86k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (348:18): [True: 29, False: 1.40k]
  |  Branch (348:63): [True: 24, False: 5]
  ------------------
  349|     24|        fuzz_ip6(ppp + 1, len, &l3);
  350|     24|      }
  351|  1.55k|    }
  352|       |
  353|       |#if defined(MAIN)
  354|       |    printf("Sending to net_builtin:\n");
  355|       |    mg_hexdump(pkt, size);
  356|       |#endif
  357|  5.56k|    mg_tcpip_rx(&mif, pkt, size);
  358|       |
  359|       |    // prior actions may have had consequences on link state
  360|  5.56k|    mif.state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4763|  5.56k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  361|       |    // Test HTTP serving (via our built-in TCP/IP stack)
  362|  5.56k|    const char *url = "http://localhost:12345"; // internally resolves
  363|       |    // creates a connection and sends SYN via the router, unless OOM
  364|  5.56k|    struct mg_connection *c = mg_http_connect(&mgr, url, fn, NULL);
  365|  5.56k|    mg_iobuf_add(&c->recv, 0, data, size);
  366|  5.56k|    c->pfn(c, MG_EV_READ, NULL); // manually invoke protocol event handler
  367|       |
  368|  5.56k|    free(pkt);
  369|  5.56k|    mg_mgr_free(&mgr);
  370|  5.56k|  }
  371|       |
  372|  5.56k|  return 0;
  373|  5.56k|}
fuzz.c:_ZL8fuzz_ip4PvmP13fuzz_l3_state:
   32|    164|static void fuzz_ip4(void *buf, size_t len, struct fuzz_l3_state *st) {
   33|    164|  if (len >= sizeof(struct ip)) {
  ------------------
  |  Branch (33:7): [True: 164, False: 0]
  ------------------
   34|    164|    uint8_t ip_protos[] = {1, 6, 17}; // ICMP, TCP, UDP
   35|    164|    struct ip *ip4 = (struct ip *) buf;
   36|    164|    ip4->ver = (uint8_t) ((ip4->ver & ~0xf0) | (4 << 4));
   37|       |    // send all handled IP protos, then 2 random ones
   38|    164|    if (st->ip_proto >= (sizeof(ip_protos) / sizeof(ip_protos[0]) + 2)) st->ip_proto = 0;
  ------------------
  |  Branch (38:9): [True: 0, False: 164]
  ------------------
   39|    164|    if (st->ip_proto < (sizeof(ip_protos) / sizeof(ip_protos[0]))) ip4->proto = ip_protos[st->ip_proto++];
  ------------------
  |  Branch (39:9): [True: 6, False: 158]
  ------------------
   40|    164|    if (ip4->proto == 1) { // ICMP
  ------------------
  |  Branch (40:9): [True: 34, False: 130]
  ------------------
   41|    130|    } else if (ip4->proto == 6) { // TCP
  ------------------
  |  Branch (41:16): [True: 2, False: 128]
  ------------------
   42|    128|    } else if (ip4->proto == 17 && len >= sizeof(struct ip) + sizeof(struct udp)) { // UDP
  ------------------
  |  Branch (42:16): [True: 22, False: 106]
  |  Branch (42:36): [True: 20, False: 2]
  ------------------
   43|     20|      uint16_t udp_ports[] = {67, 68}; // DHCP server and client
   44|     20|      struct udp *udp = (struct udp *) (ip4 + 1);
   45|       |      // send all handled UDP ports, then 2 random ones
   46|     20|      if (st->udp_port >= (sizeof(udp_ports) / sizeof(udp_ports[0]) + 2)) st->udp_port = 0;
  ------------------
  |  Branch (46:11): [True: 0, False: 20]
  ------------------
   47|     20|      if (st->udp_port < (sizeof(udp_ports) / sizeof(udp_ports[0]))) udp->dport = mg_htons(udp_ports[st->udp_port++]);
  ------------------
  |  | 2037|      4|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (47:11): [True: 4, False: 16]
  ------------------
   48|     20|    }
   49|    164|  }
   50|    164|}
fuzz.c:_ZL8fuzz_ip6PvmP13fuzz_l3_state:
   52|     52|static void fuzz_ip6(void *buf, size_t len, struct fuzz_l3_state *st) {
   53|     52|  if (len >= sizeof(struct ip6)) {
  ------------------
  |  Branch (53:7): [True: 52, False: 0]
  ------------------
   54|     52|    uint8_t ip6_protos[] = {6, 17, 58}; // TCP, UDP, ICMPv6
   55|     52|    struct ip6 *ip6 = (struct ip6 *) buf;
   56|     52|    ip6->ver = (uint8_t) ((ip6->ver & ~0xf0) | (6 << 4));
   57|       |    // send all handled IPv6 "next headers", then 2 random ones
   58|     52|    if (st->ip6_next >= (sizeof(ip6_protos) / sizeof(ip6_protos[0]) + 2)) st->ip6_next = 0;
  ------------------
  |  Branch (58:9): [True: 0, False: 52]
  ------------------
   59|     52|    if (st->ip6_next < (sizeof(ip6_protos) / sizeof(ip6_protos[0]))) ip6->next = ip6_protos[st->ip6_next++];
  ------------------
  |  Branch (59:9): [True: 6, False: 46]
  ------------------
   60|     52|    if (ip6->next == 6) { // TCP
  ------------------
  |  Branch (60:9): [True: 2, False: 50]
  ------------------
   61|     50|    } else if (ip6->next == 17) { // UDP
  ------------------
  |  Branch (61:16): [True: 2, False: 48]
  ------------------
   62|     48|    } else if (ip6->next == 58 && len >= sizeof(struct ip6) + sizeof(struct icmp6)) { // ICMPv6
  ------------------
  |  Branch (62:16): [True: 28, False: 20]
  |  Branch (62:35): [True: 28, False: 0]
  ------------------
   63|     28|      uint8_t icmp6_types[] = {128, 134, 135, 136}; // Echo Request, RA, NS, NA
   64|     28|      struct icmp6 *icmp6 = (struct icmp6 *) (ip6 + 1);
   65|       |      // send all handled ICMPv6 types, then 2 random ones
   66|     28|      if (st->icmp6_type >= (sizeof(icmp6_types) / sizeof(icmp6_types[0]) + 2)) st->icmp6_type = 0;
  ------------------
  |  Branch (66:11): [True: 0, False: 28]
  ------------------
   67|     28|      if (st->icmp6_type < (sizeof(icmp6_types) / sizeof(icmp6_types[0]))) icmp6->type = icmp6_types[st->icmp6_type++];
  ------------------
  |  Branch (67:11): [True: 8, False: 20]
  ------------------
   68|     28|    }
   69|     52|  }
   70|     52|}
fuzz.c:_ZL2fnP13mg_connectioniPv:
   19|   824k|static void fn(struct mg_connection *c, int ev, void *ev_data) {
   20|   824k|  struct mg_http_serve_opts opts = {.root_dir = "."};
   21|   824k|  if (ev == MG_EV_HTTP_MSG) {
  ------------------
  |  Branch (21:7): [True: 397k, False: 427k]
  ------------------
   22|   397k|    mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts);
   23|   397k|  }
   24|   824k|}

mg_base64_update:
   65|   195M|size_t mg_base64_update(unsigned char ch, char *to, size_t n) {
   66|   195M|  unsigned long rem = (n & 3) % 3;
   67|   195M|  if (rem == 0) {
  ------------------
  |  Branch (67:7): [True: 65.2M, False: 130M]
  ------------------
   68|  65.2M|    to[n] = (char) mg_base64_encode_single(ch >> 2);
   69|  65.2M|    to[++n] = (char) ((ch & 3) << 4);
   70|   130M|  } else if (rem == 1) {
  ------------------
  |  Branch (70:14): [True: 65.2M, False: 65.2M]
  ------------------
   71|  65.2M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 4));
   72|  65.2M|    to[++n] = (char) ((ch & 15) << 2);
   73|  65.2M|  } else {
   74|  65.2M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 6));
   75|  65.2M|    to[++n] = (char) mg_base64_encode_single(ch & 63);
   76|  65.2M|    n++;
   77|  65.2M|  }
   78|   195M|  return n;
   79|   195M|}
mg_base64_final:
   81|  11.1k|size_t mg_base64_final(char *to, size_t n) {
   82|  11.1k|  size_t saved = n;
   83|       |  // printf("---[%.*s]\n", n, to);
   84|  11.1k|  if (n & 3) n = mg_base64_update(0, to, n);
  ------------------
  |  Branch (84:7): [True: 3.71k, False: 7.40k]
  ------------------
   85|  11.1k|  if ((saved & 3) == 2) n--;
  ------------------
  |  Branch (85:7): [True: 1.72k, False: 9.39k]
  ------------------
   86|       |  // printf("    %d[%.*s]\n", n, n, to);
   87|  16.8k|  while (n & 3) to[n++] = '=';
  ------------------
  |  Branch (87:10): [True: 5.70k, False: 11.1k]
  ------------------
   88|  11.1k|  to[n] = '\0';
   89|  11.1k|  return n;
   90|  11.1k|}
mg_base64_encode:
   92|  11.1k|size_t mg_base64_encode(const unsigned char *p, size_t n, char *to, size_t dl) {
   93|  11.1k|  size_t i, len = 0;
   94|  11.1k|  if (dl > 0) to[0] = '\0';
  ------------------
  |  Branch (94:7): [True: 11.1k, False: 0]
  ------------------
   95|  11.1k|  if (dl < ((n / 3) + (n % 3 ? 1 : 0)) * 4 + 1) return 0;
  ------------------
  |  Branch (95:7): [True: 0, False: 11.1k]
  |  Branch (95:24): [True: 3.71k, False: 7.40k]
  ------------------
   96|   195M|  for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
  ------------------
  |  Branch (96:15): [True: 195M, False: 11.1k]
  ------------------
   97|  11.1k|  len = mg_base64_final(to, len);
   98|  11.1k|  return len;
   99|  11.1k|}
mg_base64_decode:
  101|  11.1k|size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t dl) {
  102|  11.1k|  const char *end = src == NULL ? NULL : src + n;  // Cannot add to NULL
  ------------------
  |  Branch (102:21): [True: 5.56k, False: 5.56k]
  ------------------
  103|  11.1k|  size_t len = 0;
  104|  11.1k|  if (dl < n / 4 * 3 + 1) goto fail;
  ------------------
  |  Branch (104:7): [True: 0, False: 11.1k]
  ------------------
  105|   698k|  while (src != NULL && src + 3 < end) {
  ------------------
  |  Branch (105:10): [True: 692k, False: 5.56k]
  |  Branch (105:25): [True: 692k, False: 535]
  ------------------
  106|   692k|    int a = mg_base64_decode_single(src[0]),
  107|   692k|        b = mg_base64_decode_single(src[1]),
  108|   692k|        c = mg_base64_decode_single(src[2]),
  109|   692k|        d = mg_base64_decode_single(src[3]);
  110|   692k|    if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) {
  ------------------
  |  Branch (110:9): [True: 21, False: 692k]
  |  Branch (110:20): [True: 2.41k, False: 689k]
  |  Branch (110:29): [True: 6, False: 689k]
  |  Branch (110:40): [True: 917, False: 688k]
  |  Branch (110:49): [True: 1.47k, False: 687k]
  |  Branch (110:58): [True: 194, False: 687k]
  ------------------
  111|  5.02k|      goto fail;
  112|  5.02k|    }
  113|   687k|    dst[len++] = (char) ((a << 2) | (b >> 4));
  114|   687k|    if (src[2] != '=') {
  ------------------
  |  Branch (114:9): [True: 686k, False: 267]
  ------------------
  115|   686k|      dst[len++] = (char) ((b << 4) | (c >> 2));
  116|   686k|      if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
  ------------------
  |  Branch (116:11): [True: 686k, False: 238]
  ------------------
  117|   686k|    }
  118|   687k|    src += 4;
  119|   687k|  }
  120|  6.09k|  dst[len] = '\0';
  121|  6.09k|  return len;
  122|  5.02k|fail:
  123|  5.02k|  if (dl > 0) dst[0] = '\0';
  ------------------
  |  Branch (123:7): [True: 5.02k, False: 0]
  ------------------
  124|  5.02k|  return 0;
  125|  11.1k|}
mg_resolve_cancel:
 2045|  5.56k|void mg_resolve_cancel(struct mg_connection *c) {
 2046|  5.56k|  struct dns_data *tmp, *d;
 2047|  5.56k|  struct mdns_data *mtmp, *md;
 2048|  5.56k|  struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
 2049|  5.56k|  struct mdns_data **mhead =
 2050|  5.56k|      (struct mdns_data **) &c->mgr->active_mdns_requests;
 2051|  5.56k|  for (d = *head; d != NULL; d = tmp) {
  ------------------
  |  Branch (2051:19): [True: 0, False: 5.56k]
  ------------------
 2052|      0|    tmp = d->next;
 2053|      0|    if (d->c == c) dns_free(head, d);
  ------------------
  |  Branch (2053:9): [True: 0, False: 0]
  ------------------
 2054|      0|  }
 2055|  5.56k|  for (md = *mhead; md != NULL; md = mtmp) {
  ------------------
  |  Branch (2055:21): [True: 0, False: 5.56k]
  ------------------
 2056|      0|    mtmp = md->next;
 2057|      0|    if (md->c == c) mdns_free(mhead, md);
  ------------------
  |  Branch (2057:9): [True: 0, False: 0]
  ------------------
 2058|      0|  }
 2059|  5.56k|}
mg_dns_parse_rr:
 2104|    707|                       bool is_question, struct mg_dns_rr *rr) {
 2105|    707|  const uint8_t *s = buf + ofs, *e = &buf[len];
 2106|       |
 2107|    707|  memset(rr, 0, sizeof(*rr));
 2108|    707|  if (len < sizeof(struct mg_dns_header)) return 0;  // Too small
  ------------------
  |  Branch (2108:7): [True: 0, False: 707]
  ------------------
 2109|    707|  if (len > 512) return 0;  //  Too large, we don't expect that
  ------------------
  |  Branch (2109:7): [True: 20, False: 687]
  ------------------
 2110|    687|  if (s >= e) return 0;     //  Overflow
  ------------------
  |  Branch (2110:7): [True: 66, False: 621]
  ------------------
 2111|       |
 2112|    621|  if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
  ------------------
  |  Branch (2112:7): [True: 69, False: 552]
  ------------------
 2113|     69|    return 0;
 2114|    552|  s += rr->nlen + 4;
 2115|    552|  if (s > e) return 0;
  ------------------
  |  Branch (2115:7): [True: 66, False: 486]
  ------------------
 2116|    486|  rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
 2117|    486|  rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
 2118|    486|  if (is_question) return (size_t) (rr->nlen + 4);
  ------------------
  |  Branch (2118:7): [True: 96, False: 390]
  ------------------
 2119|       |
 2120|    390|  s += 6;
 2121|    390|  if (s > e) return 0;
  ------------------
  |  Branch (2121:7): [True: 26, False: 364]
  ------------------
 2122|    364|  rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
 2123|    364|  if (s + rr->alen > e) return 0;
  ------------------
  |  Branch (2123:7): [True: 61, False: 303]
  ------------------
 2124|    303|  return (size_t) (rr->nlen + rr->alen + 10);
 2125|    364|}
mg_dns_parse:
 2127|  11.1k|bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
 2128|  11.1k|  const struct mg_dns_header *h = (struct mg_dns_header *) buf;
 2129|  11.1k|  struct mg_dns_rr rr;
 2130|  11.1k|  size_t i, n, num_answers, ofs = sizeof(*h);
 2131|  11.1k|  bool is_response;
 2132|  11.1k|  memset(dm, 0, sizeof(*dm));
 2133|       |
 2134|  11.1k|  if (len < sizeof(*h)) return 0;                // Too small, headers dont fit
  ------------------
  |  Branch (2134:7): [True: 6.85k, False: 4.26k]
  ------------------
 2135|  4.26k|  if (mg_ntohs(h->num_questions) > 1) return 0;  // Sanity
  ------------------
  |  Branch (2135:7): [True: 3.86k, False: 400]
  ------------------
 2136|    400|  num_answers = mg_ntohs(h->num_answers);
 2137|    400|  if (num_answers > 10) {
  ------------------
  |  Branch (2137:7): [True: 314, False: 86]
  ------------------
 2138|    314|    MG_DEBUG(("Got %u answers, ignoring beyond 10th one", num_answers));
  ------------------
  |  | 1768|    314|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|    314|  do {                      \
  |  |  |  | 1757|    314|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 314]
  |  |  |  |  ------------------
  |  |  |  | 1758|    314|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 314]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2139|    314|    num_answers = 10;  // Sanity cap
 2140|    314|  }
 2141|    400|  dm->txnid = mg_ntohs(h->txnid);
 2142|    400|  is_response = mg_ntohs(h->flags) & 0x8000;
 2143|       |
 2144|    496|  for (i = 0; i < mg_ntohs(h->num_questions); i++) {
  ------------------
  |  Branch (2144:15): [True: 157, False: 339]
  ------------------
 2145|    157|    if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
  ------------------
  |  Branch (2145:9): [True: 61, False: 96]
  ------------------
 2146|       |    // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
 2147|     96|    mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
 2148|     96|    ofs += n;
 2149|     96|  }
 2150|       |
 2151|    339|  if (!is_response) {
  ------------------
  |  Branch (2151:7): [True: 68, False: 271]
  ------------------
 2152|       |    // For queries, there is no need to parse the answers. In this way,
 2153|       |    // we also ensure the domain name (dm->name) is parsed from
 2154|       |    // the question field.
 2155|     68|    return true;
 2156|     68|  }
 2157|       |
 2158|    572|  for (i = 0; i < num_answers; i++) {
  ------------------
  |  Branch (2158:15): [True: 550, False: 22]
  ------------------
 2159|    550|    if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
  ------------------
  |  Branch (2159:9): [True: 247, False: 303]
  ------------------
 2160|       |    // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
 2161|       |    // dm->name));
 2162|    303|    mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
 2163|    303|    ofs += n;
 2164|       |
 2165|    303|    if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && rr.aclass == 1) {
  ------------------
  |  | 3701|    353|#define MG_DNS_RTYPE_A 1     // IPv4 address (4 bytes)
  ------------------
  |  Branch (2165:9): [True: 50, False: 253]
  |  Branch (2165:25): [True: 18, False: 32]
  |  Branch (2165:55): [True: 1, False: 17]
  ------------------
 2166|      1|      dm->addr.is_ip6 = false;
 2167|      1|      memcpy(&dm->addr.addr.ip, &buf[ofs - 4], 4);
 2168|      1|      dm->resolved = true;
 2169|      1|      break;  // Return success
 2170|    302|    } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA &&
  ------------------
  |  | 3704|    365|#define MG_DNS_RTYPE_AAAA 28 // IPv6 address (16 bytes)
  ------------------
  |  Branch (2170:16): [True: 63, False: 239]
  |  Branch (2170:33): [True: 33, False: 30]
  ------------------
 2171|     33|               rr.aclass == 1) {
  ------------------
  |  Branch (2171:16): [True: 1, False: 32]
  ------------------
 2172|      1|      dm->addr.is_ip6 = true;
 2173|      1|      memcpy(&dm->addr.addr.ip, &buf[ofs - 16], 16);
 2174|      1|      dm->resolved = true;
 2175|      1|      break;  // Return success
 2176|      1|    }
 2177|    303|  }
 2178|     24|  return true;
 2179|    271|}
mg_resolve:
 2309|  5.56k|void mg_resolve(struct mg_connection *c, const char *url) {
 2310|  5.56k|  struct mg_str host = mg_url_host(url);
 2311|  5.56k|  c->rem.port = mg_htons(mg_url_port(url));
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 2312|  5.56k|  if (mg_aton(host, &c->rem)) {
  ------------------
  |  Branch (2312:7): [True: 5.56k, False: 0]
  ------------------
 2313|       |    // host is an IP address, do not fire name resolution
 2314|  5.56k|    mg_connect_resolved(c);
 2315|  5.56k|  } else if (host.len > 6 &&
  ------------------
  |  Branch (2315:14): [True: 0, False: 0]
  ------------------
 2316|      0|             strncmp(".local", &host.buf[host.len - 6], 6) == 0) {
  ------------------
  |  Branch (2316:14): [True: 0, False: 0]
  ------------------
 2317|       |    // this is a request for a .local name (mDNS)
 2318|      0|    sendmdnsreq(c, &host, 500, c->mgr->mdns, c->mgr->use_dns6);  // 500ms tmout
 2319|      0|  } else {
 2320|       |    // host is not an IP nor a .local, send DNS resolution request
 2321|      0|    struct mg_dns *dns = c->mgr->use_dns6 ? &c->mgr->dns6 : &c->mgr->dns4;
  ------------------
  |  Branch (2321:26): [True: 0, False: 0]
  ------------------
 2322|      0|    sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
 2323|      0|  }
 2324|  5.56k|}
mg_call:
 2845|   824k|void mg_call(struct mg_connection *c, int ev, void *ev_data) {
 2846|       |#if MG_ENABLE_PROFILE
 2847|       |  const char *names[] = {
 2848|       |      "EV_ERROR",    "EV_OPEN",      "EV_POLL",      "EV_RESOLVE",
 2849|       |      "EV_CONNECT",  "EV_ACCEPT",    "EV_TLS_HS",    "EV_READ",
 2850|       |      "EV_WRITE",    "EV_CLOSE",     "EV_HTTP_MSG",  "EV_HTTP_CHUNK",
 2851|       |      "EV_WS_OPEN",  "EV_WS_MSG",    "EV_WS_CTL",    "EV_MQTT_CMD",
 2852|       |      "EV_MQTT_MSG", "EV_MQTT_OPEN", "EV_SNTP_TIME", "EV_USER"};
 2853|       |  if (ev != MG_EV_POLL && ev < (int) (sizeof(names) / sizeof(names[0]))) {
 2854|       |    MG_PROF_ADD(c, names[ev]);
 2855|       |  }
 2856|       |#endif
 2857|       |  // Fire protocol handler first, user handler second. See #2559
 2858|   824k|  if (c->pfn != NULL) c->pfn(c, ev, ev_data);
  ------------------
  |  Branch (2858:7): [True: 824k, False: 0]
  ------------------
 2859|   824k|  if (c->fn != NULL) c->fn(c, ev, ev_data);
  ------------------
  |  Branch (2859:7): [True: 824k, False: 0]
  ------------------
 2860|   824k|}
mg_error:
 2862|    636|void mg_error(struct mg_connection *c, const char *fmt, ...) {
 2863|    636|  char buf[64];
 2864|    636|  va_list ap;
 2865|    636|  va_start(ap, fmt);
 2866|    636|  mg_vsnprintf(buf, sizeof(buf), fmt, &ap);
 2867|    636|  va_end(ap);
 2868|    636|  MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
  ------------------
  |  | 1766|    636|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|    636|  do {                      \
  |  |  |  | 1757|    636|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 636]
  |  |  |  |  ------------------
  |  |  |  | 1758|    636|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 636]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2869|    636|  c->is_closing = 1;             // Set is_closing before sending MG_EV_CALL
 2870|    636|  mg_call(c, MG_EV_ERROR, buf);  // Let user handler override it
 2871|    636|}
mg_vxprintf:
 3127|  2.63M|                   va_list *ap) {
 3128|  2.63M|  size_t i = 0, n = 0;
 3129|  38.9M|  while (fmt[i] != '\0') {
  ------------------
  |  Branch (3129:10): [True: 36.2M, False: 2.63M]
  ------------------
 3130|  36.2M|    if (fmt[i] == '%') {
  ------------------
  |  Branch (3130:9): [True: 1.96M, False: 34.3M]
  ------------------
 3131|  1.96M|      size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = ~0U /* prec */;
 3132|  1.96M|      char pad = ' ', minus = 0, c = fmt[++i];
 3133|  1.96M|      if (c == '#') x++, c = fmt[++i];
  ------------------
  |  Branch (3133:11): [True: 0, False: 1.96M]
  ------------------
 3134|  1.96M|      if (c == '-') minus++, c = fmt[++i];
  ------------------
  |  Branch (3134:11): [True: 397k, False: 1.56M]
  ------------------
 3135|  1.96M|      if (c == '0') pad = '0', c = fmt[++i];
  ------------------
  |  Branch (3135:11): [True: 0, False: 1.96M]
  ------------------
 3136|  2.75M|      while (is_digit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (3136:14): [True: 794k, False: 1.96M]
  ------------------
 3137|  1.96M|      if (c == '.') {
  ------------------
  |  Branch (3137:11): [True: 372k, False: 1.58M]
  ------------------
 3138|   372k|        c = fmt[++i];
 3139|   372k|        if (c == '*') {
  ------------------
  |  Branch (3139:13): [True: 372k, False: 0]
  ------------------
 3140|   372k|          pr = (size_t) va_arg(*ap, int);
 3141|   372k|          c = fmt[++i];
 3142|   372k|        } else {
 3143|      0|          pr = 0;
 3144|      0|          while (is_digit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (3144:18): [True: 0, False: 0]
  ------------------
 3145|      0|        }
 3146|   372k|      }
 3147|  1.96M|      while (c == 'h') c = fmt[++i];  // Treat h and hh as int
  ------------------
  |  Branch (3147:14): [True: 0, False: 1.96M]
  ------------------
 3148|  1.96M|      if (c == 'l') {
  ------------------
  |  Branch (3148:11): [True: 397k, False: 1.56M]
  ------------------
 3149|   397k|        is_long++, c = fmt[++i];
 3150|   397k|        if (c == 'l') is_long++, c = fmt[++i];
  ------------------
  |  Branch (3150:13): [True: 0, False: 397k]
  ------------------
 3151|   397k|      }
 3152|  1.96M|      if (c == 'z') is_long = 1, c = fmt[++i];
  ------------------
  |  Branch (3152:11): [True: 0, False: 1.96M]
  ------------------
 3153|  1.96M|      if (c == 'p') x = 1, is_long = 1;
  ------------------
  |  Branch (3153:11): [True: 0, False: 1.96M]
  ------------------
 3154|  1.96M|      if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p' ||
  ------------------
  |  Branch (3154:11): [True: 397k, False: 1.56M]
  |  Branch (3154:23): [True: 397k, False: 1.16M]
  |  Branch (3154:35): [True: 0, False: 1.16M]
  |  Branch (3154:47): [True: 0, False: 1.16M]
  |  Branch (3154:59): [True: 0, False: 1.16M]
  ------------------
 3155|  1.16M|          c == 'g' || c == 'f') {
  ------------------
  |  Branch (3155:11): [True: 0, False: 1.16M]
  |  Branch (3155:23): [True: 0, False: 1.16M]
  ------------------
 3156|   794k|        bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
  ------------------
  |  Branch (3156:35): [True: 0, False: 794k]
  |  Branch (3156:47): [True: 0, False: 794k]
  |  Branch (3156:59): [True: 0, False: 794k]
  ------------------
 3157|   794k|        char tmp[40];
 3158|   794k|        size_t xl = x ? 2 : 0;
  ------------------
  |  Branch (3158:21): [True: 0, False: 794k]
  ------------------
 3159|   794k|        if (c == 'g' || c == 'f') {
  ------------------
  |  Branch (3159:13): [True: 0, False: 794k]
  |  Branch (3159:25): [True: 0, False: 794k]
  ------------------
 3160|      0|          double v = va_arg(*ap, double);
 3161|      0|          if (pr == ~0U) pr = 6;
  ------------------
  |  Branch (3161:15): [True: 0, False: 0]
  ------------------
 3162|      0|          k = mg_dtoa(tmp, sizeof(tmp), v, (int) pr, c == 'g');
 3163|   794k|        } else if (is_long == 2) {
  ------------------
  |  Branch (3163:20): [True: 0, False: 794k]
  ------------------
 3164|      0|          int64_t v = va_arg(*ap, int64_t);
 3165|      0|          k = mg_lld(tmp, v, s, h);
 3166|   794k|        } else if (is_long == 1) {
  ------------------
  |  Branch (3166:20): [True: 397k, False: 397k]
  ------------------
 3167|   397k|          long v = va_arg(*ap, long);
 3168|   397k|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned long) v, s, h);
  ------------------
  |  Branch (3168:27): [True: 0, False: 397k]
  ------------------
 3169|   397k|        } else {
 3170|   397k|          int v = va_arg(*ap, int);
 3171|   397k|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
  ------------------
  |  Branch (3171:27): [True: 397k, False: 0]
  ------------------
 3172|   397k|        }
 3173|   794k|        for (j = 0; j < xl && w > 0; j++) w--;
  ------------------
  |  Branch (3173:21): [True: 0, False: 794k]
  |  Branch (3173:31): [True: 0, False: 0]
  ------------------
 3174|   794k|        for (j = 0; pad == ' ' && !minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (3174:21): [True: 794k, False: 0]
  |  Branch (3174:35): [True: 397k, False: 397k]
  |  Branch (3174:45): [True: 0, False: 397k]
  |  Branch (3174:54): [True: 0, False: 0]
  ------------------
 3175|      0|          n += scpy(out, param, &pad, 1);
 3176|   794k|        n += scpy(out, param, (char *) "0x", xl);
 3177|   794k|        for (j = 0; pad == '0' && k < w && j + k < w; j++)
  ------------------
  |  Branch (3177:21): [True: 0, False: 794k]
  |  Branch (3177:35): [True: 0, False: 0]
  |  Branch (3177:44): [True: 0, False: 0]
  ------------------
 3178|      0|          n += scpy(out, param, &pad, 1);
 3179|   794k|        n += scpy(out, param, tmp, k);
 3180|  3.97M|        for (j = 0; pad == ' ' && minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (3180:21): [True: 3.97M, False: 0]
  |  Branch (3180:35): [True: 3.57M, False: 397k]
  |  Branch (3180:44): [True: 3.57M, False: 0]
  |  Branch (3180:53): [True: 3.17M, False: 397k]
  ------------------
 3181|  3.17M|          n += scpy(out, param, &pad, 1);
 3182|  1.16M|      } else if (c == 'm' || c == 'M') {
  ------------------
  |  Branch (3182:18): [True: 0, False: 1.16M]
  |  Branch (3182:30): [True: 0, False: 1.16M]
  ------------------
 3183|      0|        mg_pm_t f = va_arg(*ap, mg_pm_t);
 3184|      0|        if (c == 'm') out('"', param);
  ------------------
  |  Branch (3184:13): [True: 0, False: 0]
  ------------------
 3185|      0|        n += f(out, param, ap);
 3186|      0|        if (c == 'm') n += 2, out('"', param);
  ------------------
  |  Branch (3186:13): [True: 0, False: 0]
  ------------------
 3187|  1.16M|      } else if (c == 'c') {
  ------------------
  |  Branch (3187:18): [True: 0, False: 1.16M]
  ------------------
 3188|      0|        int ch = va_arg(*ap, int);
 3189|      0|        out((char) ch, param);
 3190|      0|        n++;
 3191|  1.16M|      } else if (c == 's') {
  ------------------
  |  Branch (3191:18): [True: 1.16M, False: 0]
  ------------------
 3192|  1.16M|        char *p = va_arg(*ap, char *);
 3193|  1.16M|        if (p != NULL && pr != ~0U) {
  ------------------
  |  Branch (3193:13): [True: 1.16M, False: 0]
  |  Branch (3193:26): [True: 372k, False: 794k]
  ------------------
 3194|   765k|          for (j = 0; j < pr && p[j] != '\0'; j++) ;  // portable strnlen()
  ------------------
  |  Branch (3194:23): [True: 393k, False: 372k]
  |  Branch (3194:33): [True: 393k, False: 0]
  ------------------
 3195|   372k|          pr = j;
 3196|   794k|        } else {
 3197|   794k|          pr = p == NULL ? 0 : strlen(p);
  ------------------
  |  Branch (3197:16): [True: 0, False: 794k]
  ------------------
 3198|   794k|        }
 3199|  1.16M|        for (j = 0; !minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (3199:21): [True: 1.16M, False: 0]
  |  Branch (3199:31): [True: 0, False: 1.16M]
  |  Branch (3199:41): [True: 0, False: 0]
  ------------------
 3200|      0|          n += scpy(out, param, &pad, 1);
 3201|  1.16M|        n += scpy(out, param, p, pr);
 3202|  1.16M|        for (j = 0; minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (3202:21): [True: 0, False: 1.16M]
  |  Branch (3202:30): [True: 0, False: 0]
  |  Branch (3202:40): [True: 0, False: 0]
  ------------------
 3203|      0|          n += scpy(out, param, &pad, 1);
 3204|  1.16M|      } else if (c == '%') {
  ------------------
  |  Branch (3204:18): [True: 0, False: 0]
  ------------------
 3205|      0|        out('%', param);
 3206|      0|        n++;
 3207|      0|      } else {
 3208|      0|        out('%', param);
 3209|      0|        out(c, param);
 3210|      0|        n += 2;
 3211|      0|      }
 3212|  1.96M|      i++;
 3213|  34.3M|    } else {
 3214|  34.3M|      out(fmt[i], param), n++, i++;
 3215|  34.3M|    }
 3216|  36.2M|  }
 3217|  2.63M|  return n;
 3218|  2.63M|}
mg_fs_open:
 3229|  12.1k|struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
 3230|  12.1k|  struct mg_fd *fd = (struct mg_fd *) mg_calloc(1, sizeof(*fd));
 3231|  12.1k|  if (fd != NULL) {
  ------------------
  |  Branch (3231:7): [True: 12.1k, False: 0]
  ------------------
 3232|  12.1k|    fd->fd = fs->op(path, flags);
 3233|  12.1k|    fd->fs = fs;
 3234|  12.1k|    if (fd->fd == NULL) {
  ------------------
  |  Branch (3234:9): [True: 12.1k, False: 0]
  ------------------
 3235|  12.1k|      mg_free(fd);
 3236|       |      fd = NULL;
 3237|  12.1k|    }
 3238|  12.1k|  }
 3239|  12.1k|  return fd;
 3240|  12.1k|}
mg_fs_close:
 3242|  12.1k|void mg_fs_close(struct mg_fd *fd) {
 3243|  12.1k|  if (fd != NULL) {
  ------------------
  |  Branch (3243:7): [True: 0, False: 12.1k]
  ------------------
 3244|      0|    fd->fs->cl(fd->fd);
 3245|      0|    mg_free(fd);
 3246|      0|  }
 3247|  12.1k|}
_Z12mg_to_size_t6mg_strPm:
 4013|  2.09k|bool mg_to_size_t(struct mg_str str, size_t *val) {
 4014|  2.09k|  size_t i = 0, max = (size_t) -1, max2 = max / 10, result = 0, ndigits = 0;
 4015|  2.09k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (4015:10): [True: 2.07k, False: 18]
  |  Branch (4015:26): [True: 0, False: 2.07k]
  |  Branch (4015:47): [True: 0, False: 2.07k]
  ------------------
 4016|  2.09k|  if (i < str.len && str.buf[i] == '-') return false;
  ------------------
  |  Branch (4016:7): [True: 2.07k, False: 18]
  |  Branch (4016:22): [True: 11, False: 2.06k]
  ------------------
 4017|  9.76M|  while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (4017:10): [True: 9.76M, False: 1.91k]
  |  Branch (4017:25): [True: 9.76M, False: 105]
  |  Branch (4017:46): [True: 9.76M, False: 39]
  ------------------
 4018|  9.76M|    size_t digit = (size_t) (str.buf[i] - '0');
 4019|  9.76M|    if (result > max2) return false;  // Overflow
  ------------------
  |  Branch (4019:9): [True: 16, False: 9.76M]
  ------------------
 4020|  9.76M|    result *= 10;
 4021|  9.76M|    if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (4021:9): [True: 5, False: 9.76M]
  ------------------
 4022|  9.76M|    result += digit;
 4023|  9.76M|    i++, ndigits++;
 4024|  9.76M|  }
 4025|   171k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (4025:10): [True: 169k, False: 1.91k]
  |  Branch (4025:26): [True: 169k, False: 338]
  |  Branch (4025:47): [True: 194, False: 144]
  ------------------
 4026|  2.05k|  if (ndigits == 0) return false;  // #2322: Content-Length = 1 * DIGIT
  ------------------
  |  Branch (4026:7): [True: 38, False: 2.02k]
  ------------------
 4027|  2.02k|  if (i != str.len) return false;  // Ditto
  ------------------
  |  Branch (4027:7): [True: 124, False: 1.89k]
  ------------------
 4028|  1.89k|  *val = (size_t) result;
 4029|  1.89k|  return true;
 4030|  2.02k|}
mg_http_var:
 4113|  5.56k|struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) {
 4114|  5.56k|  struct mg_str entry, k, v, result = mg_str_n(NULL, 0);
 4115|  98.0k|  while (mg_span(buf, &entry, &buf, '&')) {
  ------------------
  |  Branch (4115:10): [True: 92.5k, False: 5.53k]
  ------------------
 4116|  92.5k|    if (mg_span(entry, &k, &v, '=') && name.len == k.len &&
  ------------------
  |  Branch (4116:9): [True: 88.9k, False: 3.57k]
  |  Branch (4116:40): [True: 26.1k, False: 62.8k]
  ------------------
 4117|  26.1k|        mg_ncasecmp(name.buf, k.buf, k.len) == 0) {
  ------------------
  |  Branch (4117:9): [True: 30, False: 26.1k]
  ------------------
 4118|     30|      result = v;
 4119|     30|      break;
 4120|     30|    }
 4121|  92.5k|  }
 4122|  5.56k|  return result;
 4123|  5.56k|}
mg_http_get_var:
 4126|  11.1k|                    size_t dst_len) {
 4127|  11.1k|  int len;
 4128|  11.1k|  if (dst != NULL && dst_len > 0) {
  ------------------
  |  Branch (4128:7): [True: 5.56k, False: 5.56k]
  |  Branch (4128:22): [True: 5.56k, False: 0]
  ------------------
 4129|  5.56k|    dst[0] = '\0';  // If destination buffer is valid, always nul-terminate it
 4130|  5.56k|  }
 4131|  11.1k|  if (dst == NULL || dst_len == 0) {
  ------------------
  |  Branch (4131:7): [True: 5.56k, False: 5.56k]
  |  Branch (4131:22): [True: 0, False: 5.56k]
  ------------------
 4132|  5.56k|    len = -2;  // Bad destination
 4133|  5.56k|  } else if (buf->buf == NULL || name == NULL || buf->len == 0) {
  ------------------
  |  Branch (4133:14): [True: 0, False: 5.56k]
  |  Branch (4133:34): [True: 0, False: 5.56k]
  |  Branch (4133:50): [True: 0, False: 5.56k]
  ------------------
 4134|      0|    len = -1;  // Bad source
 4135|  5.56k|  } else {
 4136|  5.56k|    struct mg_str v = mg_http_var(*buf, mg_str(name));
  ------------------
  |  | 1467|  5.56k|#define mg_str(s) mg_str_s(s)
  ------------------
 4137|  5.56k|    if (v.buf == NULL) {
  ------------------
  |  Branch (4137:9): [True: 5.53k, False: 30]
  ------------------
 4138|  5.53k|      len = -4;  // Name does not exist
 4139|  5.53k|    } else {
 4140|     30|      len = mg_url_decode(v.buf, v.len, dst, dst_len, 1);
 4141|     30|      if (len < 0) len = -3;  // Failed to decode
  ------------------
  |  Branch (4141:11): [True: 13, False: 17]
  ------------------
 4142|     30|    }
 4143|  5.56k|  }
 4144|  11.1k|  return len;
 4145|  11.1k|}
mg_url_decode:
 4153|   388k|                  int is_form_url_encoded) {
 4154|   388k|  size_t i, j;
 4155|  7.72M|  for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
  ------------------
  |  Branch (4155:19): [True: 7.35M, False: 376k]
  |  Branch (4155:34): [True: 7.34M, False: 7.02k]
  ------------------
 4156|  7.34M|    if (src[i] == '%') {
  ------------------
  |  Branch (4156:9): [True: 105k, False: 7.23M]
  ------------------
 4157|       |      // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
 4158|   105k|      if (i + 2 < src_len && isx(src[i + 1]) && isx(src[i + 2])) {
  ------------------
  |  Branch (4158:11): [True: 104k, False: 171]
  |  Branch (4158:30): [True: 101k, False: 2.99k]
  |  Branch (4158:49): [True: 99.2k, False: 2.58k]
  ------------------
 4159|  99.2k|        mg_str_to_num(mg_str_n(src + i + 1, 2), 16, &dst[j], sizeof(uint8_t));
 4160|  99.2k|        i += 2;
 4161|  99.2k|      } else {
 4162|  5.74k|        dst[0] = '\0';
 4163|  5.74k|        return -1;
 4164|  5.74k|      }
 4165|  7.23M|    } else if (is_form_url_encoded && src[i] == '+') {
  ------------------
  |  Branch (4165:16): [True: 456k, False: 6.78M]
  |  Branch (4165:39): [True: 2.33k, False: 454k]
  ------------------
 4166|  2.33k|      dst[j] = ' ';
 4167|  7.23M|    } else {
 4168|  7.23M|      dst[j] = src[i];
 4169|  7.23M|    }
 4170|  7.34M|  }
 4171|   383k|  if (j < dst_len) dst[j] = '\0';  // Null-terminate the destination
  ------------------
  |  Branch (4171:7): [True: 383k, False: 0]
  ------------------
 4172|   383k|  return i >= src_len && j < dst_len ? (int) j : -1;
  ------------------
  |  Branch (4172:10): [True: 376k, False: 7.02k]
  |  Branch (4172:26): [True: 376k, False: 0]
  ------------------
 4173|   388k|}
mg_http_get_request_len:
 4179|   416k|int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
 4180|   416k|  size_t i;
 4181|   165M|  for (i = 0; i < buf_len; i++) {
  ------------------
  |  Branch (4181:15): [True: 165M, False: 9.55k]
  ------------------
 4182|   165M|    if (!isok(buf[i])) return -1;
  ------------------
  |  Branch (4182:9): [True: 3.62k, False: 165M]
  ------------------
 4183|   165M|    if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
  ------------------
  |  Branch (4183:10): [True: 165M, False: 409k]
  |  Branch (4183:19): [True: 972k, False: 164M]
  |  Branch (4183:37): [True: 398k, False: 573k]
  ------------------
 4184|   165M|        (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
  ------------------
  |  Branch (4184:10): [True: 163M, False: 1.63M]
  |  Branch (4184:19): [True: 573k, False: 163M]
  |  Branch (4184:37): [True: 28.6k, False: 544k]
  |  Branch (4184:59): [True: 4.60k, False: 24.0k]
  ------------------
 4185|   402k|      return (int) i + 1;
 4186|   165M|  }
 4187|  9.55k|  return 0;
 4188|   416k|}
mg_http_get_header:
 4189|  1.19M|struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
 4190|  1.19M|  size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
 4191|  1.36M|  for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
  ------------------
  |  Branch (4191:15): [True: 1.36M, False: 1.90k]
  |  Branch (4191:26): [True: 196k, False: 1.16M]
  ------------------
 4192|   196k|    struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
 4193|   196k|    if (n == k->len && mg_ncasecmp(k->buf, name, n) == 0) return v;
  ------------------
  |  Branch (4193:9): [True: 26.3k, False: 169k]
  |  Branch (4193:24): [True: 22.5k, False: 3.73k]
  ------------------
 4194|   196k|  }
 4195|  1.17M|  return NULL;
 4196|  1.19M|}
mg_http_parse:
 4261|   416k|int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
 4262|   416k|  int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
 4263|   416k|  const char *end = s == NULL ? NULL : s + req_len, *qs;  // Cannot add to NULL
  ------------------
  |  Branch (4263:21): [True: 5.56k, False: 410k]
  ------------------
 4264|   416k|  const struct mg_str *cl;
 4265|   416k|  size_t n;
 4266|   416k|  bool version_prefix_valid;
 4267|       |
 4268|   416k|  memset(hm, 0, sizeof(*hm));
 4269|   416k|  if (req_len <= 0) return req_len;
  ------------------
  |  Branch (4269:7): [True: 13.1k, False: 402k]
  ------------------
 4270|       |
 4271|   402k|  hm->message.buf = hm->head.buf = (char *) s;
 4272|   402k|  hm->body.buf = (char *) end;
 4273|   402k|  hm->head.len = (size_t) req_len;
 4274|   402k|  hm->message.len = hm->body.len = (size_t) -1;  // Set body length to infinite
 4275|       |
 4276|       |  // Parse request line
 4277|   402k|  hm->method.buf = (char *) s;
 4278|  12.6M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->method.len += n;
  ------------------
  |  Branch (4278:10): [True: 12.6M, False: 0]
  |  Branch (4278:21): [True: 12.2M, False: 402k]
  ------------------
 4279|   809k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (4279:10): [True: 809k, False: 0]
  |  Branch (4279:21): [True: 406k, False: 402k]
  ------------------
 4280|   402k|  hm->uri.buf = (char *) s;
 4281|  23.8M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
  ------------------
  |  Branch (4281:10): [True: 23.8M, False: 0]
  |  Branch (4281:21): [True: 23.4M, False: 402k]
  ------------------
 4282|   788k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (4282:10): [True: 788k, False: 0]
  |  Branch (4282:21): [True: 385k, False: 402k]
  ------------------
 4283|   402k|  is_response =
 4284|   402k|      hm->method.len > 5 && (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (4284:7): [True: 355k, False: 47.3k]
  |  Branch (4284:29): [True: 34.9k, False: 320k]
  ------------------
 4285|   402k|  if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
  ------------------
  |  Branch (4285:7): [True: 284, False: 402k]
  ------------------
 4286|       |  // If we're given a version, check that it is HTTP/x.x
 4287|   402k|  version_prefix_valid =
 4288|   402k|      hm->proto.len > 5 && (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (4288:7): [True: 388k, False: 14.3k]
  |  Branch (4288:28): [True: 368k, False: 19.8k]
  ------------------
 4289|   402k|  if (!is_response && !version_prefix_valid)
  ------------------
  |  Branch (4289:7): [True: 367k, False: 34.9k]
  |  Branch (4289:23): [True: 668, False: 366k]
  ------------------
 4290|    668|    return -1;  // no version detected in request
 4291|   401k|  if (!is_response && hm->proto.len > 0 &&
  ------------------
  |  Branch (4291:7): [True: 366k, False: 34.9k]
  |  Branch (4291:23): [True: 366k, False: 0]
  ------------------
 4292|   366k|      (!version_prefix_valid || hm->proto.len != 8 ||
  ------------------
  |  Branch (4292:8): [True: 0, False: 366k]
  |  Branch (4292:33): [True: 51, False: 366k]
  ------------------
 4293|   366k|       (hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
  ------------------
  |  Branch (4293:9): [True: 5, False: 366k]
  |  Branch (4293:35): [True: 9, False: 366k]
  ------------------
 4294|   366k|       (hm->proto.buf[6] != '.') ||
  ------------------
  |  Branch (4294:8): [True: 4, False: 366k]
  ------------------
 4295|   366k|       (hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
  ------------------
  |  Branch (4295:9): [True: 9, False: 366k]
  |  Branch (4295:35): [True: 5, False: 366k]
  ------------------
 4296|     83|    return -1;
 4297|     83|  }
 4298|       |
 4299|       |  // If URI contains '?' character, setup query string
 4300|   401k|  if ((qs = (const char *) memchr(hm->uri.buf, '?', hm->uri.len)) != NULL) {
  ------------------
  |  Branch (4300:7): [True: 1.24k, False: 400k]
  ------------------
 4301|  1.24k|    hm->query.buf = (char *) qs + 1;
 4302|  1.24k|    hm->query.len = (size_t) (&hm->uri.buf[hm->uri.len] - (qs + 1));
 4303|  1.24k|    hm->uri.len = (size_t) (qs - hm->uri.buf);
 4304|  1.24k|  }
 4305|       |
 4306|       |  // Sanity check. Allow protocol/reason to be empty
 4307|       |  // Do this check after hm->method.len and hm->uri.len are finalised
 4308|   401k|  if (hm->method.len == 0 || hm->uri.len == 0) return -1;
  ------------------
  |  Branch (4308:7): [True: 5, False: 401k]
  |  Branch (4308:30): [True: 19, False: 401k]
  ------------------
 4309|       |
 4310|   401k|  if (!mg_http_parse_headers(s, end, hm->headers,
  ------------------
  |  Branch (4310:7): [True: 402, False: 401k]
  ------------------
 4311|   401k|                             sizeof(hm->headers) / sizeof(hm->headers[0])))
 4312|    402|    return -1;  // error when parsing
 4313|   401k|  cl = mg_http_get_header(hm, "Content-Length");
 4314|   401k|  if (cl != NULL && mg_http_get_header(hm, "Transfer-Encoding") != NULL)
  ------------------
  |  Branch (4314:7): [True: 2.09k, False: 399k]
  |  Branch (4314:21): [True: 4, False: 2.09k]
  ------------------
 4315|      4|    return -1; // cannot contain both CL and TE
 4316|   401k|  if (cl != NULL) {
  ------------------
  |  Branch (4316:7): [True: 2.09k, False: 399k]
  ------------------
 4317|  2.09k|    if (mg_to_size_t(*cl, &hm->body.len) == false) return -1;
  ------------------
  |  Branch (4317:9): [True: 194, False: 1.89k]
  ------------------
 4318|  1.89k|    hm->message.len = (size_t) req_len + hm->body.len;
 4319|  1.89k|  }
 4320|       |
 4321|       |  // mg_http_parse() is used to parse both HTTP requests and HTTP
 4322|       |  // responses. If HTTP response does not have Content-Length set, then
 4323|       |  // body is read until socket is closed, i.e. body.len is infinite (~0).
 4324|       |  //
 4325|       |  // For HTTP requests though, if Content-Length is not specified
 4326|       |  // set body length to 0.
 4327|   401k|  if (hm->body.len == (size_t) ~0 && !is_response) {
  ------------------
  |  Branch (4327:7): [True: 399k, False: 1.89k]
  |  Branch (4327:38): [True: 366k, False: 32.4k]
  ------------------
 4328|   366k|    hm->body.len = 0;
 4329|   366k|    hm->message.len = (size_t) req_len;
 4330|   366k|  }
 4331|       |
 4332|       |  // The 204 (No content) responses also have 0 body length
 4333|   401k|  if (hm->body.len == (size_t) ~0 && is_response &&
  ------------------
  |  Branch (4333:7): [True: 32.4k, False: 368k]
  |  Branch (4333:38): [True: 32.4k, False: 0]
  ------------------
 4334|  32.4k|      mg_strcasecmp(hm->uri, mg_str("204")) == 0) {
  ------------------
  |  | 1467|  32.4k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4334:7): [True: 11.2k, False: 21.2k]
  ------------------
 4335|  11.2k|    hm->body.len = 0;
 4336|  11.2k|    hm->message.len = (size_t) req_len;
 4337|  11.2k|  }
 4338|   401k|  if (hm->message.len < (size_t) req_len) return -1;  // Overflow protection
  ------------------
  |  Branch (4338:7): [True: 9, False: 401k]
  ------------------
 4339|       |
 4340|   401k|  return req_len;
 4341|   401k|}
mg_http_reply:
 4441|   397k|                   const char *fmt, ...) {
 4442|   397k|  va_list ap;
 4443|   397k|  size_t len;
 4444|   397k|  mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length:            \r\n\r\n", code,
 4445|   397k|            mg_http_status_code_str(code), headers == NULL ? "" : headers);
  ------------------
  |  Branch (4445:44): [True: 0, False: 397k]
  ------------------
 4446|   397k|  len = c->send.len;
 4447|   397k|  va_start(ap, fmt);
 4448|   397k|  mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
 4449|   397k|  va_end(ap);
 4450|   397k|  if (c->send.len > 16) {
  ------------------
  |  Branch (4450:7): [True: 397k, False: 0]
  ------------------
 4451|   397k|    size_t n = mg_snprintf((char *) &c->send.buf[len - 15], 11, "%-10lu",
 4452|   397k|                           (unsigned long) (c->send.len - len));
 4453|   397k|    c->send.buf[len - 15 + n] = ' ';  // Change ending 0 to space
 4454|   397k|  }
 4455|       |  c->pfn_data = NULL;  // Response done
 4456|   397k|}
mg_http_serve_file:
 4573|  12.1k|                        const struct mg_http_serve_opts *opts) {
 4574|  12.1k|  char etag[64], tmp[MG_PATH_MAX];
 4575|  12.1k|  struct mg_fs *fs = opts && opts->fs ? opts->fs : &mg_fs_posix;
  ------------------
  |  Branch (4575:22): [True: 12.1k, False: 0]
  |  Branch (4575:30): [True: 0, False: 12.1k]
  ------------------
 4576|  12.1k|  struct mg_fd *fd = NULL;
 4577|  12.1k|  size_t size = 0;
 4578|  12.1k|  time_t mtime = 0;
 4579|  12.1k|  const char *mime_types = opts && opts->mime_types ? opts->mime_types : NULL;
  ------------------
  |  Branch (4579:28): [True: 12.1k, False: 0]
  |  Branch (4579:36): [True: 0, False: 12.1k]
  ------------------
 4580|  12.1k|  const char *hdrs = opts && opts->extra_headers ? opts->extra_headers : "";
  ------------------
  |  Branch (4580:22): [True: 12.1k, False: 0]
  |  Branch (4580:30): [True: 0, False: 12.1k]
  ------------------
 4581|  12.1k|  struct mg_str *inm = NULL;
 4582|  12.1k|  struct mg_str mime = guess_content_type(mg_str(path), mime_types);
  ------------------
  |  | 1467|  12.1k|#define mg_str(s) mg_str_s(s)
  ------------------
 4583|  12.1k|  bool gzip = false;
 4584|       |
 4585|  12.1k|  if (path != NULL) {
  ------------------
  |  Branch (4585:7): [True: 12.1k, False: 0]
  ------------------
 4586|       |    // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
 4587|  12.1k|    struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
 4588|  12.1k|    if (ae != NULL) {
  ------------------
  |  Branch (4588:9): [True: 96, False: 12.0k]
  ------------------
 4589|     96|      if (mg_match(*ae, mg_str("*gzip*"), NULL)) {
  ------------------
  |  | 1467|     96|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4589:11): [True: 6, False: 90]
  ------------------
 4590|      6|        mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
 4591|      6|        fd = mg_fs_open(fs, tmp, MG_FS_READ);
 4592|      6|        if (fd != NULL) gzip = true, path = tmp;
  ------------------
  |  Branch (4592:13): [True: 0, False: 6]
  ------------------
 4593|      6|      }
 4594|     96|    }
 4595|       |    // No luck opening .gz? Open what we've told to open
 4596|  12.1k|    if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
  ------------------
  |  Branch (4596:9): [True: 12.1k, False: 0]
  ------------------
 4597|  12.1k|  }
 4598|       |
 4599|       |  // Failed to open, and page404 is configured? Open it, then
 4600|  12.1k|  if (fd == NULL && opts && opts->page404) {
  ------------------
  |  Branch (4600:7): [True: 12.1k, False: 0]
  |  Branch (4600:21): [True: 12.1k, False: 0]
  |  Branch (4600:29): [True: 0, False: 12.1k]
  ------------------
 4601|      0|    fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
 4602|      0|    path = opts->page404;
 4603|      0|    mime = guess_content_type(mg_str(path), mime_types);
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
 4604|      0|  }
 4605|       |
 4606|  12.1k|  if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
  ------------------
  |  Branch (4606:7): [True: 12.1k, False: 0]
  |  Branch (4606:21): [True: 0, False: 0]
  ------------------
 4607|  12.1k|    mg_http_reply(c, 404, hdrs, "Not found\n");
 4608|  12.1k|    mg_fs_close(fd);
 4609|       |    // NOTE: mg_http_etag() call should go first!
 4610|  12.1k|  } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
  ------------------
  |  Branch (4610:14): [True: 0, False: 0]
  ------------------
 4611|      0|             (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
  ------------------
  |  Branch (4611:14): [True: 0, False: 0]
  ------------------
 4612|      0|             mg_strcasecmp(*inm, mg_str(etag)) == 0) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4612:14): [True: 0, False: 0]
  ------------------
 4613|      0|    mg_fs_close(fd);
 4614|      0|    mg_http_reply(c, 304, hdrs, "");
 4615|      0|  } else {
 4616|      0|    int n, status = 200;
 4617|      0|    char range[100];
 4618|      0|    size_t r1 = 0, r2 = 0, cl = size;
 4619|       |
 4620|       |    // Handle Range header
 4621|      0|    struct mg_str *rh = mg_http_get_header(hm, "Range");
 4622|      0|    range[0] = '\0';
 4623|      0|    if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
  ------------------
  |  Branch (4623:9): [True: 0, False: 0]
  |  Branch (4623:23): [True: 0, False: 0]
  ------------------
 4624|       |      // If range is specified like "400-", set second limit to content len
 4625|      0|      if (n == 1) r2 = cl - 1;
  ------------------
  |  Branch (4625:11): [True: 0, False: 0]
  ------------------
 4626|      0|      if (r1 > r2 || r2 >= cl) {
  ------------------
  |  Branch (4626:11): [True: 0, False: 0]
  |  Branch (4626:22): [True: 0, False: 0]
  ------------------
 4627|      0|        status = 416;
 4628|      0|        cl = 0;
 4629|      0|        mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
 4630|      0|                    (int64_t) size);
 4631|      0|      } else {
 4632|      0|        status = 206;
 4633|      0|        cl = r2 - r1 + 1;
 4634|      0|        mg_snprintf(range, sizeof(range),
 4635|      0|                    "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
 4636|      0|                    (uint64_t) (r1 + cl - 1), (uint64_t) size);
 4637|      0|        fs->sk(fd->fd, r1);
 4638|      0|      }
 4639|      0|    }
 4640|      0|    mg_printf(c,
 4641|      0|              "HTTP/1.1 %d %s\r\n"
 4642|      0|              "Content-Type: %.*s\r\n"
 4643|      0|              "Etag: %s\r\n"
 4644|      0|              "Content-Length: %llu\r\n"
 4645|      0|              "%s%s%s\r\n",
 4646|      0|              status, mg_http_status_code_str(status), (int) mime.len, mime.buf,
 4647|      0|              etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
  ------------------
  |  Branch (4647:36): [True: 0, False: 0]
  ------------------
 4648|      0|              range, hdrs);
 4649|      0|    if (mg_strcasecmp(hm->method, mg_str("HEAD")) == 0 || c->is_closing) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4649:9): [True: 0, False: 0]
  |  Branch (4649:59): [True: 0, False: 0]
  ------------------
 4650|      0|      c->pfn_data = NULL;  // Response done
 4651|      0|      mg_fs_close(fd);
 4652|      0|    } else {  // start serving static content only if not closing, see #3354
 4653|       |      // Track to-be-sent content length at the end of c->data, aligned
 4654|      0|      size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
 4655|      0|                                        sizeof(size_t) * sizeof(size_t)];
 4656|      0|      c->pfn = static_cb;
 4657|      0|      c->pfn_data = fd;
 4658|      0|      *clp = cl;
 4659|      0|    }
 4660|      0|  }
 4661|  12.1k|}
mg_http_serve_dir:
 4798|   397k|                       const struct mg_http_serve_opts *opts) {
 4799|   397k|  char path[MG_PATH_MAX];
 4800|   397k|  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
  ------------------
  |  Branch (4800:22): [True: 397k, False: 0]
  ------------------
 4801|   397k|  const char *sp = opts->ssi_pattern;
 4802|   397k|  int flags = uri_to_file_status(c, hm, fs, opts->root_dir, path, sizeof(path));
 4803|   397k|  if (flags < 0) {
  ------------------
  |  Branch (4803:7): [True: 31.2k, False: 366k]
  ------------------
 4804|       |    // Do nothing: the response has already been sent by uri_to_file_status()
 4805|   366k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (4805:14): [True: 354k, False: 12.1k]
  ------------------
 4806|   354k|    if (opts->enable_dir_listing) {
  ------------------
  |  Branch (4806:9): [True: 0, False: 354k]
  ------------------
 4807|      0|      listdir(c, hm, opts, path);
 4808|   354k|    } else {
 4809|   354k|      mg_http_reply(c, 403, "", "Forbidden\n");
 4810|   354k|    }
 4811|   354k|  } else if (opts->enable_delete &&
  ------------------
  |  Branch (4811:14): [True: 0, False: 12.1k]
  ------------------
 4812|      0|            mg_strcasecmp(hm->method, mg_str("DELETE")) == 0) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4812:13): [True: 0, False: 0]
  ------------------
 4813|      0|    mg_http_reply(c, flags && fs->rm(path) ? 200 : 404, "", "");
  ------------------
  |  Branch (4813:22): [True: 0, False: 0]
  |  Branch (4813:31): [True: 0, False: 0]
  ------------------
 4814|  12.1k|  } else if (opts->enable_upload &&
  ------------------
  |  Branch (4814:14): [True: 0, False: 12.1k]
  ------------------
 4815|      0|            (mg_strcasecmp(hm->method, mg_str("POST")) == 0 ||
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4815:14): [True: 0, False: 0]
  ------------------
 4816|      0|             mg_strcasecmp(hm->method, mg_str("PUT")) == 0)) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4816:14): [True: 0, False: 0]
  ------------------
 4817|       |    // Small or already fully buffered body. mg_http_serve_upload() handles
 4818|       |    // the same thing without buffering, for big uploads, from MG_EV_HTTP_HDRS
 4819|      0|    void *fd;
 4820|      0|    bool ok = false;
 4821|      0|    fs->rm(path);  // MG_FS_WRITE appends, not truncates: drop any old file
 4822|      0|    if ((fd = fs->op(path, MG_FS_WRITE)) != NULL) {
  ------------------
  |  Branch (4822:9): [True: 0, False: 0]
  ------------------
 4823|      0|      ok = fs->wr(fd, hm->body.buf, hm->body.len) == hm->body.len;
 4824|      0|      fs->cl(fd);
 4825|      0|    }
 4826|      0|    mg_http_reply(c, ok ? 200 : 500, "", "");
  ------------------
  |  Branch (4826:22): [True: 0, False: 0]
  ------------------
 4827|  12.1k|  } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
                } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4827:14): [True: 0, False: 12.1k]
  |  Branch (4827:23): [True: 0, False: 0]
  |  Branch (4827:37): [True: 0, False: 0]
  ------------------
 4828|      0|    mg_http_serve_ssi(c, opts->root_dir, path);
 4829|  12.1k|  } else {
 4830|  12.1k|    mg_http_serve_file(c, hm, path, opts);
 4831|  12.1k|  }
 4832|   397k|}
mg_http_status:
 4998|  12.4k|int mg_http_status(const struct mg_http_message *hm) {
 4999|  12.4k|  return atoi(hm->uri.buf);
 5000|  12.4k|}
mg_http_connect:
 5241|  5.56k|                                      mg_event_handler_t fn, void *fn_data) {
 5242|       |  return mg_connect_svc(mgr, url, fn, fn_data, http_cb, NULL);
 5243|  5.56k|}
mg_iobuf_resize:
 5264|  29.5k|bool mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
 5265|  29.5k|  bool ok = true;
 5266|  29.5k|  new_size = roundup(new_size, io->align);
 5267|  29.5k|  if (new_size == 0) {
  ------------------
  |  Branch (5267:7): [True: 22.2k, False: 7.27k]
  ------------------
 5268|  22.2k|    mg_bzero(io->buf, io->size);
 5269|  22.2k|    mg_free(io->buf);
 5270|  22.2k|    io->buf = NULL;
 5271|  22.2k|    io->len = io->size = 0;
 5272|  22.2k|  } else if (new_size != io->size) {
  ------------------
  |  Branch (5272:14): [True: 7.27k, False: 0]
  ------------------
 5273|       |    // NOTE(lsm): do not use realloc here. Use mg_calloc/mg_free only
 5274|  7.27k|    void *p = mg_calloc(1, new_size);
 5275|  7.27k|    if (p != NULL) {
  ------------------
  |  Branch (5275:9): [True: 7.27k, False: 0]
  ------------------
 5276|  7.27k|      size_t len = new_size < io->len ? new_size : io->len;
  ------------------
  |  Branch (5276:20): [True: 0, False: 7.27k]
  ------------------
 5277|  7.27k|      if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
  ------------------
  |  Branch (5277:11): [True: 0, False: 7.27k]
  |  Branch (5277:22): [True: 0, False: 0]
  ------------------
 5278|  7.27k|      mg_bzero(io->buf, io->size);
 5279|  7.27k|      mg_free(io->buf);
 5280|  7.27k|      io->buf = (unsigned char *) p;
 5281|  7.27k|      io->size = new_size;
 5282|  7.27k|      io->len = len;
 5283|  7.27k|    } else {
 5284|      0|      ok = false;
 5285|      0|      MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5286|      0|    }
 5287|  7.27k|  }
 5288|  29.5k|  return ok;
 5289|  29.5k|}
mg_iobuf_add:
 5299|  5.56k|                    size_t len) {
 5300|  5.56k|  size_t new_size = roundup(io->len + len, io->align);
 5301|  5.56k|  mg_iobuf_resize(io, new_size);      // Attempt to resize
 5302|  5.56k|  if (new_size != io->size) len = 0;  // Resize failure, append nothing
  ------------------
  |  Branch (5302:7): [True: 0, False: 5.56k]
  ------------------
 5303|  5.56k|  if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
  ------------------
  |  Branch (5303:7): [True: 0, False: 5.56k]
  ------------------
 5304|  5.56k|  if (buf != NULL) memmove(io->buf + ofs, buf, len);
  ------------------
  |  Branch (5304:7): [True: 5.56k, False: 0]
  ------------------
 5305|  5.56k|  if (ofs > io->len) io->len += ofs - io->len;
  ------------------
  |  Branch (5305:7): [True: 0, False: 5.56k]
  ------------------
 5306|  5.56k|  io->len += len;
 5307|  5.56k|  return len;
 5308|  5.56k|}
mg_iobuf_del:
 5310|  1.37k|size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
 5311|  1.37k|  if (ofs > io->len) ofs = io->len;
  ------------------
  |  Branch (5311:7): [True: 0, False: 1.37k]
  ------------------
 5312|  1.37k|  if (ofs + len > io->len) len = io->len - ofs;
  ------------------
  |  Branch (5312:7): [True: 0, False: 1.37k]
  ------------------
 5313|  1.37k|  if (io->buf) memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
  ------------------
  |  Branch (5313:7): [True: 1.37k, False: 0]
  ------------------
 5314|  1.37k|  if (io->buf) mg_bzero(io->buf + io->len - len, len);
  ------------------
  |  Branch (5314:7): [True: 1.37k, False: 0]
  ------------------
 5315|  1.37k|  io->len -= len;
 5316|  1.37k|  return len;
 5317|  1.37k|}
mg_iobuf_free:
 5319|  22.2k|void mg_iobuf_free(struct mg_iobuf *io) {
 5320|  22.2k|  mg_iobuf_resize(io, 0);
 5321|  22.2k|}
mg_json_get:
 5465|  16.6k|int mg_json_get(struct mg_str json, const char *path, int *toklen) {
 5466|  16.6k|  const char *s = json.buf;
 5467|  16.6k|  int len = (int) json.len;
 5468|  16.6k|  enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
 5469|  16.6k|  unsigned char nesting[MG_JSON_MAX_DEPTH];
 5470|  16.6k|  int i = 0;             // Current offset in `s`
 5471|  16.6k|  int j = 0;             // Offset in `s` we're looking for (return value)
 5472|  16.6k|  int depth = 0;         // Current depth (nesting level)
 5473|  16.6k|  int ed = 0;            // Expected depth
 5474|  16.6k|  int pos = 1;           // Current position in `path`
 5475|  16.6k|  int ci = -1, ei = -1;  // Current and expected index in array
 5476|       |
 5477|  16.6k|  if (toklen) *toklen = 0;
  ------------------
  |  Branch (5477:7): [True: 16.6k, False: 0]
  ------------------
 5478|  16.6k|  if (path[0] != '$') return MG_JSON_INVALID;
  ------------------
  |  Branch (5478:7): [True: 0, False: 16.6k]
  ------------------
 5479|       |
 5480|  16.6k|#define MG_CHECKRET(x)                                  \
 5481|  16.6k|  do {                                                  \
 5482|  16.6k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
 5483|  16.6k|      if (toklen) *toklen = i - j + 1;                  \
 5484|  16.6k|      return j;                                         \
 5485|  16.6k|    }                                                   \
 5486|  16.6k|  } while (0)
 5487|       |
 5488|       |// In the ascii table, the distance between `[` and `]` is 2.
 5489|       |// Ditto for `{` and `}`. Hence +2 in the code below.
 5490|  16.6k|#define MG_EOO(x)                                            \
 5491|  16.6k|  do {                                                       \
 5492|  16.6k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
 5493|  16.6k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
 5494|  16.6k|    depth--;                                                 \
 5495|  16.6k|    MG_CHECKRET(x);                                          \
 5496|  16.6k|  } while (0)
 5497|       |
 5498|   649k|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (5498:15): [True: 648k, False: 977]
  ------------------
 5499|   648k|    unsigned char c = ((unsigned char *) s)[i];
 5500|   648k|    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
  ------------------
  |  Branch (5500:9): [True: 1.99k, False: 646k]
  |  Branch (5500:21): [True: 582, False: 646k]
  |  Branch (5500:34): [True: 709, False: 645k]
  |  Branch (5500:47): [True: 628, False: 645k]
  ------------------
 5501|   645k|    switch (expecting) {
  ------------------
  |  Branch (5501:13): [True: 645k, False: 0]
  ------------------
 5502|   324k|      case S_VALUE:
  ------------------
  |  Branch (5502:7): [True: 324k, False: 320k]
  ------------------
 5503|       |        // p("V %s [%.*s] %d %d %d %d\n", path, pos, path, depth, ed, ci, ei);
 5504|   324k|        if (depth == ed) j = i;
  ------------------
  |  Branch (5504:13): [True: 19.1k, False: 305k]
  ------------------
 5505|   324k|        if (c == '{') {
  ------------------
  |  Branch (5505:13): [True: 5.33k, False: 319k]
  ------------------
 5506|  5.33k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (5506:15): [True: 11, False: 5.32k]
  ------------------
 5507|  5.32k|          if (depth == ed && path[pos] == '.' && ci == ei) {
  ------------------
  |  Branch (5507:15): [True: 1.56k, False: 3.76k]
  |  Branch (5507:30): [True: 333, False: 1.23k]
  |  Branch (5507:50): [True: 333, False: 0]
  ------------------
 5508|       |            // If we start the object, reset array indices
 5509|    333|            ed++, pos++, ci = ei = -1;
 5510|    333|          }
 5511|  5.32k|          nesting[depth++] = c;
 5512|  5.32k|          expecting = S_KEY;
 5513|  5.32k|          break;
 5514|   319k|        } else if (c == '[') {
  ------------------
  |  Branch (5514:20): [True: 15.5k, False: 303k]
  ------------------
 5515|  15.5k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (5515:15): [True: 14, False: 15.5k]
  ------------------
 5516|  15.5k|          if (depth == ed && path[pos] == '[' && ei == ci) {
  ------------------
  |  Branch (5516:15): [True: 2.87k, False: 12.6k]
  |  Branch (5516:30): [True: 356, False: 2.52k]
  |  Branch (5516:50): [True: 356, False: 0]
  ------------------
 5517|    356|            ed++, pos++, ci = 0;
 5518|    712|            for (ei = 0; path[pos] != ']' && path[pos] != '\0'; pos++) {
  ------------------
  |  Branch (5518:26): [True: 356, False: 356]
  |  Branch (5518:46): [True: 356, False: 0]
  ------------------
 5519|    356|              ei *= 10;
 5520|    356|              ei += path[pos] - '0';
 5521|    356|            }
 5522|    356|            if (path[pos] != 0) pos++;
  ------------------
  |  Branch (5522:17): [True: 356, False: 0]
  ------------------
 5523|    356|          }
 5524|  15.5k|          nesting[depth++] = c;
 5525|  15.5k|          break;
 5526|   303k|        } else if (c == ']' && depth > 0) {  // Empty array
  ------------------
  |  Branch (5526:20): [True: 6.02k, False: 297k]
  |  Branch (5526:32): [True: 5.99k, False: 33]
  ------------------
 5527|  5.99k|          MG_EOO(']');
  ------------------
  |  | 5491|  5.99k|  do {                                                       \
  |  | 5492|  5.99k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5492:9): [True: 4, False: 5.99k]
  |  |  |  Branch (5492:24): [True: 0, False: 4]
  |  |  ------------------
  |  | 5493|  5.99k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5493:9): [True: 14, False: 5.98k]
  |  |  ------------------
  |  | 5494|  5.99k|    depth--;                                                 \
  |  | 5495|  5.98k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5481|  5.98k|  do {                                                  \
  |  |  |  | 5482|  5.98k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5482:9): [True: 1.09k, False: 4.89k]
  |  |  |  |  |  Branch (5482:24): [True: 19, False: 1.07k]
  |  |  |  |  |  Branch (5482:45): [True: 19, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5483|     19|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5483:11): [True: 19, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5484|     19|      return j;                                         \
  |  |  |  | 5485|     19|    }                                                   \
  |  |  |  | 5486|  5.98k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5486:12): [Folded, False: 5.96k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5496|  5.98k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5496:12): [Folded, False: 5.96k]
  |  |  ------------------
  ------------------
 5528|   297k|        } else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
  ------------------
  |  Branch (5528:20): [True: 1.99k, False: 295k]
  |  Branch (5528:32): [True: 1.97k, False: 26]
  |  Branch (5528:47): [True: 1.90k, False: 71]
  ------------------
 5529|  1.90k|          i += 3;
 5530|   295k|        } else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
  ------------------
  |  Branch (5530:20): [True: 15.3k, False: 280k]
  |  Branch (5530:32): [True: 15.3k, False: 14]
  |  Branch (5530:47): [True: 15.2k, False: 89]
  ------------------
 5531|  15.2k|          i += 3;
 5532|   280k|        } else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
  ------------------
  |  Branch (5532:20): [True: 5.74k, False: 274k]
  |  Branch (5532:32): [True: 5.71k, False: 29]
  |  Branch (5532:47): [True: 5.61k, False: 103]
  ------------------
 5533|  5.61k|          i += 4;
 5534|   274k|        } else if (c == '-' || ((c >= '0' && c <= '9'))) {
  ------------------
  |  Branch (5534:20): [True: 125k, False: 148k]
  |  Branch (5534:34): [True: 143k, False: 5.00k]
  |  Branch (5534:46): [True: 134k, False: 9.70k]
  ------------------
 5535|   260k|          int numlen = 0;
 5536|   260k|          mg_atod(&s[i], len - i, &numlen);
 5537|   260k|          i += numlen - 1;
 5538|   260k|        } else if (c == '"') {
  ------------------
  |  Branch (5538:20): [True: 1.91k, False: 12.7k]
  ------------------
 5539|  1.91k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 5540|  1.91k|          if (n < 0) return n;
  ------------------
  |  Branch (5540:15): [True: 343, False: 1.57k]
  ------------------
 5541|  1.57k|          i += n + 1;
 5542|  12.7k|        } else {
 5543|  12.7k|          return MG_JSON_INVALID;
 5544|  12.7k|        }
 5545|   290k|        MG_CHECKRET('V');
  ------------------
  |  | 5481|   290k|  do {                                                  \
  |  | 5482|   290k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  ------------------
  |  |  |  Branch (5482:9): [True: 2.79k, False: 287k]
  |  |  |  Branch (5482:24): [True: 637, False: 2.15k]
  |  |  |  Branch (5482:45): [True: 637, False: 0]
  |  |  ------------------
  |  | 5483|    637|      if (toklen) *toklen = i - j + 1;                  \
  |  |  ------------------
  |  |  |  Branch (5483:11): [True: 637, False: 0]
  |  |  ------------------
  |  | 5484|    637|      return j;                                         \
  |  | 5485|    637|    }                                                   \
  |  | 5486|   290k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5486:12): [Folded, False: 289k]
  |  |  ------------------
  ------------------
 5546|   289k|        if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5546:13): [True: 2.15k, False: 287k]
  |  Branch (5546:28): [True: 0, False: 2.15k]
  ------------------
 5547|   289k|        expecting = S_COMMA_OR_EOO;
 5548|   289k|        break;
 5549|       |
 5550|  12.3k|      case S_KEY:
  ------------------
  |  Branch (5550:7): [True: 12.3k, False: 632k]
  ------------------
 5551|  12.3k|        if (c == '"') {
  ------------------
  |  Branch (5551:13): [True: 9.66k, False: 2.66k]
  ------------------
 5552|  9.66k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 5553|  9.66k|          if (n < 0) return n;
  ------------------
  |  Branch (5553:15): [True: 222, False: 9.43k]
  ------------------
 5554|  9.43k|          if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5554:15): [True: 0, False: 9.43k]
  ------------------
 5555|  9.43k|          if (depth < ed) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5555:15): [True: 1, False: 9.43k]
  ------------------
 5556|  9.43k|          if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5556:15): [True: 2.34k, False: 7.09k]
  |  Branch (5556:30): [True: 1, False: 2.34k]
  ------------------
 5557|       |          // printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
 5558|       |          //        &s[i + 1], n, depth, ed, ci, ei);
 5559|       |          //  NOTE(cpq): in the check sequence below is important.
 5560|       |          //  strncmp() must go first: it fails fast if the remaining length
 5561|       |          //  of the path is smaller than `n`.
 5562|  9.43k|          if (depth == ed && path[pos - 1] == '.' &&
  ------------------
  |  Branch (5562:15): [True: 2.34k, False: 7.09k]
  |  Branch (5562:30): [True: 2.34k, False: 0]
  ------------------
 5563|  2.34k|              strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
  ------------------
  |  Branch (5563:15): [True: 1.08k, False: 1.26k]
  ------------------
 5564|  1.08k|              (path[pos + n] == '\0' || path[pos + n] == '.' ||
  ------------------
  |  Branch (5564:16): [True: 2, False: 1.08k]
  |  Branch (5564:41): [True: 7, False: 1.07k]
  ------------------
 5565|  1.07k|               path[pos + n] == '[')) {
  ------------------
  |  Branch (5565:16): [True: 0, False: 1.07k]
  ------------------
 5566|      9|            pos += n;
 5567|      9|          }
 5568|  9.43k|          i += n + 1;
 5569|  9.43k|          expecting = S_COLON;
 5570|  9.43k|        } else if (c == '}') {  // Empty object
  ------------------
  |  Branch (5570:20): [True: 2.54k, False: 125]
  ------------------
 5571|  2.54k|          MG_EOO('}');
  ------------------
  |  | 5491|  2.54k|  do {                                                       \
  |  | 5492|  2.54k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5492:9): [True: 14, False: 2.52k]
  |  |  |  Branch (5492:24): [True: 0, False: 14]
  |  |  ------------------
  |  | 5493|  2.54k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5493:9): [True: 0, False: 2.54k]
  |  |  ------------------
  |  | 5494|  2.54k|    depth--;                                                 \
  |  | 5495|  2.54k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5481|  2.54k|  do {                                                  \
  |  |  |  | 5482|  2.54k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5482:9): [True: 547, False: 1.99k]
  |  |  |  |  |  Branch (5482:24): [True: 20, False: 527]
  |  |  |  |  |  Branch (5482:45): [True: 20, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5483|     20|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5483:11): [True: 20, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5484|     20|      return j;                                         \
  |  |  |  | 5485|     20|    }                                                   \
  |  |  |  | 5486|  2.54k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5486:12): [Folded, False: 2.52k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5496|  2.54k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5496:12): [Folded, False: 2.52k]
  |  |  ------------------
  ------------------
 5572|  2.52k|          expecting = S_COMMA_OR_EOO;
 5573|  2.52k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5573:15): [True: 527, False: 1.99k]
  |  Branch (5573:30): [True: 0, False: 527]
  ------------------
 5574|  2.52k|        } else {
 5575|    125|          return MG_JSON_INVALID;
 5576|    125|        }
 5577|  11.9k|        break;
 5578|       |
 5579|  11.9k|      case S_COLON:
  ------------------
  |  Branch (5579:7): [True: 9.27k, False: 635k]
  ------------------
 5580|  9.27k|        if (c == ':') {
  ------------------
  |  Branch (5580:13): [True: 9.01k, False: 260]
  ------------------
 5581|  9.01k|          expecting = S_VALUE;
 5582|  9.01k|        } else {
 5583|    260|          return MG_JSON_INVALID;
 5584|    260|        }
 5585|  9.01k|        break;
 5586|       |
 5587|   298k|      case S_COMMA_OR_EOO:
  ------------------
  |  Branch (5587:7): [True: 298k, False: 346k]
  ------------------
 5588|   298k|        if (depth <= 0) {
  ------------------
  |  Branch (5588:13): [True: 884, False: 298k]
  ------------------
 5589|    884|          return MG_JSON_INVALID;
 5590|   298k|        } else if (c == ',') {
  ------------------
  |  Branch (5590:20): [True: 290k, False: 7.46k]
  ------------------
 5591|   290k|          expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
  ------------------
  |  Branch (5591:23): [True: 7.06k, False: 283k]
  ------------------
 5592|   290k|        } else if (c == ']' || c == '}') {
  ------------------
  |  Branch (5592:20): [True: 6.12k, False: 1.34k]
  |  Branch (5592:32): [True: 1.06k, False: 279]
  ------------------
 5593|  7.19k|          if (depth == ed && c == '}' && path[pos - 1] == '.')
  ------------------
  |  Branch (5593:15): [True: 14, False: 7.17k]
  |  Branch (5593:30): [True: 10, False: 4]
  |  Branch (5593:42): [True: 9, False: 1]
  ------------------
 5594|      9|            return MG_JSON_NOT_FOUND;
 5595|  7.18k|          if (depth == ed && c == ']' && path[pos - 1] == ',')
  ------------------
  |  Branch (5595:15): [True: 5, False: 7.17k]
  |  Branch (5595:30): [True: 4, False: 1]
  |  Branch (5595:42): [True: 0, False: 4]
  ------------------
 5596|      0|            return MG_JSON_NOT_FOUND;
 5597|  7.18k|          MG_EOO('O');
  ------------------
  |  | 5491|  7.18k|  do {                                                       \
  |  | 5492|  7.18k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5492:9): [True: 5, False: 7.17k]
  |  |  |  Branch (5492:24): [True: 0, False: 5]
  |  |  ------------------
  |  | 5493|  7.18k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5493:9): [True: 21, False: 7.16k]
  |  |  ------------------
  |  | 5494|  7.18k|    depth--;                                                 \
  |  | 5495|  7.16k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5481|  7.16k|  do {                                                  \
  |  |  |  | 5482|  7.16k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5482:9): [True: 602, False: 6.55k]
  |  |  |  |  |  Branch (5482:24): [True: 47, False: 555]
  |  |  |  |  |  Branch (5482:45): [True: 47, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5483|     47|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5483:11): [True: 47, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5484|     47|      return j;                                         \
  |  |  |  | 5485|     47|    }                                                   \
  |  |  |  | 5486|  7.16k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5486:12): [Folded, False: 7.11k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5496|  7.16k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5496:12): [Folded, False: 7.11k]
  |  |  ------------------
  ------------------
 5598|  7.11k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5598:15): [True: 555, False: 6.55k]
  |  Branch (5598:30): [True: 0, False: 555]
  ------------------
 5599|  7.11k|        } else {
 5600|    279|          return MG_JSON_INVALID;
 5601|    279|        }
 5602|   297k|        break;
 5603|   645k|    }
 5604|   645k|  }
 5605|    977|  return MG_JSON_NOT_FOUND;
 5606|  16.6k|}
_Z10mg_l2_initP11mg_tcpip_if:
 5953|  5.56k|void mg_l2_init(struct mg_tcpip_if *ifp) {
 5954|  5.56k|  l2_init[ifp->l2type](ifp);
 5955|  5.56k|}
_Z10mg_l2_pollP11mg_tcpip_ifb:
 5957|  5.56k|bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 5958|  5.56k|  return l2_poll[ifp->l2type](ifp, expired_1000ms);
 5959|  5.56k|}
_Z12mg_l2_headerP11mg_tcpip_if10mg_l2protoPhS2_S2_:
 5962|  5.56k|                      uint8_t *src, uint8_t *dst, uint8_t *frame) {
 5963|  5.56k|  return l2_header[ifp->l2type](ifp, proto, (struct mg_l2addr *) src,
 5964|  5.56k|                                (struct mg_l2addr *) dst, frame);
 5965|  5.56k|}
_Z13mg_l2_trailerP11mg_tcpip_ifmPh:
 5967|  5.56k|size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *frame) {
 5968|  5.56k|  return l2_trailer[ifp->l2type](ifp, len, frame);
 5969|  5.56k|}
_Z8mg_l2_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 5972|  5.56k|              struct mg_str *pay, struct mg_str *raw) {
 5973|  5.56k|  return l2_rx[ifp->l2type](ifp, proto, pay, raw);
 5974|  5.56k|}
_Z13mg_l2_getaddrP11mg_tcpip_ifPh:
 5976|      1|uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) {
 5977|      1|  return (uint8_t *) l2_getaddr[ifp->l2type](ifp, frame);
 5978|      1|}
_Z19mg_l2_driver_outputP11mg_tcpip_ifm:
 6002|  1.12k|size_t mg_l2_driver_output(struct mg_tcpip_if *ifp, size_t len) {
 6003|  1.12k|  size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
 6004|  1.12k|  if (n == len) ifp->nsent++;
  ------------------
  |  Branch (6004:7): [True: 1.12k, False: 0]
  ------------------
 6005|  1.12k|  return n;
 6006|  1.12k|}
_Z14mg_l2_eth_initP11mg_tcpip_if:
 6119|  3.70k|void mg_l2_eth_init(struct mg_tcpip_if *ifp) {
 6120|  3.70k|  struct mg_l2addr *l2addr = (struct mg_l2addr *) ifp->mac;
 6121|       |  // If MAC is not set, make a random one
 6122|  3.70k|  if (l2addr->addr.mac[0] == 0 && l2addr->addr.mac[1] == 0 &&
  ------------------
  |  Branch (6122:7): [True: 3.70k, False: 0]
  |  Branch (6122:35): [True: 3.70k, False: 0]
  ------------------
 6123|  3.70k|      l2addr->addr.mac[2] == 0 && l2addr->addr.mac[3] == 0 &&
  ------------------
  |  Branch (6123:7): [True: 3.70k, False: 0]
  |  Branch (6123:35): [True: 3.70k, False: 0]
  ------------------
 6124|  3.70k|      l2addr->addr.mac[4] == 0 && l2addr->addr.mac[5] == 0) {
  ------------------
  |  Branch (6124:7): [True: 3.70k, False: 0]
  |  Branch (6124:35): [True: 3.70k, False: 0]
  ------------------
 6125|  3.70k|    l2addr->addr.mac[0] = 0x02;  // Locally administered, unicast
 6126|  3.70k|    mg_random(&l2addr->addr.mac[1], sizeof(l2addr->addr.mac) - 1);
 6127|  3.70k|    MG_INFO(
  ------------------
  |  | 1767|  3.70k|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|  3.70k|  do {                      \
  |  |  |  | 1757|  3.70k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 3.70k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  3.70k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 3.70k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6128|  3.70k|        ("MAC not set. Generated random: %M", mg_print_mac, l2addr->addr.mac));
 6129|  3.70k|  }
 6130|  3.70k|  ifp->l2mtu = 1500;
 6131|  3.70k|  ifp->framesize = 1540;
 6132|  3.70k|}
_Z14mg_l2_eth_pollP11mg_tcpip_ifb:
 6134|  1.85k|bool mg_l2_eth_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 6135|  1.85k|  (void) ifp;
 6136|  1.85k|  (void) expired_1000ms;
 6137|  1.85k|  return true;
 6138|  1.85k|}
_Z16mg_l2_eth_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 6142|  3.71k|                          uint8_t *frame) {
 6143|  3.71k|  struct eth_data *d = &ifp->l2data.eth;
 6144|  3.71k|  struct eth *eth = (struct eth *) frame;
 6145|  3.71k|  uint8_t *hlp;
 6146|  3.71k|  hlp = (uint8_t *) (eth + 1);
 6147|  3.71k|  memcpy(eth->src, src->addr.mac, sizeof(eth->dst));
 6148|  3.71k|  memcpy(eth->dst, dst->addr.mac, sizeof(eth->dst));
 6149|  3.71k|  if (d->vlan_id == 0) {  // Traditional plain frame
  ------------------
  |  Branch (6149:7): [True: 2.91k, False: 798]
  ------------------
 6150|  2.91k|    eth->type = mg_htons(eth_types[(unsigned int) proto]);
  ------------------
  |  | 2037|  2.91k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6151|  2.91k|  } else {  // Add 802.1Q tag
 6152|    798|    struct qtag *qtag = (struct qtag *) &eth->type;
 6153|    798|    qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2037|    798|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6154|    798|    qtag->tci = mg_htons(d->vlan_id);  // PCP = default (best-effort)
  ------------------
  |  | 2037|    798|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6155|    798|    hlp += sizeof(*qtag);
 6156|    798|    MG_STORE_BE16(qtag + 1, eth_types[(unsigned int) proto]);
  ------------------
  |  | 2003|    798|  do {                                    \
  |  | 2004|    798|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 1976|    798|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2005|    798|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 1976|    798|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2006|    798|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2006:12): [Folded, False: 798]
  |  |  ------------------
  ------------------
 6157|    798|  }
 6158|  3.71k|  return hlp;
 6159|  3.71k|}
_Z17mg_l2_eth_trailerP11mg_tcpip_ifmPh:
 6161|  3.71k|size_t mg_l2_eth_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6162|  3.71k|  struct eth_data *d = &ifp->l2data.eth;
 6163|       |  // there is no len field in Ethernet, CRC is hw-calculated; pad to 64 - CRC
 6164|  3.71k|  size_t ethlen =
 6165|  3.71k|      len + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0);
  ------------------
  |  Branch (6165:35): [True: 798, False: 2.91k]
  ------------------
 6166|  3.71k|  (void) cur;
 6167|  3.71k|  return ethlen >= 60 ? ethlen : 60;
  ------------------
  |  Branch (6167:10): [True: 2.12k, False: 1.59k]
  ------------------
 6168|  3.71k|}
_Z12mg_l2_eth_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6181|  3.70k|                  struct mg_str *pay, struct mg_str *raw) {
 6182|  3.70k|  struct eth *eth = (struct eth *) raw->buf;
 6183|  3.70k|  struct eth_data *d = &ifp->l2data.eth;
 6184|  3.70k|  uint16_t type, len;
 6185|  3.70k|  unsigned int i;
 6186|  3.70k|  size_t hdrlen =
 6187|  3.70k|      sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0);
  ------------------
  |  Branch (6187:29): [True: 798, False: 2.90k]
  ------------------
 6188|  3.70k|  if (raw->len < hdrlen) return false;  // Truncated - runt?
  ------------------
  |  Branch (6188:7): [True: 1.03k, False: 2.67k]
  ------------------
 6189|  2.67k|  len = (uint16_t) raw->len;
 6190|  2.67k|  if (d->vlan_id == 0) {  // We don't handle VLANs
  ------------------
  |  Branch (6190:7): [True: 1.92k, False: 744]
  ------------------
 6191|  1.92k|    type = mg_ntohs(eth->type);
 6192|  1.92k|  } else {  // We do, check 802.1Q tag
 6193|    744|    struct qtag *qtag = (struct qtag *) &eth->type;
 6194|    744|    if (qtag->tpid != mg_htons(0x8100)) return false;  // Untagged frame
  ------------------
  |  | 2037|    744|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (6194:9): [True: 258, False: 486]
  ------------------
 6195|    486|    if (VLAN_ID(mg_ntohs(qtag->tci)) != VLAN_ID(d->vlan_id))
  ------------------
  |  | 6101|    486|#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF))
  ------------------
                  if (VLAN_ID(mg_ntohs(qtag->tci)) != VLAN_ID(d->vlan_id))
  ------------------
  |  | 6101|    486|#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF))
  ------------------
  |  Branch (6195:9): [True: 242, False: 244]
  ------------------
 6196|    242|      return false;  // Not our VLAN
 6197|    244|    type = MG_LOAD_BE16(qtag + 1);
  ------------------
  |  | 1983|    244|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|    244|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|    244|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6198|    244|  }
 6199|  2.17k|  if (ifp->enable_mac_check &&
  ------------------
  |  Branch (6199:7): [True: 0, False: 2.17k]
  ------------------
 6200|      0|      memcmp(eth->dst, ifp->mac, sizeof(eth->dst)) != 0 &&
  ------------------
  |  Branch (6200:7): [True: 0, False: 0]
  ------------------
 6201|      0|      memcmp(eth->dst, mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL),
  ------------------
  |  Branch (6201:7): [True: 0, False: 0]
  ------------------
 6202|      0|             sizeof(eth->dst)) != 0)
 6203|      0|    return false;  // TODO(): add multicast addresses
 6204|  2.17k|  if (ifp->enable_fcs_check && len > hdrlen + 4) {
  ------------------
  |  Branch (6204:7): [True: 0, False: 2.17k]
  |  Branch (6204:32): [True: 0, False: 0]
  ------------------
 6205|      0|    uint32_t crc, crc_rx;
 6206|      0|    len -= 4;
 6207|      0|    crc = mg_crc32(0, (const char *) raw->buf, len);
 6208|      0|    crc_rx = MG_LOAD_LE32(raw->buf + len);
  ------------------
  |  | 6176|      0|  ((uint32_t) (((uint32_t) MG_U8P(p)[3] << 24U) | \
  |  |  ------------------
  |  |  |  | 1976|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 6177|      0|               ((uint32_t) MG_U8P(p)[2] << 16U) | \
  |  |  ------------------
  |  |  |  | 1976|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 6178|      0|               ((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[0]))
  |  |  ------------------
  |  |  |  | 1976|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                              ((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[0]))
  |  |  ------------------
  |  |  |  | 1976|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6209|      0|    if (crc_rx != crc)
  ------------------
  |  Branch (6209:9): [True: 0, False: 0]
  ------------------
 6210|      0|      return false;
 6211|      0|  }
 6212|  2.17k|  pay->buf = ((char *) eth) + hdrlen;
 6213|  2.17k|  pay->len = len - hdrlen;
 6214|  2.17k|  if (len > ifp->framesize) return false;  // Oversized
  ------------------
  |  Branch (6214:7): [True: 474, False: 1.69k]
  ------------------
 6215|  9.51k|  for (i = 0; i < sizeof(eth_types) / sizeof(uint16_t); i++) {
  ------------------
  |  Branch (6215:15): [True: 8.01k, False: 1.49k]
  ------------------
 6216|  8.01k|    if (type == eth_types[i]) break;
  ------------------
  |  Branch (6216:9): [True: 199, False: 7.81k]
  ------------------
 6217|  8.01k|  }
 6218|  1.69k|  if (i == sizeof(eth_types) / sizeof(eth_types[0])) {
  ------------------
  |  Branch (6218:7): [True: 1.49k, False: 199]
  ------------------
 6219|  1.49k|    MG_DEBUG(("Unknown eth type %x", type));
  ------------------
  |  | 1768|  1.49k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  1.49k|  do {                      \
  |  |  |  | 1757|  1.49k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1.49k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  1.49k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1.49k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6220|  1.49k|    if (mg_log_level >= MG_LL_VERBOSE)
  ------------------
  |  Branch (6220:9): [True: 0, False: 1.49k]
  ------------------
 6221|      0|      mg_hexdump(raw->buf, raw->len >= 32 ? 32 : raw->len);
  ------------------
  |  Branch (6221:28): [True: 0, False: 0]
  ------------------
 6222|  1.49k|    return false;
 6223|  1.49k|  }
 6224|    199|  *proto = (enum mg_l2proto) i;
 6225|    199|  return true;
 6226|  1.69k|}
_Z17mg_l2_eth_getaddrP11mg_tcpip_ifPh:
 6228|      2|struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) {
 6229|      2|  struct eth *eth = (struct eth *) frame; 
 6230|      2|  (void) ifp; // address field is before a possible 802.1Q tag
 6231|      2|  return (struct mg_l2addr *) &eth->src;
 6232|      2|}
_Z14mg_l2_ppp_initP11mg_tcpip_if:
 6400|  1.85k|void mg_l2_ppp_init(struct mg_tcpip_if *ifp) {
 6401|  1.85k|  ifp->l2mtu = 1500;
 6402|  1.85k|  ifp->framesize = ifp->l2mtu + sizeof(struct ppp) + sizeof(struct hdlc_) + 2;
 6403|  1.85k|}
_Z16mg_l2_pppoe_initP11mg_tcpip_if:
 6407|  1.85k|void mg_l2_pppoe_init(struct mg_tcpip_if *ifp) {
 6408|  1.85k|  mg_l2_eth_init(ifp);
 6409|  1.85k|  ifp->l2mtu = ifp->l2mtu - (uint16_t) (sizeof(struct pppoe) +
 6410|  1.85k|                                    sizeof(struct ppp));  // 1500 --> 1492
 6411|  1.85k|}
_Z14mg_l2_ppp_pollP11mg_tcpip_ifb:
 6413|  3.70k|bool mg_l2_ppp_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 6414|  3.70k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_DOWN) s_lcpup = false;
  ------------------
  |  | 4758|  3.70k|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (6414:7): [True: 3.70k, False: 0]
  |  Branch (6414:25): [True: 0, False: 3.70k]
  ------------------
 6415|  3.70k|  return s_lcpup;
 6416|  3.70k|}
_Z16mg_l2_ppp_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 6440|  1.85k|                          uint8_t *frame) {
 6441|  1.85k|  (void) ifp;
 6442|  1.85k|  (void) src;
 6443|  1.85k|  (void) dst;
 6444|  1.85k|  return l2_ppp_header(proto, hdlc_header(frame));
 6445|  1.85k|}
_Z18mg_l2_pppoe_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 6464|  1.85k|                            uint8_t *frame) {
 6465|  1.85k|  (void) dst;
 6466|  1.85k|  return l2_ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
 6467|  1.85k|                                           s_id, src, dst, frame));
 6468|  1.85k|}
_Z17mg_l2_ppp_trailerP11mg_tcpip_ifmPh:
 6470|  2.97k|size_t mg_l2_ppp_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6471|  2.97k|  uint16_t crc;
 6472|  2.97k|  uint8_t *frame;
 6473|  2.97k|  len += sizeof(struct ppp) + sizeof(struct hdlc_);
 6474|  2.97k|  frame = cur - len;
 6475|  2.97k|  crc = mg_crc16(0, (const char *) frame, len);
 6476|  2.97k|  *cur++ = (uint8_t) crc;  // add CRC, note the byte order
 6477|  2.97k|  *cur++ = (uint8_t) (crc >> 8);
 6478|       |  // there is no len field in PPP
 6479|  2.97k|  (void) ifp;
 6480|  2.97k|  return len + 2;
 6481|  2.97k|}
_Z19mg_l2_pppoe_trailerP11mg_tcpip_ifmPh:
 6491|  1.85k|size_t mg_l2_pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6492|  1.85k|  return pppoe_trailer(ifp, len + sizeof(struct ppp), cur);
 6493|  1.85k|}
_Z12mg_l2_ppp_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6757|  1.85k|                  struct mg_str *pay, struct mg_str *raw) {
 6758|  1.85k|  struct hdlc_ *hdlc = (struct hdlc_ *) raw->buf;
 6759|  1.85k|  if (raw->len < sizeof(*hdlc) + 2) return false;  // Truncated
  ------------------
  |  Branch (6759:7): [True: 136, False: 1.71k]
  ------------------
 6760|  1.71k|  if (hdlc->addr == MG_PPP_ADDR && hdlc->ctrl == MG_PPP_CTRL) {
  ------------------
  |  | 6350|  3.43k|#define MG_PPP_ADDR 0xff
  ------------------
                if (hdlc->addr == MG_PPP_ADDR && hdlc->ctrl == MG_PPP_CTRL) {
  ------------------
  |  | 6351|  1.56k|#define MG_PPP_CTRL 0x03
  ------------------
  |  Branch (6760:7): [True: 1.56k, False: 157]
  |  Branch (6760:36): [True: 1.55k, False: 1]
  ------------------
 6761|  1.55k|    pay->buf = (char *) (hdlc + 1);
 6762|  1.55k|    pay->len = raw->len - sizeof(*hdlc) - 2;
 6763|  1.55k|  } else {  // Address-and-Control-Field-Compressed PPP header
 6764|    158|    pay->buf = (char *) raw->buf;
 6765|    158|    pay->len = raw->len - 2;
 6766|    158|  }
 6767|  1.71k|  if (pay->len > ifp->l2mtu + sizeof(struct ppp)) return false;  // Oversized
  ------------------
  |  Branch (6767:7): [True: 349, False: 1.36k]
  ------------------
 6768|  1.36k|  return ppp_rx(ifp, proto, pay, raw);
 6769|  1.71k|}
_Z16mg_l2_pppoe_pollP11mg_tcpip_ifb:
 6823|  1.85k|bool mg_l2_pppoe_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 6824|  1.85k|  if (expired_1000ms && s_state == MG_PPPoE_ST_DISC &&
  ------------------
  |  | 6389|  3.70k|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
  |  Branch (6824:7): [True: 1.85k, False: 0]
  |  Branch (6824:25): [True: 1.35k, False: 499]
  ------------------
 6825|  1.35k|      ifp->state == MG_TCPIP_STATE_LINK_UP) {
  ------------------
  |  | 4759|  1.35k|#define MG_TCPIP_STATE_LINK_UP 1    // Driver reports physical link is up
  ------------------
  |  Branch (6825:7): [True: 0, False: 1.35k]
  ------------------
 6826|      0|    uint16_t tags[2];
 6827|      0|    tags[0] = mg_htons(0x0101);  // Service Request
  ------------------
  |  | 2037|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6828|      0|    tags[1] = mg_htons(0x0000);  // Any
  ------------------
  |  | 2037|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6829|      0|    pppoe_tx_frame(ifp, MG_PPPoE_PADI, 0, (uint8_t *) tags, sizeof(tags),
  ------------------
  |  | 6383|      0|#define MG_PPPoE_PADI 0x09
  ------------------
 6830|      0|                   mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL));
 6831|      0|    MG_DEBUG(("Sent PADI"));
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6832|  1.85k|  } else if (expired_1000ms && (s_state != MG_PPPoE_ST_SESS ||
  ------------------
  |  | 6391|  3.70k|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (6832:14): [True: 1.85k, False: 0]
  |  Branch (6832:33): [True: 1.37k, False: 475]
  ------------------
 6833|  1.37k|                                ifp->state == MG_TCPIP_STATE_DOWN)) {
  ------------------
  |  | 4758|    475|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (6833:33): [True: 0, False: 475]
  ------------------
 6834|  1.37k|    s_state = MG_PPPoE_ST_DISC;
  ------------------
  |  | 6389|  1.37k|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
 6835|  1.37k|  }
 6836|  1.85k|  return mg_l2_ppp_poll(ifp, expired_1000ms);
 6837|  1.85k|}
_Z14mg_l2_pppoe_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6844|  1.85k|                    struct mg_str *pay, struct mg_str *raw) {
 6845|  1.85k|  enum mg_l2proto eth_proto;  // raw is handled by eth
 6846|  1.85k|  struct pppoe *pppoe;
 6847|  1.85k|  if (!mg_l2_eth_rx(ifp, &eth_proto, pay, raw)) return false;
  ------------------
  |  Branch (6847:7): [True: 1.76k, False: 84]
  ------------------
 6848|     84|  pppoe = (struct pppoe *) pay->buf;            // here we handle pay, not raw
 6849|     84|  if (pay->len < sizeof(*pppoe)) return false;  // Truncated
  ------------------
  |  Branch (6849:7): [True: 3, False: 81]
  ------------------
 6850|     81|  if (pay->len - sizeof(*pppoe) > ifp->l2mtu + sizeof(struct ppp))
  ------------------
  |  Branch (6850:7): [True: 6, False: 75]
  ------------------
 6851|      6|    return false;  // Oversized
 6852|     75|  if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_DISC) {
  ------------------
  |  Branch (6852:7): [True: 13, False: 62]
  ------------------
 6853|     13|    MG_VERBOSE(("PPPoE_DISC"));
  ------------------
  |  | 1769|     13|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|     13|  do {                      \
  |  |  |  | 1757|     13|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 13]
  |  |  |  |  ------------------
  |  |  |  | 1758|     13|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 13]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6854|     13|    if (s_state == MG_PPPoE_ST_DISC && pppoe->code == MG_PPPoE_PADO &&
  ------------------
  |  | 6389|     26|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
                  if (s_state == MG_PPPoE_ST_DISC && pppoe->code == MG_PPPoE_PADO &&
  ------------------
  |  | 6384|     22|#define MG_PPPoE_PADO 0x07
  ------------------
  |  Branch (6854:9): [True: 9, False: 4]
  |  Branch (6854:40): [True: 2, False: 7]
  ------------------
 6855|      2|        pppoe->id == 0) {
  ------------------
  |  Branch (6855:9): [True: 2, False: 0]
  ------------------
 6856|      2|      uint16_t tags[2];
 6857|      2|      bool has_cookie = false;
 6858|      2|      size_t len = pay->len - sizeof(*pppoe);
 6859|      2|      uint8_t *p = (uint8_t *) (pppoe + 1);
 6860|      2|      uint16_t taglen;
 6861|      3|      while (len >= 4) {  // parse tags for a possible AC-Cookie
  ------------------
  |  Branch (6861:14): [True: 2, False: 1]
  ------------------
 6862|      2|        uint16_t curtag = MG_LOAD_BE16(p);
  ------------------
  |  | 1983|      2|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|      2|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|      2|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6863|      2|        taglen = MG_LOAD_BE16(p + 2);
  ------------------
  |  | 1983|      2|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|      2|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|      2|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6864|      2|        if (taglen > len - 4) return false;  // truncated / malformed
  ------------------
  |  Branch (6864:13): [True: 1, False: 1]
  ------------------
 6865|      1|        if (curtag == 0x0104) {
  ------------------
  |  Branch (6865:13): [True: 0, False: 1]
  ------------------
 6866|      0|          has_cookie = true;
 6867|      0|          break;
 6868|      0|        }
 6869|      1|        len -= 4 + taglen;
 6870|      1|        p += 4 + taglen;
 6871|      1|      }
 6872|      1|      tags[0] = mg_htons(0x0101);  // Service Request
  ------------------
  |  | 2037|      1|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6873|      1|      tags[1] = mg_htons(0x0000);  // Any
  ------------------
  |  | 2037|      1|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6874|      1|      if (has_cookie) {  // copy tags to before AC-Cookie tag in rx buffer
  ------------------
  |  Branch (6874:11): [True: 0, False: 1]
  ------------------
 6875|      0|        memcpy(p -= sizeof(tags), tags, sizeof(tags));  // point to all tags
 6876|      0|        taglen += 4 + sizeof(tags);                     // account for tags
 6877|      1|      } else {
 6878|      1|        p = (uint8_t *) tags;
 6879|      1|        taglen = sizeof(tags);
 6880|      1|      }
 6881|      1|      pppoe_tx_frame(ifp, MG_PPPoE_PADR, 0, p, taglen,
  ------------------
  |  | 6385|      1|#define MG_PPPoE_PADR 0x19
  ------------------
 6882|      1|                     mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf));
 6883|      1|      MG_DEBUG(("Sent PADR"));
  ------------------
  |  | 1768|      1|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6884|      1|      s_state = MG_PPPoE_ST_REQ;
  ------------------
  |  | 6390|      1|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
 6885|     11|    } else if (s_state == MG_PPPoE_ST_REQ && pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6390|     22|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
                  } else if (s_state == MG_PPPoE_ST_REQ && pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6386|      0|#define MG_PPPoE_PADS 0x65
  ------------------
  |  Branch (6885:16): [True: 0, False: 11]
  |  Branch (6885:46): [True: 0, False: 0]
  ------------------
 6886|      0|      s_id = pppoe->id;
 6887|      0|      memcpy(&ifp->gwmac,
 6888|      0|             mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf)->addr.mac, 6);
 6889|      0|      MG_DEBUG(("PPPoE session 0x%04x started", mg_ntohs(s_id)));
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6890|      0|      s_state = MG_PPPoE_ST_SESS;
  ------------------
  |  | 6391|      0|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
 6891|     11|    } else if (s_state == MG_PPPoE_ST_SESS && pppoe->code == MG_PPPoE_PADT &&
  ------------------
  |  | 6391|     22|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
                  } else if (s_state == MG_PPPoE_ST_SESS && pppoe->code == MG_PPPoE_PADT &&
  ------------------
  |  | 6387|     15|#define MG_PPPoE_PADT 0xa7
  ------------------
  |  Branch (6891:16): [True: 4, False: 7]
  |  Branch (6891:47): [True: 1, False: 3]
  ------------------
 6892|      1|               pppoe->id == s_id) {
  ------------------
  |  Branch (6892:16): [True: 1, False: 0]
  ------------------
 6893|      1|      MG_ERROR(("Got PADT"));
  ------------------
  |  | 1766|      1|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6894|      1|      s_id = 0;
 6895|      1|      s_lcpup = false;
 6896|      1|      s_state = MG_PPPoE_ST_DISC;
  ------------------
  |  | 6389|      1|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
 6897|      1|    }
 6898|     62|  } else if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_SESS &&
  ------------------
  |  Branch (6898:14): [True: 12, False: 50]
  ------------------
 6899|     12|             s_state == MG_PPPoE_ST_SESS) {
  ------------------
  |  | 6391|     12|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (6899:14): [True: 4, False: 8]
  ------------------
 6900|      4|    pay->buf = (char *) (pppoe + 1);
 6901|      4|    pay->len = pay->len - sizeof(*pppoe);
 6902|      4|    return ppp_rx(ifp, proto, pay, raw);
 6903|      4|  }
 6904|     70|  return false;
 6905|     75|}
mg_hexdump:
 7257|  2.66k|void mg_hexdump(const void *buf, size_t len) {
 7258|  2.66k|  const unsigned char *p = (const unsigned char *) buf;
 7259|  2.66k|  unsigned char ascii[16], alen = 0;
 7260|  2.66k|  size_t i;
 7261|  39.1k|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (7261:15): [True: 36.5k, False: 2.66k]
  ------------------
 7262|  36.5k|    if ((i % 16) == 0) {
  ------------------
  |  Branch (7262:9): [True: 2.66k, False: 33.8k]
  ------------------
 7263|       |      // Print buffered ascii chars
 7264|  2.66k|      if (i > 0)
  ------------------
  |  Branch (7264:11): [True: 0, False: 2.66k]
  ------------------
 7265|      0|        logs("  ", 2), logs((char *) ascii, 16), logs("\r\n", 2), alen = 0;
 7266|       |      // Print hex address, then \t
 7267|  2.66k|      logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
 7268|  2.66k|          logc(nibble((i >> 4) & 15)), logc('0'), logs("   ", 3);
 7269|  2.66k|    }
 7270|  36.5k|    logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15));  // Two nibbles, e.g. c5
 7271|  36.5k|    logc(' ');                                         // Space after hex number
 7272|  36.5k|    ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.';        // Add to the ascii buf
  ------------------
  |  | 7256|  36.5k|#define ISPRINT(x) ((x) >= ' ' && (x) <= '~')
  |  |  ------------------
  |  |  |  Branch (7256:21): [True: 25.3k, False: 11.2k]
  |  |  |  Branch (7256:35): [True: 18.2k, False: 7.08k]
  |  |  ------------------
  ------------------
 7273|  36.5k|  }
 7274|  8.77k|  while (alen < 16) logs("   ", 3), ascii[alen++] = ' ';
  ------------------
  |  Branch (7274:10): [True: 6.11k, False: 2.66k]
  ------------------
 7275|  2.66k|  logs("  ", 2), logs((char *) ascii, 16), logs("\r\n", 2);
 7276|  2.66k|}
mg_mdash_poll:
 7670|  5.56k|void mg_mdash_poll(struct mg_mgr *mgr) {
 7671|  5.56k|  (void) mgr;
 7672|  5.56k|}
mg_mqtt_next_prop:
 8113|  8.25k|                         size_t ofs) {
 8114|  8.25k|  uint8_t *props = (uint8_t *) msg->dgram.buf + msg->props_start;
 8115|  8.25k|  uint8_t *props_end = props + msg->props_size;
 8116|  8.25k|  uint8_t *i = props + ofs;
 8117|  8.25k|  size_t new_pos = ofs, len;
 8118|       |  
 8119|  8.25k|  if (msg->props_start > msg->dgram.len ||
  ------------------
  |  Branch (8119:7): [True: 0, False: 8.25k]
  ------------------
 8120|  8.25k|    msg->props_size > msg->dgram.len - msg->props_start ||
  ------------------
  |  Branch (8120:5): [True: 0, False: 8.25k]
  ------------------
 8121|  8.25k|    ofs >= msg->props_size)
  ------------------
  |  Branch (8121:5): [True: 1.95k, False: 6.29k]
  ------------------
 8122|  1.95k|  return 0;
 8123|       |
 8124|  6.29k|  memset(prop, 0, sizeof(struct mg_mqtt_prop));
 8125|  6.29k|  prop->id = i[0];
 8126|  6.29k|  i++, new_pos++;
 8127|       |
 8128|  6.29k|  switch (mqtt_prop_type_by_id(prop->id)) {
 8129|     45|    case MQTT_PROP_TYPE_STRING_PAIR:
  ------------------
  |  Branch (8129:5): [True: 45, False: 6.25k]
  ------------------
 8130|     45|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (8130:11): [True: 4, False: 41]
  ------------------
 8131|     41|      prop->key.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 8132|     41|      if (i + 2 + prop->key.len > props_end) return 0;
  ------------------
  |  Branch (8132:11): [True: 26, False: 15]
  ------------------
 8133|     15|      prop->key.buf = (char *) i + 2;
 8134|     15|      i += 2 + prop->key.len;
 8135|     15|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (8135:11): [True: 2, False: 13]
  ------------------
 8136|     13|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 8137|     13|      prop->val.buf = (char *) i + 2;
 8138|     13|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (8138:11): [True: 1, False: 12]
  ------------------
 8139|     12|      new_pos += 2 * sizeof(uint16_t) + prop->val.len + prop->key.len;
 8140|     12|      break;
 8141|  1.36k|    case MQTT_PROP_TYPE_BYTE:
  ------------------
  |  Branch (8141:5): [True: 1.36k, False: 4.93k]
  ------------------
 8142|  1.36k|      if (i + 1 > props_end) return 0;
  ------------------
  |  Branch (8142:11): [True: 5, False: 1.36k]
  ------------------
 8143|  1.36k|      prop->iv = (uint8_t) i[0];
 8144|  1.36k|      new_pos++;
 8145|  1.36k|      break;
 8146|    272|    case MQTT_PROP_TYPE_SHORT:
  ------------------
  |  Branch (8146:5): [True: 272, False: 6.02k]
  ------------------
 8147|    272|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (8147:11): [True: 4, False: 268]
  ------------------
 8148|    268|      prop->iv = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 8149|    268|      new_pos += sizeof(uint16_t);
 8150|    268|      break;
 8151|  3.83k|    case MQTT_PROP_TYPE_INT:
  ------------------
  |  Branch (8151:5): [True: 3.83k, False: 2.45k]
  ------------------
 8152|  3.83k|      if (i + 4 > props_end) return 0;
  ------------------
  |  Branch (8152:11): [True: 13, False: 3.82k]
  ------------------
 8153|  3.82k|      prop->iv = ((uint32_t) i[0] << 24) | ((uint32_t) i[1] << 16) |
 8154|  3.82k|                 ((uint32_t) i[2] << 8) | i[3];
 8155|  3.82k|      new_pos += sizeof(uint32_t);
 8156|  3.82k|      break;
 8157|     46|    case MQTT_PROP_TYPE_STRING:
  ------------------
  |  Branch (8157:5): [True: 46, False: 6.25k]
  ------------------
 8158|     46|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (8158:11): [True: 4, False: 42]
  ------------------
 8159|     42|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 8160|     42|      prop->val.buf = (char *) i + 2;
 8161|     42|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (8161:11): [True: 19, False: 23]
  ------------------
 8162|     23|      new_pos += 2 + prop->val.len;
 8163|     23|      break;
 8164|     42|    case MQTT_PROP_TYPE_BINARY_DATA:
  ------------------
  |  Branch (8164:5): [True: 42, False: 6.25k]
  ------------------
 8165|     42|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (8165:11): [True: 2, False: 40]
  ------------------
 8166|     40|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 8167|     40|      prop->val.buf = (char *) i + 2;
 8168|     40|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (8168:11): [True: 20, False: 20]
  ------------------
 8169|     20|      new_pos += 2 + prop->val.len;
 8170|     20|      break;
 8171|    586|    case MQTT_PROP_TYPE_VARIABLE_INT:
  ------------------
  |  Branch (8171:5): [True: 586, False: 5.71k]
  ------------------
 8172|    586|      len = decode_varint(i, (size_t) (props_end - i), &prop->iv);
 8173|    586|      if (i + len > props_end) return 0;
  ------------------
  |  Branch (8173:11): [True: 0, False: 586]
  ------------------
 8174|    586|      new_pos = (len == 0) ? 0 : new_pos + len;
  ------------------
  |  Branch (8174:17): [True: 9, False: 577]
  ------------------
 8175|    586|      break;
 8176|    100|    default:
  ------------------
  |  Branch (8176:5): [True: 100, False: 6.19k]
  ------------------
 8177|    100|      new_pos = 0;
 8178|    100|      break;
 8179|  6.29k|  }
 8180|       |
 8181|  6.19k|  return new_pos;
 8182|  6.29k|}
mg_mqtt_parse:
 8327|  22.2k|                  struct mg_mqtt_message *m) {
 8328|  22.2k|  uint8_t lc = 0, *p, *end;
 8329|  22.2k|  uint32_t n = 0, len_len = 0, tmp;
 8330|       |
 8331|  22.2k|  memset(m, 0, sizeof(*m));
 8332|  22.2k|  m->dgram.buf = (char *) buf;
 8333|  22.2k|  if (len < 2) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (8333:7): [True: 11.3k, False: 10.9k]
  ------------------
 8334|  10.9k|  m->cmd = (uint8_t) (buf[0] >> 4);
 8335|  10.9k|  m->qos = (buf[0] >> 1) & 3;
 8336|       |
 8337|  10.9k|  n = len_len = 0;
 8338|  10.9k|  p = (uint8_t *) buf + 1;
 8339|  13.0k|  while ((size_t) (p - buf) < len) {
  ------------------
  |  Branch (8339:10): [True: 12.8k, False: 118]
  ------------------
 8340|  12.8k|    lc = *((uint8_t *) p++);
 8341|  12.8k|    n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
 8342|  12.8k|    len_len++;
 8343|  12.8k|    if (!(lc & 0x80)) break;
  ------------------
  |  Branch (8343:9): [True: 10.5k, False: 2.31k]
  ------------------
 8344|  2.31k|    if (len_len >= 4) return MQTT_MALFORMED;
  ------------------
  |  Branch (8344:9): [True: 232, False: 2.08k]
  ------------------
 8345|  2.31k|  }
 8346|  10.7k|  end = p + n;
 8347|  10.7k|  if ((lc & 0x80) || (end > buf + len)) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (8347:7): [True: 118, False: 10.5k]
  |  Branch (8347:22): [True: 5.25k, False: 5.32k]
  ------------------
 8348|  5.32k|  m->dgram.len = (size_t) (end - buf);
 8349|       |
 8350|  5.32k|  switch (m->cmd) {
 8351|    610|    case MQTT_CMD_CONNACK:
  ------------------
  |  | 3492|    610|#define MQTT_CMD_CONNACK 2
  ------------------
  |  Branch (8351:5): [True: 610, False: 4.71k]
  ------------------
 8352|    610|      if (end - p < 2) return MQTT_MALFORMED;
  ------------------
  |  Branch (8352:11): [True: 112, False: 498]
  ------------------
 8353|    498|      m->ack = p[1];
 8354|    498|      p += 2;
 8355|    498|      if (version == 5) {
  ------------------
  |  Branch (8355:11): [True: 249, False: 249]
  ------------------
 8356|    249|        if (p >= end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8356:13): [True: 2, False: 247]
  ------------------
 8357|    247|        len_len = (uint32_t) decode_varint(p, (size_t) (end - p), &tmp);
 8358|    247|        if (!len_len) return MQTT_MALFORMED;
  ------------------
  |  Branch (8358:13): [True: 18, False: 229]
  ------------------
 8359|    229|        m->props_size = (size_t) tmp;
 8360|    229|        m->props_start = (size_t) (p + len_len - buf);
 8361|    229|        p += len_len + m->props_size;
 8362|    229|        if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8362:13): [True: 112, False: 117]
  ------------------
 8363|    229|      }
 8364|    366|      break;
 8365|  1.85k|    case MQTT_CMD_PUBACK:
  ------------------
  |  | 3494|  1.85k|#define MQTT_CMD_PUBACK 4
  ------------------
  |  Branch (8365:5): [True: 1.85k, False: 3.47k]
  ------------------
 8366|  2.34k|    case MQTT_CMD_PUBREC:
  ------------------
  |  | 3495|  2.34k|#define MQTT_CMD_PUBREC 5
  ------------------
  |  Branch (8366:5): [True: 494, False: 4.83k]
  ------------------
 8367|  2.43k|    case MQTT_CMD_PUBREL:
  ------------------
  |  | 3496|  2.43k|#define MQTT_CMD_PUBREL 6
  ------------------
  |  Branch (8367:5): [True: 88, False: 5.23k]
  ------------------
 8368|  2.88k|    case MQTT_CMD_PUBCOMP:
  ------------------
  |  | 3497|  2.88k|#define MQTT_CMD_PUBCOMP 7
  ------------------
  |  Branch (8368:5): [True: 448, False: 4.87k]
  ------------------
 8369|  2.94k|    case MQTT_CMD_SUBSCRIBE:
  ------------------
  |  | 3498|  2.94k|#define MQTT_CMD_SUBSCRIBE 8
  ------------------
  |  Branch (8369:5): [True: 68, False: 5.25k]
  ------------------
 8370|  3.10k|    case MQTT_CMD_SUBACK:
  ------------------
  |  | 3499|  3.10k|#define MQTT_CMD_SUBACK 9
  ------------------
  |  Branch (8370:5): [True: 154, False: 5.17k]
  ------------------
 8371|  3.12k|    case MQTT_CMD_UNSUBSCRIBE:
  ------------------
  |  | 3500|  3.12k|#define MQTT_CMD_UNSUBSCRIBE 10
  ------------------
  |  Branch (8371:5): [True: 26, False: 5.29k]
  ------------------
 8372|  3.13k|    case MQTT_CMD_UNSUBACK:
  ------------------
  |  | 3501|  3.13k|#define MQTT_CMD_UNSUBACK 11
  ------------------
  |  Branch (8372:5): [True: 4, False: 5.32k]
  ------------------
 8373|  3.13k|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8373:11): [True: 252, False: 2.88k]
  ------------------
 8374|  2.88k|      m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8375|  2.88k|      p += 2;
 8376|  2.88k|      break;
 8377|    662|    case MQTT_CMD_PUBLISH: {
  ------------------
  |  | 3493|    662|#define MQTT_CMD_PUBLISH 3
  ------------------
  |  Branch (8377:5): [True: 662, False: 4.66k]
  ------------------
 8378|    662|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8378:11): [True: 16, False: 646]
  ------------------
 8379|    646|      m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8380|    646|      m->topic.buf = (char *) p + 2;
 8381|    646|      p += 2 + m->topic.len;
 8382|    646|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8382:11): [True: 312, False: 334]
  ------------------
 8383|    334|      if (m->qos > 0) {
  ------------------
  |  Branch (8383:11): [True: 80, False: 254]
  ------------------
 8384|     80|        if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8384:13): [True: 6, False: 74]
  ------------------
 8385|     74|        m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8386|     74|        p += 2;
 8387|     74|      }
 8388|    328|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8388:11): [True: 0, False: 328]
  ------------------
 8389|    328|      if (version == 5 && p + 2 < end) {
  ------------------
  |  Branch (8389:11): [True: 164, False: 164]
  |  Branch (8389:27): [True: 159, False: 5]
  ------------------
 8390|    159|        len_len = (uint32_t) decode_varint(p, (size_t) (end - p), &tmp);
 8391|    159|        if (!len_len) return MQTT_MALFORMED;
  ------------------
  |  Branch (8391:13): [True: 7, False: 152]
  ------------------
 8392|    152|        m->props_size = (size_t) tmp;
 8393|    152|        m->props_start = (size_t) (p + len_len - buf);
 8394|    152|        p += len_len + m->props_size;
 8395|    152|      }
 8396|    321|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8396:11): [True: 7, False: 314]
  ------------------
 8397|    314|      m->data.buf = (char *) p;
 8398|    314|      m->data.len = (size_t) (end - p);
 8399|    314|      break;
 8400|    321|    }
 8401|    920|    default: break;
  ------------------
  |  Branch (8401:5): [True: 920, False: 4.40k]
  ------------------
 8402|  5.32k|  }
 8403|  4.48k|  return MQTT_OK;
 8404|  5.32k|}
mg_vprintf:
 8543|   397k|size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
 8544|   397k|  size_t old = c->send.len;
 8545|   397k|  size_t expected = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
 8546|   397k|  size_t actual = c->send.len - old;
 8547|   397k|  if (actual != expected) {
  ------------------
  |  Branch (8547:7): [True: 0, False: 397k]
  ------------------
 8548|      0|    mg_error(c, "OOM");
 8549|      0|    c->send.len = old;
 8550|      0|    actual = 0;
 8551|      0|  }
 8552|   397k|  return actual;
 8553|   397k|}
mg_printf:
 8555|   397k|size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
 8556|   397k|  size_t len = 0;
 8557|   397k|  va_list ap;
 8558|   397k|  va_start(ap, fmt);
 8559|   397k|  len = mg_vprintf(c, fmt, &ap);
 8560|       |  va_end(ap);
 8561|   397k|  return len;
 8562|   397k|}
mg_aton:
 8703|  5.56k|bool mg_aton(struct mg_str str, struct mg_addr *addr) {
 8704|  5.56k|  return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton_(str, addr);
  ------------------
  |  Branch (8704:10): [True: 0, False: 5.56k]
  |  Branch (8704:33): [True: 5.56k, False: 0]
  |  Branch (8704:56): [True: 0, False: 0]
  ------------------
 8705|  5.56k|}
mg_alloc_conn:
 8707|  5.56k|struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
 8708|  5.56k|  struct mg_connection *c =
 8709|  5.56k|      (struct mg_connection *) mg_calloc(1, sizeof(*c) + mgr->extraconnsize);
 8710|  5.56k|  if (c != NULL) {
  ------------------
  |  Branch (8710:7): [True: 5.56k, False: 0]
  ------------------
 8711|  5.56k|    c->mgr = mgr;
 8712|  5.56k|    c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
  ------------------
  |  |    7|  5.56k|#define MG_IO_SIZE (32 * 1024 * 1024)  // Big IO size for fast resizes
  ------------------
 8713|  5.56k|    c->id = ++mgr->nextid;
 8714|  5.56k|    MG_PROF_INIT(c);
 8715|  5.56k|  }
 8716|  5.56k|  return c;
 8717|  5.56k|}
mg_close_conn:
 8719|  5.56k|void mg_close_conn(struct mg_connection *c) {
 8720|  5.56k|  mg_resolve_cancel(c);  // Close any pending DNS query
 8721|  5.56k|  LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
  ------------------
  |  | 2105|  5.56k|  do {                                     \
  |  | 2106|  5.56k|    type_ **h = head_;                     \
  |  | 2107|  5.56k|    while (*h != (elem_)) h = &(*h)->next; \
  |  |  ------------------
  |  |  |  Branch (2107:12): [True: 0, False: 5.56k]
  |  |  ------------------
  |  | 2108|  5.56k|    *h = (elem_)->next;                    \
  |  | 2109|  5.56k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2109:12): [Folded, False: 5.56k]
  |  |  ------------------
  ------------------
 8722|  5.56k|  if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
  ------------------
  |  Branch (8722:7): [True: 0, False: 5.56k]
  ------------------
 8723|  5.56k|  if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
  ------------------
  |  Branch (8723:7): [True: 0, False: 5.56k]
  ------------------
 8724|       |  // Order of operations is important. `MG_EV_CLOSE` event must be fired
 8725|       |  // before we deallocate received data, see #1331
 8726|  5.56k|  mg_call(c, MG_EV_CLOSE, NULL);
 8727|  5.56k|  MG_DEBUG(("%lu %ld closed", c->id, c->fd));
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8728|  5.56k|  MG_PROF_DUMP(c);
 8729|  5.56k|  MG_PROF_FREE(c);
 8730|       |
 8731|  5.56k|  mg_tls_free(c);
 8732|  5.56k|  mg_iobuf_free(&c->recv);
 8733|  5.56k|  mg_iobuf_free(&c->send);
 8734|  5.56k|  mg_iobuf_free(&c->rtls);
 8735|  5.56k|  mg_bzero((unsigned char *) c, sizeof(*c));
 8736|  5.56k|  mg_free(c);
 8737|  5.56k|}
mg_connect_svc:
 8741|  5.56k|                                     mg_event_handler_t pfn, void *pfn_data) {
 8742|  5.56k|  struct mg_connection *c = NULL;
 8743|  5.56k|  if (url == NULL || url[0] == '\0') {
  ------------------
  |  Branch (8743:7): [True: 0, False: 5.56k]
  |  Branch (8743:22): [True: 0, False: 5.56k]
  ------------------
 8744|      0|    MG_ERROR(("null url"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8745|      0|#if MG_ENABLE_TCPIP
 8746|  5.56k|  } else if (mgr->ifp != NULL && mgr->ifp->state != MG_TCPIP_STATE_READY) {
  ------------------
  |  | 4763|  5.56k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (8746:14): [True: 5.56k, False: 0]
  |  Branch (8746:34): [True: 0, False: 5.56k]
  ------------------
 8747|      0|    MG_ERROR(("Network is down"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8748|      0|#endif
 8749|  5.56k|  } else if ((c = mg_alloc_conn(mgr)) == NULL) {
  ------------------
  |  Branch (8749:14): [True: 0, False: 5.56k]
  ------------------
 8750|      0|    MG_ERROR(("OOM"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8751|  5.56k|  } else {
 8752|  5.56k|    LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
  ------------------
  |  | 2092|  5.56k|  do {                                     \
  |  | 2093|  5.56k|    (elem_)->next = (*head_);              \
  |  | 2094|  5.56k|    *(head_) = (elem_);                    \
  |  | 2095|  5.56k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2095:12): [Folded, False: 5.56k]
  |  |  ------------------
  ------------------
 8753|  5.56k|    c->is_udp = (strncmp(url, "udp:", 4) == 0);
 8754|  5.56k|    c->fd = (void *) (size_t) MG_INVALID_SOCKET;
  ------------------
  |  | 1267|  5.56k|#define MG_INVALID_SOCKET (-1)
  ------------------
 8755|  5.56k|    c->fn = fn;
 8756|  5.56k|    c->is_client = true;
 8757|  5.56k|    c->fn_data = fn_data;
 8758|  5.56k|    c->is_tls = (mg_url_is_ssl(url) != 0);
 8759|  5.56k|    c->pfn = pfn;
 8760|  5.56k|    c->pfn_data = pfn_data;
 8761|  5.56k|    mg_call(c, MG_EV_OPEN, (void *) url);
 8762|  5.56k|    MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8763|  5.56k|    mg_resolve(c, url);
 8764|  5.56k|  }
 8765|  5.56k|  return c;
 8766|  5.56k|}
mg_mgr_free:
 8828|  5.56k|void mg_mgr_free(struct mg_mgr *mgr) {
 8829|  5.56k|  struct mg_connection *c;
 8830|  5.56k|  struct mg_timer *tmp, *t = mgr->timers;
 8831|  5.56k|  while (t != NULL) tmp = t->next, mg_free(t), t = tmp;
  ------------------
  |  Branch (8831:10): [True: 0, False: 5.56k]
  ------------------
 8832|  5.56k|  mgr->timers = NULL;  // Important. Next call to poll won't touch timers
 8833|  11.1k|  for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
  ------------------
  |  Branch (8833:24): [True: 5.56k, False: 5.56k]
  ------------------
 8834|       |#if MG_ENABLE_MDASH
 8835|       |  mg_mdash_free(mgr);  // Before the final poll, so mdash does not reconnect
 8836|       |#endif
 8837|  5.56k|  mg_mgr_poll(mgr, 0);
 8838|       |#if MG_ENABLE_FREERTOS_TCP
 8839|       |  FreeRTOS_DeleteSocketSet(mgr->ss);
 8840|       |#endif
 8841|  5.56k|  MG_DEBUG(("All connections closed"));
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8842|  5.56k|#if MG_ENABLE_EPOLL
 8843|  5.56k|  if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
  ------------------
  |  Branch (8843:7): [True: 5.56k, False: 0]
  ------------------
 8844|  5.56k|#endif
 8845|  5.56k|  mg_tls_ctx_free(mgr);
 8846|  5.56k|#if MG_ENABLE_TCPIP
 8847|  5.56k|  if (mgr->ifp) mg_tcpip_free(mgr->ifp);
  ------------------
  |  Branch (8847:7): [True: 5.56k, False: 0]
  ------------------
 8848|  5.56k|#endif
 8849|  5.56k|}
mg_mgr_init:
 8851|  5.56k|void mg_mgr_init(struct mg_mgr *mgr) {
 8852|  5.56k|  memset(mgr, 0, sizeof(*mgr));
 8853|  5.56k|#if MG_ENABLE_EPOLL
 8854|  5.56k|  if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
  ------------------
  |  Branch (8854:7): [True: 0, False: 5.56k]
  ------------------
 8855|  5.56k|    MG_ERROR(("epoll_create1 errno %d", errno));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8856|       |#else
 8857|       |  mgr->epoll_fd = -1;
 8858|       |#endif
 8859|       |#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
 8860|       |  // clang-format off
 8861|       |  { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
 8862|       |  // clang-format on
 8863|       |#elif MG_ENABLE_FREERTOS_TCP
 8864|       |  mgr->ss = FreeRTOS_CreateSocketSet();
 8865|       |#elif MG_ARCH == MG_ARCH_UNIX
 8866|       |  // Ignore SIGPIPE signal, so if client cancels the request, it
 8867|       |  // won't kill the whole process.
 8868|  5.56k|  signal(SIGPIPE, SIG_IGN);
 8869|       |#elif MG_ENABLE_TCPIP_DRIVER_INIT && defined(MG_TCPIP_DRIVER_INIT)
 8870|       |  MG_TCPIP_DRIVER_INIT(mgr);
 8871|       |#endif
 8872|       |#if MG_ENABLE_BSD_SOCKETS
 8873|       |  mgr->pipe.q = NULL;
 8874|       |#else
 8875|  5.56k|  mgr->pipe.fd = MG_INVALID_SOCKET;
  ------------------
  |  | 1267|  5.56k|#define MG_INVALID_SOCKET (-1)
  ------------------
 8876|  5.56k|#endif
 8877|  5.56k|  mgr->dnstimeout = 3000;
 8878|  5.56k|  mgr->dns4.url = "udp://8.8.8.8:53";
 8879|  5.56k|  mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
 8880|  5.56k|  mg_tls_ctx_init(mgr);
 8881|  5.56k|  MG_DEBUG(("MG_IO_SIZE: %lu, TLS: %s, conn size: %zu, mgr size: %zu",
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  |  Branch (1757:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1757:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1757:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1757:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, Folded]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8882|  5.56k|            MG_IO_SIZE,
 8883|  5.56k|            MG_TLS == MG_TLS_NONE      ? "none"
 8884|  5.56k|            : MG_TLS == MG_TLS_MBED    ? "MbedTLS"
 8885|  5.56k|            : MG_TLS == MG_TLS_OPENSSL ? "OpenSSL"
 8886|  5.56k|            : MG_TLS == MG_TLS_BUILTIN ? "builtin"
 8887|  5.56k|            : MG_TLS == MG_TLS_WOLFSSL ? "WolfSSL"
 8888|  5.56k|                                       : "custom",
 8889|  5.56k|            sizeof(struct mg_connection), sizeof(struct mg_mgr)));
 8890|       |#if MG_ENABLE_MDASH
 8891|       |  mg_mdash_init(mgr);
 8892|       |#endif
 8893|  5.56k|}
mg_tcpip_init:
11167|  5.56k|void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
11168|       |  // If L2 address is not set, make a random one; fill MTU
11169|  5.56k|  mg_l2_init(ifp);
11170|  5.56k|  ifp->mtu = ifp->l2mtu;
11171|  5.56k|  if (MG_ENABLE_TCPIP_TCPRTX) ifp->enable_tcp_retransmit = true;
  ------------------
  |  | 1304|  5.56k|#define MG_ENABLE_TCPIP_TCPRTX 0  // TCP retransmission queue
  |  |  ------------------
  |  |  |  Branch (1304:32): [Folded, False: 5.56k]
  |  |  ------------------
  ------------------
11172|       |
11173|  5.56k|  if (ifp->dhcp_name[0] == '\0')  // If DHCP name is not set, use "mip"
  ------------------
  |  Branch (11173:7): [True: 5.56k, False: 0]
  ------------------
11174|  5.56k|    memcpy(ifp->dhcp_name, "mip", 4);
11175|  5.56k|  ifp->dhcp_name[sizeof(ifp->dhcp_name) - 1] = '\0';  // Just in case
11176|       |
11177|  5.56k|  if (ifp->driver->init && !ifp->driver->init(ifp)) {
  ------------------
  |  Branch (11177:7): [True: 5.56k, False: 0]
  |  Branch (11177:28): [True: 0, False: 5.56k]
  ------------------
11178|      0|    MG_ERROR(("driver init failed"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11179|  5.56k|  } else {
11180|  5.56k|    ifp->tx.buf = (char *) mg_calloc(1, ifp->framesize),
11181|  5.56k|    ifp->tx.len = ifp->framesize;
11182|  5.56k|    if (ifp->recv_queue.size == 0)
  ------------------
  |  Branch (11182:9): [True: 5.56k, False: 0]
  ------------------
11183|  5.56k|      ifp->recv_queue.size = ifp->driver->rx ? ifp->framesize : 8192;
  ------------------
  |  Branch (11183:30): [True: 5.56k, False: 0]
  ------------------
11184|  5.56k|    ifp->recv_queue.buf = (char *) mg_calloc(1, ifp->recv_queue.size);
11185|  5.56k|    ifp->timer_1000ms = mg_millis();
11186|  5.56k|    mgr->ifp = ifp;
11187|  5.56k|    ifp->mgr = mgr;
11188|  5.56k|    mgr->extraconnsize = sizeof(struct connstate);
11189|  5.56k|    if (ifp->ip == 0 && ifp->l2type != MG_TCPIP_L2_PPP &&
  ------------------
  |  Branch (11189:9): [True: 0, False: 5.56k]
  |  Branch (11189:25): [True: 0, False: 0]
  ------------------
11190|      0|        ifp->l2type != MG_TCPIP_L2_PPPoE)
  ------------------
  |  Branch (11190:9): [True: 0, False: 0]
  ------------------
11191|      0|      ifp->enable_dhcp_client = true;
11192|  5.56k|    mg_random(&ifp->eport, sizeof(ifp->eport));  // Random from 0 to 65535
11193|  5.56k|    ifp->eport |= MG_EPHEMERAL_PORT_BASE;        // Random from
  ------------------
  |  | 8913|  5.56k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
11194|       |                                           // MG_EPHEMERAL_PORT_BASE to 65535
11195|  5.56k|    if (ifp->tx.buf == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (11195:9): [True: 0, False: 5.56k]
  |  Branch (11195:32): [True: 0, False: 5.56k]
  ------------------
11196|  5.56k|    MG_DEBUG(("Builtin TCP/IP init done. Queue size: %zu, extra conn size: %zu",
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11197|  5.56k|              ifp->recv_queue.size, mgr->extraconnsize));
11198|  5.56k|  }
11199|  5.56k|  mg_bsd_init(mgr);
11200|  5.56k|}
mg_tcpip_free:
11208|  5.56k|void mg_tcpip_free(struct mg_tcpip_if *ifp) {
11209|  5.56k|  while (ifp->mgr->conns != NULL) close_conn(ifp->mgr->conns); // TCP FIN wait
  ------------------
  |  Branch (11209:10): [True: 0, False: 5.56k]
  ------------------
11210|  5.56k|  mg_free(ifp->recv_queue.buf);
11211|  5.56k|  mg_free(ifp->tx.buf);
11212|  5.56k|  mg_free(ifp->dns4_url);
11213|  5.56k|}
mg_connect_resolved:
11232|  5.56k|void mg_connect_resolved(struct mg_connection *c) {
11233|  5.56k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
11234|  5.56k|  uint8_t *l2addr;
11235|  5.56k|  struct connstate *s = (struct connstate *) (c + 1);
11236|  5.56k|  s->retransmit = ifp->enable_tcp_retransmit;
11237|  5.56k|  s->txq.align = MG_TCPIP_TXQ_ALIGN;
  ------------------
  |  | 8938|  5.56k|#define MG_TCPIP_TXQ_ALIGN 1024  // Retransmit queue allocation quantum
  ------------------
11238|  5.56k|  c->is_resolving = 0;
11239|  5.56k|  if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 8913|  5.56k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
                if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 8913|      0|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
  |  Branch (11239:7): [True: 0, False: 5.56k]
  ------------------
11240|  5.56k|  c->loc.port = mg_htons(ifp->eport++);
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
11241|       |#if MG_ENABLE_IPV6
11242|       |  if (c->rem.is_ip6) {
11243|       |    if (c->rem.addr.ip6[0] == ifp->ip6ll[0]) {  // same local LAN, use ll
11244|       |      c->loc.addr.ip6[0] = ifp->ip6ll[0], c->loc.addr.ip6[1] = ifp->ip6ll[1];
11245|       |    } else {  // use global address
11246|       |      c->loc.addr.ip6[0] = ifp->ip6[0], c->loc.addr.ip6[1] = ifp->ip6[1];
11247|       |    }
11248|       |    c->loc.is_ip6 = true;
11249|       |  } else
11250|       |#endif
11251|  5.56k|  {
11252|  5.56k|    c->loc.addr.ip4 = ifp->ip;
11253|  5.56k|  }
11254|  5.56k|  MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
  ------------------
  |  | 1768|  5.56k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11255|  5.56k|            &c->rem));
11256|  5.56k|  mg_call(c, MG_EV_RESOLVE, NULL);
11257|  5.56k|  c->is_connecting = 1;
11258|  5.56k|  if (c->is_udp && (l2addr = tcpip_mapip(ifp, &c->rem)) != NULL) {
  ------------------
  |  Branch (11258:7): [True: 0, False: 5.56k]
  |  Branch (11258:20): [True: 0, False: 0]
  ------------------
11259|      0|    memcpy(s->mac, l2addr, sizeof(s->mac));
11260|      0|    l2addr_resolved(c);  // broadcast or multicast
11261|       |#if MG_ENABLE_IPV6
11262|       |  } else if (c->rem.is_ip6) {
11263|       |    if (match_prefix((uint8_t *) c->rem.addr.ip6, ifp->prefix,
11264|       |                     ifp->prefix_len)                       // same global LAN
11265|       |        || (c->rem.addr.ip6[0] == ifp->ip6ll[0]             // same local LAN
11266|       |            && !MG_IP6MATCH(c->rem.addr.ip6, ifp->gw6))) {  // and not gw
11267|       |      // If we're in the same LAN, fire a Neighbor Solicitation
11268|       |      MG_DEBUG(("%lu NS lookup...", c->id));
11269|       |      tx_ndp_ns(ifp, c->rem.addr.ip6, NULL);  // RFC-4861 4.3, requesting
11270|       |      settmout(c, MIP_TTYPE_ARP);
11271|       |      c->is_arplooking = 1;
11272|       |    } else if (ifp->gw6_ready) {
11273|       |      memcpy(s->mac, ifp->gw6mac, sizeof(s->mac));
11274|       |      l2addr_resolved(c);
11275|       |    } else {
11276|       |      mg_error(c, "No IPv6 gateway, can't connect");
11277|       |    }
11278|       |#endif
11279|  5.56k|  } else {
11280|  5.56k|    uint32_t rem_ip = c->rem.addr.ip4;
11281|  5.56k|    if (ifp->ip && MG_IPISLOCAL(ifp, rem_ip) &&
  ------------------
  |  | 9223|  11.1k|#define MG_IPISLOCAL(i, a) ((a & i->mask) == (i->ip & i->mask))
  |  |  ------------------
  |  |  |  Branch (9223:28): [True: 0, False: 5.56k]
  |  |  ------------------
  ------------------
  |  Branch (11281:9): [True: 5.56k, False: 0]
  ------------------
11282|      0|        rem_ip != ifp->gw) {  // skip if gw (onstatechange -> ARP)
  ------------------
  |  Branch (11282:9): [True: 0, False: 0]
  ------------------
11283|       |      // If we're in the same LAN, fire an ARP lookup.
11284|      0|      MG_DEBUG(("%lu ARP lookup...", c->id));
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11285|      0|      mg_tcpip_arp_request(ifp, rem_ip, NULL);
11286|      0|      settmout(c, MIP_TTYPE_ARP);
  ------------------
  |  | 8956|      0|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
11287|      0|      c->is_arplooking = 1;
11288|  5.56k|    } else if (ifp->gw_ready) {
  ------------------
  |  Branch (11288:16): [True: 5.56k, False: 0]
  ------------------
11289|  5.56k|      memcpy(s->mac, ifp->gwmac, sizeof(s->mac));
11290|  5.56k|      l2addr_resolved(c);
11291|  5.56k|    } else {
11292|      0|      mg_error(c, "No gateway, can't connect");
11293|      0|    }
11294|  5.56k|  }
11295|  5.56k|}
mg_mgr_poll:
11323|  5.56k|void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
11324|  5.56k|  struct mg_connection *c, *tmp;
11325|  5.56k|  uint64_t now = mg_millis();
11326|  5.56k|  mg_timer_poll(&mgr->timers, now);
11327|  5.56k|  mg_ota_poll(mgr);
11328|  5.56k|  mg_mdash_poll(mgr);
11329|  5.56k|  if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
  ------------------
  |  Branch (11329:7): [True: 0, False: 5.56k]
  |  Branch (11329:27): [True: 0, False: 5.56k]
  ------------------
11330|  5.56k|  mg_tcpip_poll(mgr->ifp, now);
11331|  11.1k|  for (c = mgr->conns; c != NULL; c = tmp) {
  ------------------
  |  Branch (11331:24): [True: 5.56k, False: 5.56k]
  ------------------
11332|  5.56k|    struct connstate *s = (struct connstate *) (c + 1);
11333|  5.56k|    long flush = 0;
11334|  5.56k|    bool is_tls = c->is_tls && !c->is_resolving && !c->is_arplooking &&
  ------------------
  |  Branch (11334:19): [True: 0, False: 5.56k]
  |  Branch (11334:32): [True: 0, False: 0]
  |  Branch (11334:52): [True: 0, False: 0]
  ------------------
11335|      0|                  !c->is_listening && !c->is_connecting;
  ------------------
  |  Branch (11335:19): [True: 0, False: 0]
  |  Branch (11335:39): [True: 0, False: 0]
  ------------------
11336|  5.56k|    tmp = c->next;
11337|  5.56k|    mg_call(c, MG_EV_POLL, &now);
11338|  5.56k|    MG_VERBOSE(("%lu .. %c%c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
  ------------------
  |  | 1769|  5.56k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11339|  5.56k|                c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
11340|  5.56k|                c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c',
11341|  5.56k|                s->is_closing ? 'F' : 'f', mg_tls_pending(c), c->rtls.len));
11342|  5.56k|    if (!c->is_closing) {
  ------------------
  |  Branch (11342:9): [True: 0, False: 5.56k]
  ------------------
11343|       |      // order is important, TLS conn close with > 1 record in buffer (below)
11344|      0|      if (is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
  ------------------
  |  Branch (11344:11): [True: 0, False: 0]
  |  Branch (11344:22): [True: 0, False: 0]
  |  Branch (11344:41): [True: 0, False: 0]
  ------------------
11345|      0|      c->is_tls_hs ? mg_tls_handshake(c) : handle_tls_recv(c);
  ------------------
  |  Branch (11345:7): [True: 0, False: 0]
  ------------------
11346|      0|      if (can_write(c)) write_conn(c);
  ------------------
  |  Branch (11346:11): [True: 0, False: 0]
  ------------------
11347|      0|      if (is_tls && c->send.len == 0) flush = mg_tls_flush(c);
  ------------------
  |  Branch (11347:11): [True: 0, False: 0]
  |  Branch (11347:21): [True: 0, False: 0]
  ------------------
11348|      0|    }
11349|  5.56k|    if (flush == MG_IO_ERR) proto_error(c, false, "tx err"); // should RST but
  ------------------
  |  Branch (11349:9): [True: 0, False: 5.56k]
  ------------------
11350|  5.56k|    if (c->is_draining && c->send.len == 0 &&
  ------------------
  |  Branch (11350:9): [True: 2.66k, False: 2.89k]
  |  Branch (11350:27): [True: 2.33k, False: 326]
  ------------------
11351|  2.33k|        (c->is_udp ||
  ------------------
  |  Branch (11351:10): [True: 0, False: 2.33k]
  ------------------
11352|  2.33k|         (flush == 0 && s->txq.len == 0 && s->ttype != MIP_TTYPE_FIN)))
  ------------------
  |  | 8958|  2.33k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (11352:11): [True: 2.33k, False: 0]
  |  Branch (11352:25): [True: 2.33k, False: 0]
  |  Branch (11352:44): [True: 2.33k, False: 0]
  ------------------
11353|  2.33k|      c->is_closing = 1;
11354|       |    // For non-TLS, close immediately upon completing the 3-way closure
11355|       |    // For TLS, handle any pending data (above) until MIP_TTYPE_FIN expires
11356|  5.56k|    if (s->twclosure &&
  ------------------
  |  Branch (11356:9): [True: 0, False: 5.56k]
  ------------------
11357|      0|        (!c->is_tls || (c->rtls.len == 0 && mg_tls_pending(c) == 0))) {
  ------------------
  |  Branch (11357:10): [True: 0, False: 0]
  |  Branch (11357:25): [True: 0, False: 0]
  |  Branch (11357:45): [True: 0, False: 0]
  ------------------
11358|      0|      s->is_closing = 1;
11359|  5.56k|    } else if (c->is_closing && !s->is_closing) {
  ------------------
  |  Branch (11359:16): [True: 5.56k, False: 0]
  |  Branch (11359:33): [True: 591, False: 4.96k]
  ------------------
11360|    591|      if (c->is_udp || c->is_listening || c->is_resolving || c->is_arplooking ||
  ------------------
  |  Branch (11360:11): [True: 0, False: 591]
  |  Branch (11360:24): [True: 0, False: 591]
  |  Branch (11360:43): [True: 0, False: 591]
  |  Branch (11360:62): [True: 0, False: 591]
  ------------------
11361|    591|          c->is_connecting) {
  ------------------
  |  Branch (11361:11): [True: 591, False: 0]
  ------------------
11362|    591|        close_conn(c);
11363|    591|        continue;
11364|    591|      } else if (s->ttype != MIP_TTYPE_FIN) {  // active TCP: initiate closure
  ------------------
  |  | 8958|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (11364:18): [True: 0, False: 0]
  ------------------
11365|      0|        size_t tx = tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp,
11366|      0|                           TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 9045|      0|#define TH_FIN 0x01
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 9049|      0|#define TH_ACK 0x10
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11367|      0|                           s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8930|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (11367:28): [True: 0, False: 0]
  ------------------
11368|      0|        if (tx == (size_t) -1) {
  ------------------
  |  Branch (11368:13): [True: 0, False: 0]
  ------------------
11369|      0|          s->is_closing = 1;
11370|      0|        } else if (tx > 0) {
  ------------------
  |  Branch (11370:20): [True: 0, False: 0]
  ------------------
11371|      0|          s->seq++;
11372|      0|          settmout(c, MIP_TTYPE_FIN);
  ------------------
  |  | 8958|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
11373|      0|        }  // else tx = 0, should recover later or we have worse problems
11374|      0|      }
11375|    591|    }
11376|  4.96k|    if (s->send_rst)  // proto_error requested TCP RST, send it and close
  ------------------
  |  Branch (11376:9): [True: 0, False: 4.96k]
  ------------------
11377|      0|      tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_RST,
  ------------------
  |  | 9047|      0|#define TH_RST 0x04
  ------------------
11378|      0|             mg_htonl(s->seq), 0, 0, NULL, 0);
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11379|  4.96k|    if (s->is_closing) close_conn(c);  // then removes the conn
  ------------------
  |  Branch (11379:9): [True: 4.96k, False: 0]
  ------------------
11380|  4.96k|  }
11381|  5.56k|  mg_bsd_poll(mgr);
11382|  5.56k|  (void) ms;
11383|  5.56k|}
mg_ota_poll:
11721|  5.56k|void mg_ota_poll(struct mg_mgr *mgr) {
11722|  5.56k|  static uint64_t t = 5000;  // Fire first time 5 sec after boot
11723|       |
11724|  5.56k|  static uint64_t feed_timer;  // Advances 500ms per tick; tracks elapsed time
11725|  5.56k|  if (MG_OTA_STATE_GET() == MG_OTA_FAILED &&
  ------------------
  |  | 4277|  5.56k|#define MG_OTA_STATE_GET() 0
  ------------------
  |  Branch (11725:7): [Folded, False: 5.56k]
  ------------------
11726|      0|      mg_timer_expired(&feed_timer, 500, mg_millis())) {
  ------------------
  |  Branch (11726:7): [True: 0, False: 0]
  ------------------
11727|      0|    if (feed_timer < (uint64_t) MG_OTA_ROLLBACK_TIMEOUT_SECONDS * 1000) {
  ------------------
  |  | 4288|      0|#define MG_OTA_ROLLBACK_TIMEOUT_SECONDS 120
  ------------------
  |  Branch (11727:9): [True: 0, False: 0]
  ------------------
11728|      0|      MG_OTA_ROLLBACK_TIMER_FEED();  // Feed watchdog every 500ms
11729|      0|    } else if (s_autocommit_ok) {
  ------------------
  |  Branch (11729:16): [True: 0, False: 0]
  ------------------
11730|      0|      MG_INFO(("Auto-committing firmware"));
  ------------------
  |  | 1767|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11731|      0|      MG_OTA_STATE_SET(MG_OTA_CONFIRMED);  // Stop feeding → IWDG resets cleanly
  ------------------
  |  | 4280|      0|#define MG_OTA_STATE_SET(val) (void) (val)
  ------------------
11732|      0|    } else {
11733|      0|      MG_INFO(("No commit confirmation, rolling back"));
  ------------------
  |  | 1767|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11734|       |      // Stop feeding → IWDG fires → resets into MG_OTA_FAILED → rollback
11735|      0|    }
11736|      0|  }
11737|       |
11738|  5.56k|  if (MG_OTA_URL != NULL &&
  ------------------
  |  | 4331|  5.56k|#define MG_OTA_URL NULL
  ------------------
  |  Branch (11738:7): [Folded, False: 5.56k]
  ------------------
11739|      0|      mg_timer_expired(&t, MG_OTA_PULL_INTERVAL_SECONDS * 1000, mg_millis())) {
  ------------------
  |  | 4357|      0|#define MG_OTA_PULL_INTERVAL_SECONDS 60
  ------------------
  |  Branch (11739:7): [True: 0, False: 0]
  ------------------
11740|      0|    mg_ota_url_check(mgr, MG_OTA_URL, MG_OTA_STATUS_FN);
  ------------------
  |  | 4331|      0|#define MG_OTA_URL NULL
  ------------------
                  mg_ota_url_check(mgr, MG_OTA_URL, MG_OTA_STATUS_FN);
  ------------------
  |  | 4342|      0|#define MG_OTA_STATUS_FN NULL
  ------------------
11741|      0|  }
11742|  5.56k|}
mg_pfn_iobuf_noresize:
14226|  17.5M|void mg_pfn_iobuf_noresize(char ch, void *param) {
14227|  17.5M|  mg_pfn_iobuf_private(ch, param, false);
14228|  17.5M|}
mg_pfn_iobuf:
14230|  25.9M|void mg_pfn_iobuf(char ch, void *param) {
14231|  25.9M|  mg_pfn_iobuf_private(ch, param, true);
14232|  25.9M|}
mg_vsnprintf:
14234|  1.83M|size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
14235|  1.83M|  struct mg_iobuf io = {0, 0, 0, 0};
14236|  1.83M|  size_t n;
14237|  1.83M|  io.buf = (uint8_t *) buf, io.size = len;
14238|  1.83M|  n = mg_vxprintf(mg_pfn_iobuf_noresize, &io, fmt, ap);
14239|  1.83M|  if (n < len) buf[n] = '\0';
  ------------------
  |  Branch (14239:7): [True: 1.83M, False: 1.21k]
  ------------------
14240|  1.83M|  return n;
14241|  1.83M|}
mg_snprintf:
14243|  1.83M|size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) {
14244|  1.83M|  va_list ap;
14245|  1.83M|  size_t n;
14246|  1.83M|  va_start(ap, fmt);
14247|  1.83M|  n = mg_vsnprintf(buf, len, fmt, &ap);
14248|       |  va_end(ap);
14249|  1.83M|  return n;
14250|  1.83M|}
mg_pfn_stdout:
14267|   199k|void mg_pfn_stdout(char c, void *param) {
14268|   199k|#if MG_ENABLE_POSIX_FS
14269|   199k|  putchar(c);
14270|   199k|#endif
14271|   199k|  (void) param, (void) c;
14272|   199k|}
mg_sntp_parse:
15249|  11.1k|int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
15250|  11.1k|  int64_t epoch_milliseconds = -1;
15251|  11.1k|  int mode = len > 0 ? buf[0] & 7 : 0;
  ------------------
  |  Branch (15251:14): [True: 5.56k, False: 5.56k]
  ------------------
15252|  11.1k|  int version = len > 0 ? (buf[0] >> 3) & 7 : 0;
  ------------------
  |  Branch (15252:17): [True: 5.56k, False: 5.56k]
  ------------------
15253|  11.1k|  if (len < 48) {
  ------------------
  |  Branch (15253:7): [True: 8.58k, False: 2.53k]
  ------------------
15254|  8.58k|    MG_ERROR(("%s", "corrupt packet"));
  ------------------
  |  | 1766|  8.58k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|  8.58k|  do {                      \
  |  |  |  | 1757|  8.58k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 8.58k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  8.58k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 8.58k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
15255|  8.58k|  } else if (mode != 4 && mode != 5) {
  ------------------
  |  Branch (15255:14): [True: 2.41k, False: 123]
  |  Branch (15255:27): [True: 2.21k, False: 199]
  ------------------
15256|  2.21k|    MG_ERROR(("%s", "not a server reply"));
  ------------------
  |  | 1766|  2.21k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|  2.21k|  do {                      \
  |  |  |  | 1757|  2.21k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 2.21k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  2.21k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 2.21k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
15257|  2.21k|  } else if (buf[1] == 0) {
  ------------------
  |  Branch (15257:14): [True: 3, False: 319]
  ------------------
15258|      3|    MG_ERROR(("%s", "server sent a kiss of death"));
  ------------------
  |  | 1766|      3|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      3|  do {                      \
  |  |  |  | 1757|      3|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  |  | 1758|      3|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
15259|    319|  } else if (version == 4 || version == 3) {
  ------------------
  |  Branch (15259:14): [True: 82, False: 237]
  |  Branch (15259:30): [True: 153, False: 84]
  ------------------
15260|       |    // int64_t ref = gettimestamp((uint32_t *) &buf[16]);
15261|    235|    int64_t origin_time = gettimestamp((uint32_t *) &buf[24]);
15262|    235|    int64_t receive_time = gettimestamp((uint32_t *) &buf[32]);
15263|    235|    int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]);
15264|    235|    int64_t now = (int64_t) mg_millis();
15265|    235|    int64_t latency = (now - origin_time) - (transmit_time - receive_time);
15266|    235|    epoch_milliseconds = transmit_time + latency / 2;
15267|    235|    mg_boot_timestamp_ms = (uint64_t) (epoch_milliseconds - now);
15268|    235|  } else {
15269|     84|    MG_ERROR(("unexpected version: %d", version));
  ------------------
  |  | 1766|     84|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|     84|  do {                      \
  |  |  |  | 1757|     84|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 84]
  |  |  |  |  ------------------
  |  |  |  | 1758|     84|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 84]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
15270|     84|  }
15271|  11.1k|  return epoch_milliseconds;
15272|  11.1k|}
mg_str_s:
16249|  2.36M|struct mg_str mg_str_s(const char *s) {
16250|  2.36M|  struct mg_str str;
16251|  2.36M|  str.buf = (char *) s, str.len = (s == NULL) ? 0 : strlen(s);
  ------------------
  |  Branch (16251:35): [True: 12.1k, False: 2.34M]
  ------------------
16252|  2.36M|  return str;
16253|  2.36M|}
mg_str_n:
16255|  4.97M|struct mg_str mg_str_n(const char *s, size_t n) {
16256|  4.97M|  struct mg_str str;
16257|  4.97M|  str.buf = (char *) s, str.len = n;
16258|  4.97M|  return str;
16259|  4.97M|}
mg_strcmp:
16288|  1.14M|int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
16289|  1.14M|  size_t i = 0;
16290|  1.88M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (16290:10): [True: 1.14M, False: 737k]
  |  Branch (16290:26): [True: 1.12M, False: 14.5k]
  ------------------
16291|  1.12M|    int c1 = str1.buf[i];
16292|  1.12M|    int c2 = str2.buf[i];
16293|  1.12M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (16293:9): [True: 379k, False: 748k]
  ------------------
16294|   748k|    if (c1 > c2) return 1;
  ------------------
  |  Branch (16294:9): [True: 9.71k, False: 738k]
  ------------------
16295|   738k|    i++;
16296|   738k|  }
16297|   751k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (16297:7): [True: 14.5k, False: 737k]
  ------------------
16298|   737k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (16298:7): [True: 13.2k, False: 724k]
  ------------------
16299|   724k|  return 0;
16300|   737k|}
mg_strcasecmp:
16302|  1.15M|int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) {
16303|  1.15M|  size_t i = 0;
16304|  1.84M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (16304:10): [True: 1.76M, False: 84.0k]
  |  Branch (16304:26): [True: 1.75M, False: 1.61k]
  ------------------
16305|  1.75M|    int c1 = mg_tolc(str1.buf[i]);
16306|  1.75M|    int c2 = mg_tolc(str2.buf[i]);
16307|  1.75M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (16307:9): [True: 247k, False: 1.51M]
  ------------------
16308|  1.51M|    if (c1 > c2) return 1;
  ------------------
  |  Branch (16308:9): [True: 823k, False: 687k]
  ------------------
16309|   687k|    i++;
16310|   687k|  }
16311|  85.6k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (16311:7): [True: 1.61k, False: 84.0k]
  ------------------
16312|  84.0k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (16312:7): [True: 26.4k, False: 57.5k]
  ------------------
16313|  57.5k|  return 0;
16314|  84.0k|}
mg_match:
16316|  5.65k|bool mg_match(struct mg_str s, struct mg_str p, struct mg_str *caps) {
16317|  5.65k|  size_t i = 0, j = 0, ni = 0, nj = 0;
16318|  5.65k|  if (caps) caps->buf = NULL, caps->len = 0;
  ------------------
  |  Branch (16318:7): [True: 0, False: 5.65k]
  ------------------
16319|   200M|  while (i < p.len || j < s.len) {
  ------------------
  |  Branch (16319:10): [True: 200M, False: 7.25k]
  |  Branch (16319:23): [True: 1.69k, False: 5.56k]
  ------------------
16320|   200M|    if (i < p.len && j < s.len &&
  ------------------
  |  Branch (16320:9): [True: 200M, False: 1.69k]
  |  Branch (16320:22): [True: 200M, False: 154]
  ------------------
16321|   200M|        (p.buf[i] == '?' ||
  ------------------
  |  Branch (16321:10): [True: 224k, False: 199M]
  ------------------
16322|   199M|         (p.buf[i] != '*' && p.buf[i] != '#' && s.buf[j] == p.buf[i]))) {
  ------------------
  |  Branch (16322:11): [True: 195M, False: 4.18M]
  |  Branch (16322:30): [True: 195M, False: 189k]
  |  Branch (16322:49): [True: 193M, False: 2.18M]
  ------------------
16323|   193M|      if (caps == NULL) {
  ------------------
  |  Branch (16323:11): [True: 193M, False: 0]
  ------------------
16324|   193M|      } else if (p.buf[i] == '?') {
  ------------------
  |  Branch (16324:18): [True: 0, False: 0]
  ------------------
16325|      0|        caps->buf = &s.buf[j], caps->len = 1;     // Finalize `?` cap
16326|      0|        caps++, caps->buf = NULL, caps->len = 0;  // Init next cap
16327|      0|      } else if (caps->buf != NULL && caps->len == 0) {
  ------------------
  |  Branch (16327:18): [True: 0, False: 0]
  |  Branch (16327:39): [True: 0, False: 0]
  ------------------
16328|      0|        caps->len = (size_t) (&s.buf[j] - caps->buf);  // Finalize current cap
16329|      0|        caps++, caps->len = 0, caps->buf = NULL;       // Init next cap
16330|      0|      }
16331|   193M|      i++, j++;
16332|   193M|    } else if (i < p.len && (p.buf[i] == '*' || p.buf[i] == '#')) {
  ------------------
  |  Branch (16332:16): [True: 6.56M, False: 1.69k]
  |  Branch (16332:30): [True: 4.18M, False: 2.37M]
  |  Branch (16332:49): [True: 189k, False: 2.18M]
  ------------------
16333|  4.37M|      if (caps && !caps->buf) caps->len = 0, caps->buf = &s.buf[j];  // Init cap
  ------------------
  |  Branch (16333:11): [True: 0, False: 4.37M]
  |  Branch (16333:19): [True: 0, False: 0]
  ------------------
16334|  4.37M|      ni = i++, nj = j + 1;
16335|  4.37M|    } else if (nj > 0 && nj <= s.len &&
  ------------------
  |  Branch (16335:16): [True: 2.18M, False: 0]
  |  Branch (16335:26): [True: 2.18M, False: 6]
  ------------------
16336|  2.18M|               ((ni < p.len && p.buf[ni] == '#') ||
  ------------------
  |  Branch (16336:18): [True: 2.18M, False: 0]
  |  Branch (16336:32): [True: 94.4k, False: 2.09M]
  ------------------
16337|  2.18M|                (j < s.len && s.buf[j] != '/'))) {
  ------------------
  |  Branch (16337:18): [True: 2.09M, False: 2]
  |  Branch (16337:31): [True: 2.09M, False: 82]
  ------------------
16338|  2.18M|      i = ni, j = nj;
16339|  2.18M|      if (caps && caps->buf == NULL && caps->len == 0) {
  ------------------
  |  Branch (16339:11): [True: 0, False: 2.18M]
  |  Branch (16339:19): [True: 0, False: 0]
  |  Branch (16339:40): [True: 0, False: 0]
  ------------------
16340|      0|        caps--, caps->len = 0;  // Restart previous cap
16341|      0|      }
16342|  2.18M|    } else {
16343|     90|      return false;
16344|     90|    }
16345|   200M|  }
16346|  5.56k|  if (caps && caps->buf && caps->len == 0) {
  ------------------
  |  Branch (16346:7): [True: 0, False: 5.56k]
  |  Branch (16346:15): [True: 0, False: 0]
  |  Branch (16346:28): [True: 0, False: 0]
  ------------------
16347|      0|    caps->len = (size_t) (&s.buf[j] - caps->buf);
16348|      0|  }
16349|  5.56k|  return true;
16350|  5.65k|}
mg_span:
16352|  2.43M|bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) {
16353|  2.43M|  if (s.len == 0 || s.buf == NULL) {
  ------------------
  |  Branch (16353:7): [True: 424k, False: 2.00M]
  |  Branch (16353:21): [True: 0, False: 2.00M]
  ------------------
16354|   424k|    return false;  // Empty string, nothing to span - fail
16355|  2.00M|  } else {
16356|  2.00M|    size_t len = 0;
16357|   541M|    while (len < s.len && s.buf[len] != sep) len++;  // Find separator
  ------------------
  |  Branch (16357:12): [True: 540M, False: 881k]
  |  Branch (16357:27): [True: 539M, False: 1.12M]
  ------------------
16358|  2.00M|    if (a) *a = mg_str_n(s.buf, len);                // Init a
  ------------------
  |  Branch (16358:9): [True: 2.00M, False: 0]
  ------------------
16359|  2.00M|    if (b) *b = mg_str_n(s.buf + len, s.len - len);  // Init b
  ------------------
  |  Branch (16359:9): [True: 2.00M, False: 0]
  ------------------
16360|  2.00M|    if (b && len < s.len) b->buf++, b->len--;        // Skip separator
  ------------------
  |  Branch (16360:9): [True: 2.00M, False: 0]
  |  Branch (16360:14): [True: 1.12M, False: 881k]
  ------------------
16361|  2.00M|    return true;
16362|  2.00M|  }
16363|  2.43M|}
mg_str_to_num:
16365|   137k|bool mg_str_to_num(struct mg_str str, int base, void *val, size_t val_len) {
16366|   137k|  size_t i = 0, ndigits = 0;
16367|   137k|  uint64_t max = val_len == sizeof(uint8_t)    ? 0xFF
  ------------------
  |  Branch (16367:18): [True: 99.2k, False: 38.1k]
  ------------------
16368|   137k|                 : val_len == sizeof(uint16_t) ? 0xFFFF
  ------------------
  |  Branch (16368:20): [True: 0, False: 38.1k]
  ------------------
16369|  38.1k|                 : val_len == sizeof(uint32_t) ? 0xFFFFFFFF
  ------------------
  |  Branch (16369:20): [True: 38.1k, False: 0]
  ------------------
16370|  38.1k|                                               : (uint64_t) ~0;
16371|   137k|  uint64_t result = 0;
16372|   137k|  if (max == (uint64_t) ~0 && val_len != sizeof(uint64_t)) return false;
  ------------------
  |  Branch (16372:7): [True: 0, False: 137k]
  |  Branch (16372:31): [True: 0, False: 0]
  ------------------
16373|   137k|  if (base == 0 && str.len >= 2) {
  ------------------
  |  Branch (16373:7): [True: 0, False: 137k]
  |  Branch (16373:20): [True: 0, False: 0]
  ------------------
16374|      0|    if (str.buf[i] == '0') {
  ------------------
  |  Branch (16374:9): [True: 0, False: 0]
  ------------------
16375|      0|      i++;
16376|      0|      base = str.buf[i] == 'b' ? 2 : str.buf[i] == 'x' ? 16 : 10;
  ------------------
  |  Branch (16376:14): [True: 0, False: 0]
  |  Branch (16376:38): [True: 0, False: 0]
  ------------------
16377|      0|      if (base != 10) ++i;
  ------------------
  |  Branch (16377:11): [True: 0, False: 0]
  ------------------
16378|      0|    } else {
16379|      0|      base = 10;
16380|      0|    }
16381|      0|  }
16382|   137k|  switch (base) {
16383|      0|    case 2:
  ------------------
  |  Branch (16383:5): [True: 0, False: 137k]
  ------------------
16384|      0|      while (i < str.len && (str.buf[i] == '0' || str.buf[i] == '1')) {
  ------------------
  |  Branch (16384:14): [True: 0, False: 0]
  |  Branch (16384:30): [True: 0, False: 0]
  |  Branch (16384:51): [True: 0, False: 0]
  ------------------
16385|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
16386|      0|        if (result > max / 2) return false;  // Overflow
  ------------------
  |  Branch (16386:13): [True: 0, False: 0]
  ------------------
16387|      0|        result *= 2;
16388|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (16388:13): [True: 0, False: 0]
  ------------------
16389|      0|        result += digit;
16390|      0|        i++, ndigits++;
16391|      0|      }
16392|      0|      break;
16393|      0|    case 10:
  ------------------
  |  Branch (16393:5): [True: 0, False: 137k]
  ------------------
16394|      0|      while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (16394:14): [True: 0, False: 0]
  |  Branch (16394:29): [True: 0, False: 0]
  |  Branch (16394:50): [True: 0, False: 0]
  ------------------
16395|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
16396|      0|        if (result > max / 10) return false;  // Overflow
  ------------------
  |  Branch (16396:13): [True: 0, False: 0]
  ------------------
16397|      0|        result *= 10;
16398|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (16398:13): [True: 0, False: 0]
  ------------------
16399|      0|        result += digit;
16400|      0|        i++, ndigits++;
16401|      0|      }
16402|      0|      break;
16403|   137k|    case 16:
  ------------------
  |  Branch (16403:5): [True: 137k, False: 0]
  ------------------
16404|  9.31M|      while (i < str.len) {
  ------------------
  |  Branch (16404:14): [True: 9.17M, False: 137k]
  ------------------
16405|  9.17M|        char c = str.buf[i];
16406|  9.17M|        uint64_t digit = (c >= '0' && c <= '9')   ? (uint64_t) (c - '0')
  ------------------
  |  Branch (16406:27): [True: 9.17M, False: 0]
  |  Branch (16406:39): [True: 8.97M, False: 197k]
  ------------------
16407|  9.17M|                         : (c >= 'A' && c <= 'F') ? (uint64_t) (c - '7')
  ------------------
  |  Branch (16407:29): [True: 197k, False: 0]
  |  Branch (16407:41): [True: 13.2k, False: 183k]
  ------------------
16408|   197k|                         : (c >= 'a' && c <= 'f') ? (uint64_t) (c - 'W')
  ------------------
  |  Branch (16408:29): [True: 183k, False: 0]
  |  Branch (16408:41): [True: 183k, False: 0]
  ------------------
16409|   183k|                                                  : (uint64_t) ~0;
16410|  9.17M|        if (digit == (uint64_t) ~0) break;
  ------------------
  |  Branch (16410:13): [True: 0, False: 9.17M]
  ------------------
16411|  9.17M|        if (result > max / 16) return false;  // Overflow
  ------------------
  |  Branch (16411:13): [True: 39, False: 9.17M]
  ------------------
16412|  9.17M|        result *= 16;
16413|  9.17M|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (16413:13): [True: 0, False: 9.17M]
  ------------------
16414|  9.17M|        result += digit;
16415|  9.17M|        i++, ndigits++;
16416|  9.17M|      }
16417|   137k|      break;
16418|   137k|    default: return false;
  ------------------
  |  Branch (16418:5): [True: 0, False: 137k]
  ------------------
16419|   137k|  }
16420|   137k|  if (ndigits == 0) return false;
  ------------------
  |  Branch (16420:7): [True: 0, False: 137k]
  ------------------
16421|   137k|  if (i != str.len) return false;
  ------------------
  |  Branch (16421:7): [True: 0, False: 137k]
  ------------------
16422|   137k|  if (val_len == 1) {
  ------------------
  |  Branch (16422:7): [True: 99.2k, False: 38.0k]
  ------------------
16423|  99.2k|    *((uint8_t *) val) = (uint8_t) result;
16424|  99.2k|  } else if (val_len == 2) {
  ------------------
  |  Branch (16424:14): [True: 0, False: 38.0k]
  ------------------
16425|      0|    *((uint16_t *) val) = (uint16_t) result;
16426|  38.0k|  } else if (val_len == 4) {
  ------------------
  |  Branch (16426:14): [True: 38.0k, False: 0]
  ------------------
16427|  38.0k|    *((uint32_t *) val) = (uint32_t) result;
16428|  38.0k|  } else {
16429|      0|    *((uint64_t *) val) = (uint64_t) result;
16430|      0|  }
16431|   137k|  return true;
16432|   137k|}
mg_timer_expired:
16454|  5.56k|bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
16455|  5.56k|  if (now + prd < *t) *t = 0;                    // Time wrapped? Reset timer
  ------------------
  |  Branch (16455:7): [True: 0, False: 5.56k]
  ------------------
16456|  5.56k|  if (*t == 0) *t = now + prd;                   // Firt poll? Set expiration
  ------------------
  |  Branch (16456:7): [True: 0, False: 5.56k]
  ------------------
16457|  5.56k|  if (*t > now) return false;                    // Not expired yet, return
  ------------------
  |  Branch (16457:7): [True: 0, False: 5.56k]
  ------------------
16458|  5.56k|  *t = (now - *t) > prd ? now + prd : *t + prd;  // Next expiration time
  ------------------
  |  Branch (16458:8): [True: 0, False: 5.56k]
  ------------------
16459|  5.56k|  return true;                                   // Expired, return true
16460|  5.56k|}
mg_timer_poll:
16462|  5.56k|void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
16463|  5.56k|  struct mg_timer *t, *tmp;
16464|  5.56k|  for (t = *head; t != NULL; t = tmp) {
  ------------------
  |  Branch (16464:19): [True: 0, False: 5.56k]
  ------------------
16465|      0|    bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
  ------------------
  |  | 1780|      0|#define MG_TIMER_RUN_NOW 2     // Call immediately when timer is set
  ------------------
  |  Branch (16465:17): [True: 0, False: 0]
  |  Branch (16465:35): [True: 0, False: 0]
  ------------------
16466|      0|                !(t->flags & MG_TIMER_CALLED);  // Handle MG_TIMER_NOW only once
  ------------------
  |  | 1781|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
  |  Branch (16466:17): [True: 0, False: 0]
  ------------------
16467|      0|    bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
16468|      0|    tmp = t->next;
16469|      0|    if (!once && !expired) continue;
  ------------------
  |  Branch (16469:9): [True: 0, False: 0]
  |  Branch (16469:18): [True: 0, False: 0]
  ------------------
16470|      0|    if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 1779|      0|#define MG_TIMER_REPEAT 1      // Call function periodically
  ------------------
                  if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 1781|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
  |  Branch (16470:9): [True: 0, False: 0]
  |  Branch (16470:41): [True: 0, False: 0]
  ------------------
16471|      0|      t->fn(t->arg);
16472|      0|    }
16473|      0|    t->flags |= MG_TIMER_CALLED;
  ------------------
  |  | 1781|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
16474|       |
16475|       |    // If this timer is not repeating and marked AUTODELETE, remove it
16476|      0|    if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
  ------------------
  |  | 1779|      0|#define MG_TIMER_REPEAT 1      // Call function periodically
  ------------------
                  if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
  ------------------
  |  | 1782|      0|#define MG_TIMER_AUTODELETE 8  // mg_free() timer when done
  ------------------
  |  Branch (16476:9): [True: 0, False: 0]
  |  Branch (16476:42): [True: 0, False: 0]
  ------------------
16477|      0|      mg_timer_free(head, t);
16478|      0|      mg_free(t);
16479|      0|    }
16480|      0|  }
16481|  5.56k|}
mg_tls_free:
21970|  5.56k|void mg_tls_free(struct mg_connection *c) {
21971|  5.56k|  (void) c;
21972|  5.56k|}
mg_tls_ctx_init:
21987|  5.56k|void mg_tls_ctx_init(struct mg_mgr *mgr) {
21988|  5.56k|  (void) mgr;
21989|  5.56k|}
mg_tls_ctx_free:
21990|  5.56k|void mg_tls_ctx_free(struct mg_mgr *mgr) {
21991|  5.56k|  (void) mgr;
21992|  5.56k|}
mg_url_is_ssl:
29302|  5.56k|bool mg_url_is_ssl(const char *url) {
29303|  5.56k|  return strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0 ||
  ------------------
  |  Branch (29303:10): [True: 0, False: 5.56k]
  |  Branch (29303:42): [True: 0, False: 5.56k]
  ------------------
29304|  5.56k|         strncmp(url, "mqtts:", 6) == 0 || strncmp(url, "ssl:", 4) == 0 ||
  ------------------
  |  Branch (29304:10): [True: 0, False: 5.56k]
  |  Branch (29304:44): [True: 0, False: 5.56k]
  ------------------
29305|  5.56k|         strncmp(url, "tls:", 4) == 0 || strncmp(url, "tcps:", 5) == 0;
  ------------------
  |  Branch (29305:10): [True: 0, False: 5.56k]
  |  Branch (29305:42): [True: 0, False: 5.56k]
  ------------------
29306|  5.56k|}
mg_url_host:
29336|  5.56k|struct mg_str mg_url_host(const char *url) {
29337|  5.56k|  struct url u = urlparse(url);
29338|  5.56k|  size_t n = u.port  ? u.port - u.host - 1
  ------------------
  |  Branch (29338:14): [True: 5.56k, False: 0]
  ------------------
29339|  5.56k|             : u.uri ? u.uri - u.host
  ------------------
  |  Branch (29339:16): [True: 0, False: 0]
  ------------------
29340|      0|                     : u.end - u.host;
29341|  5.56k|  struct mg_str s = mg_str_n(url + u.host, n);
29342|  5.56k|  return s;
29343|  5.56k|}
mg_url_port:
29350|  5.56k|unsigned short mg_url_port(const char *url) {
29351|  5.56k|  struct url u = urlparse(url);
29352|  5.56k|  unsigned short port = 0;
29353|  5.56k|  if (strncmp(url, "http:", 5) == 0 || strncmp(url, "ws:", 3) == 0) port = 80;
  ------------------
  |  Branch (29353:7): [True: 5.56k, False: 0]
  |  Branch (29353:40): [True: 0, False: 0]
  ------------------
29354|  5.56k|  if (strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0)
  ------------------
  |  Branch (29354:7): [True: 0, False: 5.56k]
  |  Branch (29354:39): [True: 0, False: 5.56k]
  ------------------
29355|      0|    port = 443;
29356|  5.56k|  if (strncmp(url, "mqtt:", 5) == 0) port = 1883;
  ------------------
  |  Branch (29356:7): [True: 0, False: 5.56k]
  ------------------
29357|  5.56k|  if (strncmp(url, "mqtts:", 6) == 0) port = 8883;
  ------------------
  |  Branch (29357:7): [True: 0, False: 5.56k]
  ------------------
29358|  5.56k|  if (u.port) port = (unsigned short) atoi(url + u.port);
  ------------------
  |  Branch (29358:7): [True: 5.56k, False: 0]
  ------------------
29359|  5.56k|  return port;
29360|  5.56k|}
mg_bzero:
29391|  36.4k|void mg_bzero(volatile unsigned char *buf, size_t len) {
29392|  36.4k|  if (buf != NULL) {
  ------------------
  |  Branch (29392:7): [True: 14.2k, False: 22.2k]
  ------------------
29393|   243G|    while (len--) *buf++ = 0;
  ------------------
  |  Branch (29393:12): [True: 243G, False: 14.2k]
  ------------------
29394|  14.2k|  }
29395|  36.4k|}
mg_random:
29423|  10.3k|bool mg_random(void *buf, size_t len) {
29424|  10.3k|  bool success = false;
29425|  10.3k|  unsigned char *p = (unsigned char *) buf;
29426|       |#if MG_ARCH == MG_ARCH_ESP32
29427|       |  while (len--) *p++ = (unsigned char) (esp_random() & 255);
29428|       |  success = true;
29429|       |#elif MG_ARCH == MG_ARCH_CUBE && defined(HAL_RNG_MODULE_ENABLED)
29430|       |  extern RNG_HandleTypeDef hrng;
29431|       |  success = true;
29432|       |  for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
29433|       |    uint32_t r = 0;
29434|       |    if (HAL_RNG_GenerateRandomNumber(&hrng, &r) != HAL_OK) success = false;
29435|       |    memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
29436|       |  }
29437|       |#elif MG_ARCH == MG_ARCH_PICOSDK
29438|       |  while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
29439|       |  success = true;
29440|       |#elif MG_ARCH == MG_ARCH_ZEPHYR
29441|       |#if MG_TLS == MG_TLS_BUILTIN ||                                    \
29442|       |    (MG_TLS == MG_TLS_MBED && (!defined(MBEDTLS_VERSION_NUMBER) || \
29443|       |                               MBEDTLS_VERSION_NUMBER < 0x04000000))
29444|       |  return (sys_csrand_get(buf, len) == 0);  // do not fallback on reseed error
29445|       |#else
29446|       |  sys_rand_get(buf, len);
29447|       |  success = true;
29448|       |#endif
29449|       |#elif MG_ARCH == MG_ARCH_WIN32
29450|       |#if defined(_MSC_VER) && _MSC_VER < 1700
29451|       |  static bool initialised = false;
29452|       |  static HCRYPTPROV hProv;
29453|       |  // CryptGenRandom() implementation earlier than 2008 is weak, see
29454|       |  // https://en.wikipedia.org/wiki/CryptGenRandom
29455|       |  if (!initialised) {
29456|       |    initialised = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
29457|       |                                      CRYPT_VERIFYCONTEXT);
29458|       |  }
29459|       |  if (initialised) success = CryptGenRandom(hProv, len, p);
29460|       |#else
29461|       |  size_t i;
29462|       |  for (i = 0; i < len; i++) {
29463|       |    unsigned int rand_v;
29464|       |    if (rand_s(&rand_v) == 0) {
29465|       |      p[i] = (unsigned char) (rand_v & 255);
29466|       |    } else {
29467|       |      break;
29468|       |    }
29469|       |  }
29470|       |  success = (i == len);
29471|       |#endif
29472|       |
29473|       |#elif MG_ARCH == MG_ARCH_UNIX
29474|       |  FILE *fp = fopen("/dev/urandom", "rb");
29475|  10.3k|  if (fp != NULL) {
  ------------------
  |  Branch (29475:7): [True: 10.3k, False: 0]
  ------------------
29476|  10.3k|    if (fread(buf, 1, len, fp) == len) success = true;
  ------------------
  |  Branch (29476:9): [True: 10.3k, False: 0]
  ------------------
29477|  10.3k|    fclose(fp);
29478|  10.3k|  }
29479|  10.3k|#endif
29480|       |  // If everything above did not work, fallback to a pseudo random generator
29481|  10.3k|  if (success == false) {
  ------------------
  |  Branch (29481:7): [True: 0, False: 10.3k]
  ------------------
29482|      0|    MG_ERROR(("Weak RNG: using rand()"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
29483|      0|    while (len--) *p++ = (unsigned char) (rand() & 255);
  ------------------
  |  Branch (29483:12): [True: 0, False: 0]
  ------------------
29484|      0|  }
29485|  10.3k|  return success;
29486|  10.3k|}
mg_crc32:
29502|   147k|uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
29503|   147k|  static const uint32_t crclut[16] = {
29504|       |      // table for polynomial 0xEDB88320 (reflected)
29505|   147k|      0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
29506|   147k|      0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
29507|   147k|      0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
29508|   147k|  crc = ~crc;
29509|  28.7M|  while (len--) {
  ------------------
  |  Branch (29509:10): [True: 28.6M, False: 147k]
  ------------------
29510|  28.6M|    uint8_t b = *(uint8_t *) buf++;
29511|  28.6M|    crc = crclut[(crc ^ b) & 0x0F] ^ (crc >> 4);
29512|  28.6M|    crc = crclut[(crc ^ (b >> 4)) & 0x0F] ^ (crc >> 4);
29513|  28.6M|  }
29514|   147k|  return ~crc;
29515|   147k|}
mg_crc16:
29517|  2.97k|uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len) {
29518|  2.97k|  static const uint16_t crclut[16] = {
29519|       |      // table for polynomial 0x8408 (reflected)
29520|  2.97k|      0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
29521|  2.97k|      0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F};
29522|  2.97k|  unsigned int c = (unsigned int) ~crc & 0xffff;
29523|   239k|  while (len--) {
  ------------------
  |  Branch (29523:10): [True: 236k, False: 2.97k]
  ------------------
29524|   236k|    uint8_t b = *(uint8_t *) buf++;
29525|   236k|    c = crclut[(c ^ b) & 0x0F] ^ (c >> 4);
29526|   236k|    c = crclut[(c ^ (b >> 4)) & 0x0F] ^ (c >> 4);
29527|   236k|  }
29528|  2.97k|  return (uint16_t) ~c;
29529|  2.97k|}
mg_path_is_sane:
29568|   367k|bool mg_path_is_sane(const struct mg_str path) {
29569|   367k|  const char *s = path.buf;
29570|   367k|  size_t n = path.len;
29571|   367k|  if (n == 0 || path.buf[0] == '\0') return true;
  ------------------
  |  Branch (29571:7): [True: 0, False: 367k]
  |  Branch (29571:17): [True: 0, False: 367k]
  ------------------
29572|   367k|  if (s[0] == '~') return false;  // Starts with ~
  ------------------
  |  Branch (29572:7): [True: 0, False: 367k]
  ------------------
29573|   367k|  if (s[0] == '.' && n > 1 && s[1] == '.')
  ------------------
  |  Branch (29573:7): [True: 367k, False: 0]
  |  Branch (29573:22): [True: 367k, False: 0]
  |  Branch (29573:31): [True: 0, False: 367k]
  ------------------
29574|      0|    return false;  // Starts with ..
29575|  5.19M|  for (; n > 0 && s[0] != '\0'; s++, n--) {
  ------------------
  |  Branch (29575:10): [True: 4.83M, False: 366k]
  |  Branch (29575:19): [True: 4.83M, False: 0]
  ------------------
29576|  4.83M|    if ((s[0] == '/' || s[0] == '\\') && n >= 2 && s[1] == '.' && n > 2 &&
  ------------------
  |  Branch (29576:10): [True: 4.27M, False: 559k]
  |  Branch (29576:25): [True: 6.75k, False: 552k]
  |  Branch (29576:42): [True: 3.92M, False: 354k]
  |  Branch (29576:52): [True: 26.2k, False: 3.89M]
  |  Branch (29576:67): [True: 26.1k, False: 79]
  ------------------
29577|  26.1k|        s[2] == '.')
  ------------------
  |  Branch (29577:9): [True: 648, False: 25.5k]
  ------------------
29578|    648|      return false;  // Subdir starts with ..
29579|  4.83M|  }
29580|   366k|  if (n > 0) return false;  // embedded nul (terminator not counted in len)
  ------------------
  |  Branch (29580:7): [True: 0, False: 366k]
  ------------------
29581|   366k|  return true;
29582|   366k|}
mg_millis:
29586|  11.3k|uint64_t mg_millis(void) {
29587|       |#if MG_ARCH == MG_ARCH_ESP32 || MG_ENABLE_FREERTOS
29588|       |  return xTaskGetTickCount() * portTICK_PERIOD_MS;
29589|       |#elif MG_ARCH == MG_ARCH_THREADX
29590|       |  return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
29591|       |#elif MG_ARCH == MG_ARCH_TIRTOS
29592|       |  return (uint64_t) Clock_getTicks();
29593|       |#elif MG_ARCH == MG_ARCH_ZEPHYR
29594|       |  return (uint64_t) k_uptime_get();
29595|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
29596|       |  return (uint64_t) rt_time_get();
29597|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
29598|       |  return (uint64_t) ((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
29599|       |#elif MG_ARCH == MG_ARCH_RTTHREAD
29600|       |  return (uint64_t) ((rt_tick_get() * 1000) / RT_TICK_PER_SECOND);
29601|       |#elif MG_ARCH == MG_ARCH_WIN32
29602|       |  return GetTickCount();
29603|       |#elif MG_ARCH == MG_ARCH_PICOSDK
29604|       |  return time_us_64() / 1000;
29605|       |#elif MG_ARCH == MG_ARCH_CUBE
29606|       |  return (uint64_t) HAL_GetTick();
29607|       |#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
29608|       |  // Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
29609|       |  // Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
29610|       |  return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
29611|       |#elif MG_ARCH == MG_ARCH_UNIX
29612|       |  struct timespec ts = {0, 0};
29613|       |  // See #1615 - prefer monotonic clock
29614|  11.3k|#if defined(CLOCK_MONOTONIC_RAW)
29615|       |  // Raw hardware-based time that is not subject to NTP adjustment
29616|  11.3k|  clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
29617|       |#elif defined(CLOCK_MONOTONIC)
29618|       |  // Affected by the incremental adjustments performed by adjtime and NTP
29619|       |  clock_gettime(CLOCK_MONOTONIC, &ts);
29620|       |#else
29621|       |  // Affected by discontinuous jumps in the system time and by the incremental
29622|       |  // adjustments performed by adjtime and NTP
29623|       |  clock_gettime(CLOCK_REALTIME, &ts);
29624|       |#endif
29625|  11.3k|  return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
29626|       |#elif defined(ARDUINO)
29627|       |  return (uint64_t) millis();
29628|       |#else
29629|       |  return (uint64_t) (time(NULL) * 1000);
29630|       |#endif
29631|  11.3k|}
mg_ntohs:
29635|  95.2k|uint16_t mg_ntohs(uint16_t net) {
29636|  95.2k|  return MG_LOAD_BE16(&net);
  ------------------
  |  | 1983|  95.2k|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|  95.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 1976|  95.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
29637|  95.2k|}
mg_ntohl:
29639|  12.5k|uint32_t mg_ntohl(uint32_t net) {
29640|  12.5k|  return MG_LOAD_BE32(&net);
  ------------------
  |  | 1988|  12.5k|  ((uint32_t) (((uint32_t) MG_U8P(p)[0] << 24U) | \
  |  |  ------------------
  |  |  |  | 1976|  12.5k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 1989|  12.5k|               ((uint32_t) MG_U8P(p)[1] << 16U) | \
  |  |  ------------------
  |  |  |  | 1976|  12.5k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 1990|  12.5k|               ((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
  |  |  ------------------
  |  |  |  | 1976|  12.5k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                              ((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
  |  |  ------------------
  |  |  |  | 1976|  12.5k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
29641|  12.5k|}
mg_calloc:
29655|  36.1k|void *mg_calloc(size_t count, size_t size) {
29656|  36.1k|  return calloc(count, size);
29657|  36.1k|}
mg_free:
29659|  63.9k|void mg_free(void *ptr) {
29660|  63.9k|  free(ptr);
29661|  63.9k|}
fuzz.c:_ZL23mg_base64_encode_singlei:
   27|   260M|static int mg_base64_encode_single(int c) {
   28|   260M|  if (c < 26) {
  ------------------
  |  Branch (28:7): [True: 154M, False: 106M]
  ------------------
   29|   154M|    return c + 'A';
   30|   154M|  } else if (c < 52) {
  ------------------
  |  Branch (30:14): [True: 84.0M, False: 22.7M]
  ------------------
   31|  84.0M|    return c - 26 + 'a';
   32|  84.0M|  } else if (c < 62) {
  ------------------
  |  Branch (32:14): [True: 19.6M, False: 3.06M]
  ------------------
   33|  19.6M|    return c - 52 + '0';
   34|  19.6M|  } else {
   35|  3.06M|    return c == 62 ? '+' : '/';
  ------------------
  |  Branch (35:12): [True: 354k, False: 2.71M]
  ------------------
   36|  3.06M|  }
   37|   260M|}
fuzz.c:_ZL23mg_base64_decode_singlei:
   57|  2.76M|static int mg_base64_decode_single(int c) {
   58|  2.76M|  return base64_decode_single(c, '+', '/');
   59|  2.76M|}
fuzz.c:_ZL20base64_decode_singleicc:
   39|  2.76M|static int base64_decode_single(int c, char plus, char slash) {
   40|  2.76M|  if (c >= 'A' && c <= 'Z') {
  ------------------
  |  Branch (40:7): [True: 117k, False: 2.65M]
  |  Branch (40:19): [True: 11.8k, False: 105k]
  ------------------
   41|  11.8k|    return c - 'A';
   42|  2.75M|  } else if (c >= 'a' && c <= 'z') {
  ------------------
  |  Branch (42:14): [True: 104k, False: 2.65M]
  |  Branch (42:26): [True: 103k, False: 762]
  ------------------
   43|   103k|    return c + 26 - 'a';
   44|  2.65M|  } else if (c >= '0' && c <= '9') {
  ------------------
  |  Branch (44:14): [True: 2.63M, False: 17.1k]
  |  Branch (44:26): [True: 2.63M, False: 2.76k]
  ------------------
   45|  2.63M|    return c + 52 - '0';
   46|  2.63M|  } else if (c == plus) {
  ------------------
  |  Branch (46:14): [True: 1.86k, False: 18.0k]
  ------------------
   47|  1.86k|    return 62;
   48|  18.0k|  } else if (c == slash) {
  ------------------
  |  Branch (48:14): [True: 4.83k, False: 13.2k]
  ------------------
   49|  4.83k|    return 63;
   50|  13.2k|  } else if (c == '=') {
  ------------------
  |  Branch (50:14): [True: 585, False: 12.6k]
  ------------------
   51|    585|    return 64;
   52|  12.6k|  } else {
   53|  12.6k|    return -1;
   54|  12.6k|  }
   55|  2.76M|}
fuzz.c:_ZL17mg_dns_parse_namePKhmmPcm:
 2099|  1.02k|                                char *dst, size_t dstlen) {
 2100|  1.02k|  return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0, 0);
 2101|  1.02k|}
fuzz.c:_ZL23mg_dns_parse_name_depthPKhmmPcmmi:
 2063|  1.58k|                                      int depth) {
 2064|  1.58k|  size_t i = 0;
 2065|  1.58k|  if (tolen > 0 && depth == 0) to[0] = '\0';
  ------------------
  |  Branch (2065:7): [True: 625, False: 959]
  |  Branch (2065:20): [True: 399, False: 226]
  ------------------
 2066|  1.58k|  if (depth > 5) return 0;
  ------------------
  |  Branch (2066:7): [True: 13, False: 1.57k]
  ------------------
 2067|       |  // MG_INFO(("ofs %lx %x %x", (unsigned long) ofs, s[ofs], s[ofs + 1]));
 2068|  4.85k|  while (ofs + i + 1 < len) {
  ------------------
  |  Branch (2068:10): [True: 4.77k, False: 79]
  ------------------
 2069|  4.77k|    size_t n = s[ofs + i];
 2070|  4.77k|    if (n == 0) {
  ------------------
  |  Branch (2070:9): [True: 451, False: 4.32k]
  ------------------
 2071|    451|      i++;
 2072|    451|      break;
 2073|    451|    }
 2074|  4.32k|    if (n & 0xc0) {
  ------------------
  |  Branch (2074:9): [True: 1.00k, False: 3.31k]
  ------------------
 2075|  1.00k|      size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]);  // 12 is hdr len
 2076|       |      // MG_INFO(("PTR %lx", (unsigned long) ptr));
 2077|  1.00k|      if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
  ------------------
  |  Branch (2077:11): [True: 622, False: 385]
  |  Branch (2077:28): [True: 564, False: 58]
  ------------------
 2078|    564|          mg_dns_parse_name_depth(s, len, ptr, to, tolen, j, depth + 1) == 0)
  ------------------
  |  Branch (2078:11): [True: 92, False: 472]
  ------------------
 2079|     92|        return 0;
 2080|    915|      i += 2;
 2081|    915|      break;
 2082|  1.00k|    }
 2083|  3.31k|    if (ofs + i + n + 1 >= len) return 0;
  ------------------
  |  Branch (2083:9): [True: 34, False: 3.28k]
  ------------------
 2084|  3.28k|    if (j > 0) {
  ------------------
  |  Branch (2084:9): [True: 2.92k, False: 361]
  ------------------
 2085|  2.92k|      if (j < tolen) to[j] = '.';
  ------------------
  |  Branch (2085:11): [True: 758, False: 2.16k]
  ------------------
 2086|  2.92k|      j++;
 2087|  2.92k|    }
 2088|  3.28k|    if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
  ------------------
  |  Branch (2088:9): [True: 907, False: 2.37k]
  ------------------
 2089|  3.28k|    j += n;
 2090|  3.28k|    i += n + 1;
 2091|  3.28k|    if (j < tolen) to[j] = '\0';  // Zero-terminate this chunk
  ------------------
  |  Branch (2091:9): [True: 907, False: 2.37k]
  ------------------
 2092|       |    // MG_INFO(("--> [%s]", to));
 2093|  3.28k|  }
 2094|  1.44k|  if (tolen > 0) to[tolen - 1] = '\0';  // Make sure it is nul-term
  ------------------
  |  Branch (2094:7): [True: 625, False: 820]
  ------------------
 2095|  1.44k|  return i;
 2096|  1.57k|}
fuzz.c:_ZL8is_digiti:
 2981|  2.75M|static bool is_digit(int c) {
 2982|  2.75M|  return c >= '0' && c <= '9';
  ------------------
  |  Branch (2982:10): [True: 2.38M, False: 372k]
  |  Branch (2982:22): [True: 794k, False: 1.58M]
  ------------------
 2983|  2.75M|}
fuzz.c:_ZL6mg_lldPclbb:
 3088|   794k|static size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
 3089|   794k|  const char *letters = "0123456789abcdef";
 3090|   794k|  uint64_t v = (uint64_t) val;
 3091|   794k|  size_t s = 0, n, i;
 3092|   794k|  if (is_signed && val < 0) buf[s++] = '-', v = (uint64_t) (-val);
  ------------------
  |  Branch (3092:7): [True: 397k, False: 397k]
  |  Branch (3092:20): [True: 0, False: 397k]
  ------------------
 3093|       |  // This loop prints a number in reverse order. I guess this is because we
 3094|       |  // write numbers from right to left: least significant digit comes last.
 3095|       |  // Maybe because we use Arabic numbers, and Arabs write RTL?
 3096|   794k|  if (is_hex) {
  ------------------
  |  Branch (3096:7): [True: 0, False: 794k]
  ------------------
 3097|      0|    for (n = 0; v; v >>= 4) buf[s + n++] = letters[v & 15];
  ------------------
  |  Branch (3097:17): [True: 0, False: 0]
  ------------------
 3098|   794k|  } else {
 3099|  2.78M|    for (n = 0; v; v /= 10) buf[s + n++] = letters[v % 10];
  ------------------
  |  Branch (3099:17): [True: 1.98M, False: 794k]
  ------------------
 3100|   794k|  }
 3101|       |  // Reverse a string
 3102|  1.58M|  for (i = 0; i < n / 2; i++) {
  ------------------
  |  Branch (3102:15): [True: 794k, False: 794k]
  ------------------
 3103|   794k|    char t = buf[s + i];
 3104|   794k|    buf[s + i] = buf[s + n - i - 1], buf[s + n - i - 1] = t;
 3105|   794k|  }
 3106|   794k|  if (val == 0) buf[n++] = '0';  // Handle special case
  ------------------
  |  Branch (3106:7): [True: 0, False: 794k]
  ------------------
 3107|   794k|  return n + s;
 3108|   794k|}
fuzz.c:_ZL4scpyPFvcPvES_Pcm:
 3111|  5.93M|                   size_t len) {
 3112|  5.93M|  size_t i = 0;
 3113|  15.1M|  while (i < len && buf[i] != '\0') out(buf[i++], ptr);
  ------------------
  |  Branch (3113:10): [True: 9.20M, False: 5.93M]
  |  Branch (3113:21): [True: 9.20M, False: 0]
  ------------------
 3114|  5.93M|  return i;
 3115|  5.93M|}
fuzz.c:_ZL6p_statPKcPmPl:
 3591|  1.07M|static int p_stat(const char *path, size_t *size, time_t *mtime) {
 3592|       |#if !defined(S_ISDIR)
 3593|       |  MG_ERROR(("stat() API is not supported. %p %p %p", path, size, mtime));
 3594|       |  return 0;
 3595|       |#else
 3596|       |#if MG_ARCH == MG_ARCH_WIN32
 3597|       |  struct _stati64 st;
 3598|       |  wchar_t tmp[MG_PATH_MAX];
 3599|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
 3600|       |  if (_wstati64(tmp, &st) != 0) return 0;
 3601|       |  // If path is a symlink, windows reports 0 in st.st_size.
 3602|       |  // Get a real file size by opening it and jumping to the end
 3603|       |  if (st.st_size == 0 && (st.st_mode & _S_IFREG)) {
 3604|       |    FILE *fp = _wfopen(tmp, L"rb");
 3605|       |    if (fp != NULL) {
 3606|       |      fseek(fp, 0, SEEK_END);
 3607|       |      if (ftell(fp) > 0) st.st_size = ftell(fp);  // Use _ftelli64 on win10+
 3608|       |      fclose(fp);
 3609|       |    }
 3610|       |  }
 3611|       |#else
 3612|  1.07M|  struct MG_STAT_STRUCT st;
 3613|  1.07M|  if (MG_STAT_FUNC(path, &st) != 0) return 0;
  ------------------
  |  | 3584|  1.07M|#define MG_STAT_FUNC stat
  ------------------
  |  Branch (3613:7): [True: 1.07M, False: 2.36k]
  ------------------
 3614|  2.36k|#endif
 3615|  2.36k|  if (size) *size = (size_t) st.st_size;
  ------------------
  |  Branch (3615:7): [True: 0, False: 2.36k]
  ------------------
 3616|  2.36k|  if (mtime) *mtime = st.st_mtime;
  ------------------
  |  Branch (3616:7): [True: 0, False: 2.36k]
  ------------------
 3617|  2.36k|  return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
  ------------------
  |  Branch (3617:38): [True: 2.36k, False: 0]
  ------------------
 3618|  1.07M|#endif
 3619|  1.07M|}
fuzz.c:_ZL6p_openPKci:
 3752|  12.1k|static void *p_open(const char *path, int flags) {
 3753|       |#if MG_ARCH == MG_ARCH_WIN32
 3754|       |  const char *mode = flags == MG_FS_READ    ? "rb"
 3755|       |                     : (flags & MG_FS_EXCL) ? "wxb"
 3756|       |                                            : "a+b";
 3757|       |  wchar_t b1[MG_PATH_MAX], b2[10];
 3758|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
 3759|       |  MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
 3760|       |  return (void *) _wfopen(b1, b2);
 3761|       |#else
 3762|  12.1k|  const char *mode = flags == MG_FS_READ    ? "rbe"
  ------------------
  |  Branch (3762:22): [True: 12.1k, False: 0]
  ------------------
 3763|  12.1k|                     : (flags & MG_FS_EXCL) ? "wxbe"
  ------------------
  |  Branch (3763:24): [True: 0, False: 0]
  ------------------
 3764|      0|                                            : "a+be"; // e for CLOSEXEC
 3765|  12.1k|  return (void *) fopen(path, mode);
 3766|  12.1k|#endif
 3767|  12.1k|}
fuzz.c:_ZL11mg_ncasecmpPKcS0_m:
 4001|  1.54M|static int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
 4002|  1.54M|  int diff = 0;
 4003|  5.43M|  if (len > 0) do {
  ------------------
  |  Branch (4003:7): [True: 1.54M, False: 0]
  ------------------
 4004|  5.43M|      int c = *s1++, d = *s2++;
 4005|  5.43M|      if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
  ------------------
  |  Branch (4005:11): [True: 4.23M, False: 1.20M]
  |  Branch (4005:23): [True: 1.64M, False: 2.59M]
  ------------------
 4006|  5.43M|      if (d >= 'A' && d <= 'Z') d += 'a' - 'A';
  ------------------
  |  Branch (4006:11): [True: 4.24M, False: 1.18M]
  |  Branch (4006:23): [True: 3.88M, False: 359k]
  ------------------
 4007|  5.43M|      diff = c - d;
 4008|  5.43M|    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
  ------------------
  |  Branch (4008:14): [True: 4.33M, False: 1.10M]
  |  Branch (4008:27): [True: 4.33M, False: 0]
  |  Branch (4008:45): [True: 3.89M, False: 441k]
  ------------------
 4009|  1.54M|  return diff;
 4010|  1.54M|}
fuzz.c:_ZL3isxi:
 4147|   206k|static bool isx(int c) {
 4148|   206k|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (4148:11): [True: 204k, False: 2.52k]
  |  Branch (4148:23): [True: 2.55k, False: 201k]
  |  Branch (4148:37): [True: 186k, False: 17.6k]
  |  Branch (4148:49): [True: 183k, False: 2.97k]
  ------------------
 4149|  20.6k|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (4149:11): [True: 18.0k, False: 2.58k]
  |  Branch (4149:23): [True: 15.0k, False: 2.99k]
  ------------------
 4150|   206k|}
fuzz.c:_ZL4isokh:
 4175|   165M|static bool isok(uint8_t c) {
 4176|   165M|  return c == '\n' || c == '\r' || c == '\t' || c >= ' ';
  ------------------
  |  Branch (4176:10): [True: 972k, False: 164M]
  |  Branch (4176:23): [True: 29.8k, False: 164M]
  |  Branch (4176:36): [True: 84.6k, False: 164M]
  |  Branch (4176:49): [True: 164M, False: 3.62k]
  ------------------
 4177|   165M|}
fuzz.c:_ZL4clenPKcS0_:
 4204|  62.8M|static size_t clen(const char *s, const char *end) {
 4205|  62.8M|  const unsigned char *u = (unsigned char *) s, c = *u;
 4206|  62.8M|  long n = (long) (end - s);
 4207|  62.8M|  if (c > ' ' && c <= '~') return 1;  // Usual ascii printed char
  ------------------
  |  Branch (4207:7): [True: 62.0M, False: 786k]
  |  Branch (4207:18): [True: 62.0M, False: 41.4k]
  ------------------
 4208|   828k|  if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2;  // 2-byte UTF8
  ------------------
  |  Branch (4208:7): [True: 10.8k, False: 817k]
  |  Branch (4208:29): [True: 10.8k, False: 0]
  |  Branch (4208:38): [True: 6.16k, False: 4.64k]
  ------------------
 4209|   822k|  if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
  ------------------
  |  Branch (4209:7): [True: 15.2k, False: 806k]
  |  Branch (4209:29): [True: 15.2k, False: 0]
  |  Branch (4209:38): [True: 13.9k, False: 1.36k]
  |  Branch (4209:51): [True: 12.0k, False: 1.91k]
  ------------------
 4210|   810k|  if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
  ------------------
  |  Branch (4210:7): [True: 12.4k, False: 797k]
  |  Branch (4210:29): [True: 10.4k, False: 2.07k]
  |  Branch (4210:38): [True: 6.49k, False: 3.90k]
  |  Branch (4210:51): [True: 5.20k, False: 1.29k]
  |  Branch (4210:64): [True: 3.82k, False: 1.37k]
  ------------------
 4211|  3.82k|    return 4;
 4212|   806k|  return 0;
 4213|   810k|}
fuzz.c:_ZL3vcbh:
 4199|  62.1k|static bool vcb(uint8_t c) {
 4200|  62.1k|  return (c & 0xc0) == 0x80;
 4201|  62.1k|}
fuzz.c:_ZL8skiptornPKcS0_P6mg_str:
 4216|   476k|static const char *skiptorn(const char *s, const char *end, struct mg_str *v) {
 4217|   476k|  v->buf = (char *) s;
 4218|  44.0M|  while (s < end && s[0] != '\n' && s[0] != '\r') s++, v->len++;  // To newline
  ------------------
  |  Branch (4218:10): [True: 44.0M, False: 0]
  |  Branch (4218:21): [True: 43.6M, False: 453k]
  |  Branch (4218:37): [True: 43.6M, False: 23.0k]
  ------------------
 4219|   476k|  if (s >= end || (s[0] == '\r' && s[1] != '\n')) return NULL;    // Stray \r
  ------------------
  |  Branch (4219:7): [True: 0, False: 476k]
  |  Branch (4219:20): [True: 23.0k, False: 453k]
  |  Branch (4219:36): [True: 304, False: 22.7k]
  ------------------
 4220|   475k|  if (s < end && s[0] == '\r') s++;                               // Skip \r
  ------------------
  |  Branch (4220:7): [True: 475k, False: 0]
  |  Branch (4220:18): [True: 22.7k, False: 453k]
  ------------------
 4221|   475k|  if (s >= end || *s++ != '\n') return NULL;                      // Skip \n
  ------------------
  |  Branch (4221:7): [True: 0, False: 475k]
  |  Branch (4221:19): [True: 0, False: 475k]
  ------------------
 4222|   475k|  return s;
 4223|   475k|}
fuzz.c:_ZL21mg_http_parse_headersPKcS0_P14mg_http_headerm:
 4226|   401k|                                  struct mg_http_header *h, size_t max_hdrs) {
 4227|   401k|  size_t i, n;
 4228|   401k|  int cl_count = 0, te_count = 0, auth_count = 0;
 4229|   401k|  int conn_count = 0, cookie_count = 0;
 4230|   475k|  for (i = 0; i < max_hdrs; i++) {
  ------------------
  |  Branch (4230:15): [True: 474k, False: 780]
  ------------------
 4231|   474k|    struct mg_str k = {NULL, 0}, v = {NULL, 0};
 4232|   474k|    if (s >= end) return false;
  ------------------
  |  Branch (4232:9): [True: 0, False: 474k]
  ------------------
 4233|   474k|    if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) break;
  ------------------
  |  Branch (4233:9): [True: 396k, False: 78.3k]
  |  Branch (4233:26): [True: 4.53k, False: 73.7k]
  |  Branch (4233:42): [True: 4.52k, False: 6]
  ------------------
 4234|  73.7k|    k.buf = (char *) s;
 4235|  26.3M|    while (s < end && s[0] != ':' && (n = clen(s, end)) > 0) s += n, k.len += n;
  ------------------
  |  Branch (4235:12): [True: 26.3M, False: 0]
  |  Branch (4235:23): [True: 26.3M, False: 73.4k]
  |  Branch (4235:38): [True: 26.3M, False: 362]
  ------------------
 4236|  73.7k|    if (k.len == 0) return false;                     // Empty name
  ------------------
  |  Branch (4236:9): [True: 53, False: 73.7k]
  ------------------
 4237|  73.7k|    if (s >= end || clen(s, end) == 0) return false;  // Invalid UTF-8
  ------------------
  |  Branch (4237:9): [True: 0, False: 73.7k]
  |  Branch (4237:21): [True: 320, False: 73.4k]
  ------------------
 4238|  73.4k|    if (*s++ != ':') return false;  // Invalid, not followed by :
  ------------------
  |  Branch (4238:9): [True: 0, False: 73.4k]
  ------------------
 4239|       |    // if (clen(s, end) == 0) return false;        // Invalid UTF-8
 4240|   104k|    while (s < end && (s[0] == ' ' || s[0] == '\t')) s++;  // Skip spaces
  ------------------
  |  Branch (4240:12): [True: 104k, False: 0]
  |  Branch (4240:24): [True: 30.8k, False: 73.8k]
  |  Branch (4240:39): [True: 434, False: 73.4k]
  ------------------
 4241|  73.4k|    if ((s = skiptorn(s, end, &v)) == NULL) return false;
  ------------------
  |  Branch (4241:9): [True: 20, False: 73.3k]
  ------------------
 4242|  81.9k|    while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) {
  ------------------
  |  Branch (4242:12): [True: 51.9k, False: 29.9k]
  |  Branch (4242:26): [True: 8.19k, False: 43.7k]
  |  Branch (4242:53): [True: 337, False: 43.4k]
  ------------------
 4243|  8.53k|      v.len--;  // Trim spaces
 4244|  8.53k|    }
 4245|       |    // detect duplicated headers -> discard
 4246|  73.3k|    if (((mg_strcasecmp(k, mg_str("Content-Length")) == 0) &&
  ------------------
  |  | 1467|  73.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4246:10): [True: 2.10k, False: 71.2k]
  ------------------
 4247|  2.10k|         (++cl_count > 1)) ||
  ------------------
  |  Branch (4247:10): [True: 3, False: 2.10k]
  ------------------
 4248|  73.3k|        ((mg_strcasecmp(k, mg_str("Transfer-Encoding")) == 0) &&
  ------------------
  |  | 1467|  73.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4248:10): [True: 19.3k, False: 54.0k]
  ------------------
 4249|  19.3k|         (++te_count > 1)) ||
  ------------------
  |  Branch (4249:10): [True: 3, False: 19.3k]
  ------------------
 4250|  73.3k|        ((mg_strcasecmp(k, mg_str("Authorization")) == 0) &&
  ------------------
  |  | 1467|  73.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4250:10): [True: 0, False: 73.3k]
  ------------------
 4251|      0|         (++auth_count > 1)) ||
  ------------------
  |  Branch (4251:10): [True: 0, False: 0]
  ------------------
 4252|  73.3k|        ((mg_strcasecmp(k, mg_str("Cookie")) == 0) && (++cookie_count > 1)) ||
  ------------------
  |  | 1467|  73.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4252:10): [True: 0, False: 73.3k]
  |  Branch (4252:55): [True: 0, False: 0]
  ------------------
 4253|  73.3k|        ((mg_strcasecmp(k, mg_str("Connection")) == 0) && (++conn_count > 1)))
  ------------------
  |  | 1467|  73.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4253:10): [True: 571, False: 72.8k]
  |  Branch (4253:59): [True: 3, False: 568]
  ------------------
 4254|      9|      return false;
 4255|       |    // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf));
 4256|  73.3k|    h[i].name = k, h[i].value = v;  // Success. Assign values
 4257|  73.3k|  }
 4258|   401k|  return true;
 4259|   401k|}
fuzz.c:_ZL23mg_http_status_code_stri:
 4370|   397k|static const char *mg_http_status_code_str(int status_code) {
 4371|   397k|  switch (status_code) {
 4372|      0|    case 100: return "Continue";
  ------------------
  |  Branch (4372:5): [True: 0, False: 397k]
  ------------------
 4373|      0|    case 101: return "Switching Protocols";
  ------------------
  |  Branch (4373:5): [True: 0, False: 397k]
  ------------------
 4374|      0|    case 102: return "Processing";
  ------------------
  |  Branch (4374:5): [True: 0, False: 397k]
  ------------------
 4375|      0|    case 200: return "OK";
  ------------------
  |  Branch (4375:5): [True: 0, False: 397k]
  ------------------
 4376|      0|    case 201: return "Created";
  ------------------
  |  Branch (4376:5): [True: 0, False: 397k]
  ------------------
 4377|      0|    case 202: return "Accepted";
  ------------------
  |  Branch (4377:5): [True: 0, False: 397k]
  ------------------
 4378|      0|    case 203: return "Non-authoritative Information";
  ------------------
  |  Branch (4378:5): [True: 0, False: 397k]
  ------------------
 4379|      0|    case 204: return "No Content";
  ------------------
  |  Branch (4379:5): [True: 0, False: 397k]
  ------------------
 4380|      0|    case 205: return "Reset Content";
  ------------------
  |  Branch (4380:5): [True: 0, False: 397k]
  ------------------
 4381|      0|    case 206: return "Partial Content";
  ------------------
  |  Branch (4381:5): [True: 0, False: 397k]
  ------------------
 4382|      0|    case 207: return "Multi-Status";
  ------------------
  |  Branch (4382:5): [True: 0, False: 397k]
  ------------------
 4383|      0|    case 208: return "Already Reported";
  ------------------
  |  Branch (4383:5): [True: 0, False: 397k]
  ------------------
 4384|      0|    case 226: return "IM Used";
  ------------------
  |  Branch (4384:5): [True: 0, False: 397k]
  ------------------
 4385|      0|    case 300: return "Multiple Choices";
  ------------------
  |  Branch (4385:5): [True: 0, False: 397k]
  ------------------
 4386|      0|    case 301: return "Moved Permanently";
  ------------------
  |  Branch (4386:5): [True: 0, False: 397k]
  ------------------
 4387|      0|    case 302: return "Found";
  ------------------
  |  Branch (4387:5): [True: 0, False: 397k]
  ------------------
 4388|      0|    case 303: return "See Other";
  ------------------
  |  Branch (4388:5): [True: 0, False: 397k]
  ------------------
 4389|      0|    case 304: return "Not Modified";
  ------------------
  |  Branch (4389:5): [True: 0, False: 397k]
  ------------------
 4390|      0|    case 305: return "Use Proxy";
  ------------------
  |  Branch (4390:5): [True: 0, False: 397k]
  ------------------
 4391|      0|    case 307: return "Temporary Redirect";
  ------------------
  |  Branch (4391:5): [True: 0, False: 397k]
  ------------------
 4392|      0|    case 308: return "Permanent Redirect";
  ------------------
  |  Branch (4392:5): [True: 0, False: 397k]
  ------------------
 4393|  31.2k|    case 400: return "Bad Request";
  ------------------
  |  Branch (4393:5): [True: 31.2k, False: 366k]
  ------------------
 4394|      0|    case 401: return "Unauthorized";
  ------------------
  |  Branch (4394:5): [True: 0, False: 397k]
  ------------------
 4395|      0|    case 402: return "Payment Required";
  ------------------
  |  Branch (4395:5): [True: 0, False: 397k]
  ------------------
 4396|   354k|    case 403: return "Forbidden";
  ------------------
  |  Branch (4396:5): [True: 354k, False: 43.3k]
  ------------------
 4397|  12.1k|    case 404: return "Not Found";
  ------------------
  |  Branch (4397:5): [True: 12.1k, False: 385k]
  ------------------
 4398|      0|    case 405: return "Method Not Allowed";
  ------------------
  |  Branch (4398:5): [True: 0, False: 397k]
  ------------------
 4399|      0|    case 406: return "Not Acceptable";
  ------------------
  |  Branch (4399:5): [True: 0, False: 397k]
  ------------------
 4400|      0|    case 407: return "Proxy Authentication Required";
  ------------------
  |  Branch (4400:5): [True: 0, False: 397k]
  ------------------
 4401|      0|    case 408: return "Request Timeout";
  ------------------
  |  Branch (4401:5): [True: 0, False: 397k]
  ------------------
 4402|      0|    case 409: return "Conflict";
  ------------------
  |  Branch (4402:5): [True: 0, False: 397k]
  ------------------
 4403|      0|    case 410: return "Gone";
  ------------------
  |  Branch (4403:5): [True: 0, False: 397k]
  ------------------
 4404|      0|    case 411: return "Length Required";
  ------------------
  |  Branch (4404:5): [True: 0, False: 397k]
  ------------------
 4405|      0|    case 412: return "Precondition Failed";
  ------------------
  |  Branch (4405:5): [True: 0, False: 397k]
  ------------------
 4406|      0|    case 413: return "Payload Too Large";
  ------------------
  |  Branch (4406:5): [True: 0, False: 397k]
  ------------------
 4407|      0|    case 414: return "Request-URI Too Long";
  ------------------
  |  Branch (4407:5): [True: 0, False: 397k]
  ------------------
 4408|      0|    case 415: return "Unsupported Media Type";
  ------------------
  |  Branch (4408:5): [True: 0, False: 397k]
  ------------------
 4409|      0|    case 416: return "Requested Range Not Satisfiable";
  ------------------
  |  Branch (4409:5): [True: 0, False: 397k]
  ------------------
 4410|      0|    case 417: return "Expectation Failed";
  ------------------
  |  Branch (4410:5): [True: 0, False: 397k]
  ------------------
 4411|      0|    case 418: return "I'm a teapot";
  ------------------
  |  Branch (4411:5): [True: 0, False: 397k]
  ------------------
 4412|      0|    case 421: return "Misdirected Request";
  ------------------
  |  Branch (4412:5): [True: 0, False: 397k]
  ------------------
 4413|      0|    case 422: return "Unprocessable Entity";
  ------------------
  |  Branch (4413:5): [True: 0, False: 397k]
  ------------------
 4414|      0|    case 423: return "Locked";
  ------------------
  |  Branch (4414:5): [True: 0, False: 397k]
  ------------------
 4415|      0|    case 424: return "Failed Dependency";
  ------------------
  |  Branch (4415:5): [True: 0, False: 397k]
  ------------------
 4416|      0|    case 426: return "Upgrade Required";
  ------------------
  |  Branch (4416:5): [True: 0, False: 397k]
  ------------------
 4417|      0|    case 428: return "Precondition Required";
  ------------------
  |  Branch (4417:5): [True: 0, False: 397k]
  ------------------
 4418|      0|    case 429: return "Too Many Requests";
  ------------------
  |  Branch (4418:5): [True: 0, False: 397k]
  ------------------
 4419|      0|    case 431: return "Request Header Fields Too Large";
  ------------------
  |  Branch (4419:5): [True: 0, False: 397k]
  ------------------
 4420|      0|    case 444: return "Connection Closed Without Response";
  ------------------
  |  Branch (4420:5): [True: 0, False: 397k]
  ------------------
 4421|      0|    case 451: return "Unavailable For Legal Reasons";
  ------------------
  |  Branch (4421:5): [True: 0, False: 397k]
  ------------------
 4422|      0|    case 499: return "Client Closed Request";
  ------------------
  |  Branch (4422:5): [True: 0, False: 397k]
  ------------------
 4423|      0|    case 500: return "Internal Server Error";
  ------------------
  |  Branch (4423:5): [True: 0, False: 397k]
  ------------------
 4424|      0|    case 501: return "Not Implemented";
  ------------------
  |  Branch (4424:5): [True: 0, False: 397k]
  ------------------
 4425|      0|    case 502: return "Bad Gateway";
  ------------------
  |  Branch (4425:5): [True: 0, False: 397k]
  ------------------
 4426|      0|    case 503: return "Service Unavailable";
  ------------------
  |  Branch (4426:5): [True: 0, False: 397k]
  ------------------
 4427|      0|    case 504: return "Gateway Timeout";
  ------------------
  |  Branch (4427:5): [True: 0, False: 397k]
  ------------------
 4428|      0|    case 505: return "HTTP Version Not Supported";
  ------------------
  |  Branch (4428:5): [True: 0, False: 397k]
  ------------------
 4429|      0|    case 506: return "Variant Also Negotiates";
  ------------------
  |  Branch (4429:5): [True: 0, False: 397k]
  ------------------
 4430|      0|    case 507: return "Insufficient Storage";
  ------------------
  |  Branch (4430:5): [True: 0, False: 397k]
  ------------------
 4431|      0|    case 508: return "Loop Detected";
  ------------------
  |  Branch (4431:5): [True: 0, False: 397k]
  ------------------
 4432|      0|    case 510: return "Not Extended";
  ------------------
  |  Branch (4432:5): [True: 0, False: 397k]
  ------------------
 4433|      0|    case 511: return "Network Authentication Required";
  ------------------
  |  Branch (4433:5): [True: 0, False: 397k]
  ------------------
 4434|      0|    case 599: return "Network Connect Timeout Error";
  ------------------
  |  Branch (4434:5): [True: 0, False: 397k]
  ------------------
 4435|      0|    default: return "";
  ------------------
  |  Branch (4435:5): [True: 0, False: 397k]
  ------------------
 4436|   397k|  }
 4437|   397k|}
fuzz.c:_ZL18guess_content_type6mg_strPKc:
 4531|  12.1k|static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
 4532|  12.1k|  struct mg_str entry, k, v, s = mg_str(extra), asterisk = mg_str_n("*", 1);
  ------------------
  |  | 1467|  12.1k|#define mg_str(s) mg_str_s(s)
  ------------------
 4533|  12.1k|  size_t i = 0;
 4534|       |
 4535|       |  // Shrink path to its extension only
 4536|   220k|  while (i < path.len && path.buf[path.len - i - 1] != '.') i++;
  ------------------
  |  Branch (4536:10): [True: 220k, False: 0]
  |  Branch (4536:26): [True: 208k, False: 12.1k]
  ------------------
 4537|  12.1k|  path.buf += path.len - i;
 4538|  12.1k|  path.len = i;
 4539|       |
 4540|       |  // Process user-provided mime type overrides, if any
 4541|  12.1k|  while (mg_span(s, &entry, &s, ',')) {
  ------------------
  |  Branch (4541:10): [True: 0, False: 12.1k]
  ------------------
 4542|      0|    if (mg_span(entry, &k, &v, '=') &&
  ------------------
  |  Branch (4542:9): [True: 0, False: 0]
  ------------------
 4543|      0|        (mg_strcmp(asterisk, k) == 0 || mg_strcmp(path, k) == 0))
  ------------------
  |  Branch (4543:10): [True: 0, False: 0]
  |  Branch (4543:41): [True: 0, False: 0]
  ------------------
 4544|      0|      return v;
 4545|      0|  }
 4546|       |
 4547|       |  // Process built-in mime types
 4548|   389k|  for (i = 0; s_known_types[i].buf != NULL; i += 2) {
  ------------------
  |  Branch (4548:15): [True: 377k, False: 12.1k]
  ------------------
 4549|   377k|    if (mg_strcmp(path, s_known_types[i]) == 0) return s_known_types[i + 1];
  ------------------
  |  Branch (4549:9): [True: 2, False: 377k]
  ------------------
 4550|   377k|  }
 4551|       |
 4552|  12.1k|  return mg_str("text/plain; charset=utf-8");
  ------------------
  |  | 1467|  12.1k|#define mg_str(s) mg_str_s(s)
  ------------------
 4553|  12.1k|}
fuzz.c:_ZL18uri_to_file_statusP13mg_connectionP15mg_http_messageP5mg_fsPKcPcm:
 4753|   397k|                              char *path, size_t path_size) {
 4754|   397k|  int flags, tmp;
 4755|   397k|  size_t n;
 4756|   397k|  if (!uri2path(root_dir, hm->uri, path, path_size)) {
  ------------------
  |  Branch (4756:7): [True: 31.2k, False: 366k]
  ------------------
 4757|  31.2k|    mg_http_reply(c, 400, "", "Invalid path");
 4758|  31.2k|    return -1;
 4759|  31.2k|  }
 4760|   366k|  n = strlen(path);
 4761|   366k|  flags = mg_strcmp(hm->uri, mg_str("/")) == 0 ? MG_FS_DIR
  ------------------
  |  | 1467|   366k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4761:11): [True: 351k, False: 14.5k]
  ------------------
 4762|   366k|                                               : fs->st(path, NULL, NULL);
 4763|   366k|  MG_VERBOSE(("%lu %.*s -> %s %d", c->id, (int) hm->uri.len, hm->uri.buf, path,
  ------------------
  |  | 1769|   366k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|   366k|  do {                      \
  |  |  |  | 1757|   366k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 366k]
  |  |  |  |  ------------------
  |  |  |  | 1758|   366k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 366k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4764|   366k|              flags));
 4765|   366k|  if (flags == 0) {
  ------------------
  |  Branch (4765:7): [True: 12.1k, False: 354k]
  ------------------
 4766|       |    // Do nothing - let's caller decide
 4767|   354k|  } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
  ------------------
  |  Branch (4767:14): [True: 354k, False: 0]
  |  Branch (4767:37): [True: 354k, False: 0]
  ------------------
 4768|   354k|             hm->uri.buf[hm->uri.len - 1] != '/') {
  ------------------
  |  Branch (4768:14): [True: 86, False: 354k]
  ------------------
 4769|     86|    mg_printf(c,
 4770|     86|              "HTTP/1.1 301 Moved\r\n"
 4771|     86|              "Location: %.*s/\r\n"
 4772|     86|              "Content-Length: 0\r\n"
 4773|     86|              "\r\n",
 4774|     86|              (int) hm->uri.len, hm->uri.buf);
 4775|     86|    c->pfn_data = NULL;  // Response done
 4776|     86|    flags = -1;
 4777|   354k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (4777:14): [True: 354k, False: 0]
  ------------------
 4778|   354k|    if (((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
  ------------------
  |  | 1243|   354k|#define MG_HTTP_INDEX "index.html"
  ------------------
  |  Branch (4778:11): [True: 354k, False: 0]
  ------------------
 4779|   354k|          (tmp = fs->st(path, NULL, NULL)) != 0) ||
  ------------------
  |  Branch (4779:11): [True: 0, False: 354k]
  ------------------
 4780|   354k|         (mg_snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
  ------------------
  |  Branch (4780:11): [True: 354k, False: 0]
  ------------------
 4781|   354k|          (tmp = fs->st(path, NULL, NULL)) != 0))) {
  ------------------
  |  Branch (4781:11): [True: 0, False: 354k]
  ------------------
 4782|      0|      flags = tmp;
 4783|   354k|    } else if ((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX ".gz") >
  ------------------
  |  Branch (4783:17): [True: 354k, False: 0]
  ------------------
 4784|   354k|                    0 &&
 4785|   354k|                (tmp = fs->st(path, NULL, NULL)) !=
  ------------------
  |  Branch (4785:17): [True: 0, False: 354k]
  ------------------
 4786|   354k|                    0)) {  // check for gzipped index
 4787|      0|      flags = tmp;
 4788|      0|      path[n + 1 + strlen(MG_HTTP_INDEX)] =
  ------------------
  |  | 1243|      0|#define MG_HTTP_INDEX "index.html"
  ------------------
 4789|      0|          '\0';  // Remove appended .gz in index file name
 4790|   354k|    } else {
 4791|   354k|      path[n] = '\0';  // Remove appended index file name
 4792|   354k|    }
 4793|   354k|  }
 4794|   366k|  return flags;
 4795|   397k|}
fuzz.c:_ZL8uri2pathPKc6mg_strPcm:
 4724|   397k|static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
 4725|   397k|  struct mg_str k, v, part, s = mg_str(r), u = {NULL, 0}, d = u;
  ------------------
  |  | 1467|   397k|#define mg_str(s) mg_str_s(s)
  ------------------
 4726|   397k|  size_t n;
 4727|   397k|  bool matched = false;
 4728|   795k|  while (mg_span(s, &part, &s, ',')) {
  ------------------
  |  Branch (4728:10): [True: 397k, False: 397k]
  ------------------
 4729|   397k|    if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
  ------------------
  |  Branch (4729:9): [True: 0, False: 397k]
  ------------------
 4730|   397k|    if (v.len == 0) v = k, k = mg_str("/"), u = k, d = v;
  ------------------
  |  | 1467|   397k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4730:9): [True: 397k, False: 0]
  ------------------
 4731|   397k|    if (uri.len < k.len) continue;
  ------------------
  |  Branch (4731:9): [True: 0, False: 397k]
  ------------------
 4732|   397k|    if (mg_strcmp(k, mg_str_n(uri.buf, k.len)) != 0) continue;
  ------------------
  |  Branch (4732:9): [True: 25.2k, False: 372k]
  ------------------
 4733|   372k|    u = k, d = v, matched = true;
 4734|   372k|  }
 4735|   397k|  if (!matched) return false;
  ------------------
  |  Branch (4735:7): [True: 25.2k, False: 372k]
  ------------------
 4736|   372k|  n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
 4737|   372k|  if (len == 0 || n + 2 >= len) return false;  // Path overflow
  ------------------
  |  Branch (4737:7): [True: 0, False: 372k]
  |  Branch (4737:19): [True: 0, False: 372k]
  ------------------
 4738|   372k|  if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0';  // Add slash
  ------------------
  |  Branch (4738:7): [True: 372k, False: 0]
  |  Branch (4738:16): [True: 372k, False: 0]
  ------------------
 4739|   372k|  if (mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0) < 0) {
  ------------------
  |  Branch (4739:7): [True: 5.28k, False: 367k]
  ------------------
 4740|  5.28k|    return false;
 4741|  5.28k|  }
 4742|   367k|  buf[len - 1] = '\0';  // Double-check
 4743|   367k|  n = strlen(buf);
 4744|   367k|  if (!mg_path_is_sane(mg_str_n(buf, n))) return false;
  ------------------
  |  Branch (4744:7): [True: 648, False: 366k]
  ------------------
 4745|   868k|  while (n > 1 && buf[n - 1] == '/') buf[--n] = 0;  // Trim trailing slashes
  ------------------
  |  Branch (4745:10): [True: 515k, False: 352k]
  |  Branch (4745:19): [True: 501k, False: 14.2k]
  ------------------
 4746|   366k|  return true;
 4747|   367k|}
fuzz.c:_ZL7http_cbP13mg_connectioniPv:
 5124|   830k|static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
 5125|   830k|  if (ev == MG_EV_READ || ev == MG_EV_CLOSE ||
  ------------------
  |  Branch (5125:7): [True: 5.56k, False: 824k]
  |  Branch (5125:27): [True: 5.56k, False: 819k]
  ------------------
 5126|   819k|      (ev == MG_EV_POLL && c->is_accepted && !c->is_draining &&
  ------------------
  |  Branch (5126:8): [True: 5.56k, False: 813k]
  |  Branch (5126:28): [True: 0, False: 5.56k]
  |  Branch (5126:46): [True: 0, False: 0]
  ------------------
 5127|  11.1k|       c->recv.len > 0)) {  // see #2796
  ------------------
  |  Branch (5127:8): [True: 0, False: 0]
  ------------------
 5128|  11.1k|    struct mg_http_message hm;
 5129|  11.1k|    size_t ofs = 0;  // Parsing offset
 5130|       |    // c->pfn_data is the "response generation in progress" marker. While it
 5131|       |    // is set, don't parse the next pipelined request, to keep responses in order
 5132|   408k|    while (c->pfn_data == NULL && ofs < c->recv.len) {
  ------------------
  |  Branch (5132:12): [True: 408k, False: 0]
  |  Branch (5132:35): [True: 404k, False: 3.75k]
  ------------------
 5133|   404k|      const char *buf = (char *) c->recv.buf + ofs;
 5134|   404k|      int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
 5135|   404k|      struct mg_str *te;  // Transfer - encoding header
 5136|   404k|      bool is_chunked = false, is_http_1_0 = false;
 5137|   404k|      size_t old_len = c->recv.len;
 5138|   404k|      if (n < 0) {
  ------------------
  |  Branch (5138:11): [True: 2.66k, False: 402k]
  ------------------
 5139|       |        // We don't use mg_error() here, to avoid closing pipelined requests
 5140|       |        // prematurely, see #2592
 5141|  2.66k|        MG_ERROR(("HTTP parse, %lu bytes", c->recv.len));
  ------------------
  |  | 1766|  2.66k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|  2.66k|  do {                      \
  |  |  |  | 1757|  2.66k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 2.66k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  2.66k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 2.66k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5142|  2.66k|        c->is_draining = 1;
 5143|  2.66k|        mg_hexdump(buf, c->recv.len - ofs > 16 ? 16 : c->recv.len - ofs);
  ------------------
  |  Branch (5143:25): [True: 1.83k, False: 827]
  ------------------
 5144|  2.66k|        c->recv.len = 0;
 5145|  2.66k|        return;
 5146|  2.66k|      }
 5147|   402k|      if (n == 0) break;                 // Request is not buffered yet
  ------------------
  |  Branch (5147:11): [True: 2.98k, False: 399k]
  ------------------
 5148|   399k|      mg_call(c, MG_EV_HTTP_HDRS, &hm);  // Got all HTTP headers
 5149|   399k|      if (c->recv.len != old_len) {
  ------------------
  |  Branch (5149:11): [True: 0, False: 399k]
  ------------------
 5150|       |        // User manipulated received data. Wash our hands
 5151|      0|        MG_DEBUG(("%lu detaching HTTP handler", c->id));
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5152|      0|        c->pfn = NULL;
 5153|      0|        return;
 5154|      0|      }
 5155|   399k|      if (ev == MG_EV_CLOSE) {  // If client did not set Content-Length
  ------------------
  |  Branch (5155:11): [True: 8.32k, False: 390k]
  ------------------
 5156|  8.32k|        hm.message.len = c->recv.len - ofs;  // and closes now, deliver MSG
 5157|  8.32k|        hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
 5158|  8.32k|      }
 5159|   399k|      is_http_1_0 =
 5160|   399k|          hm.proto.len == 8 && mg_ncasecmp(hm.proto.buf, "HTTP/1.0", 8) == 0;
  ------------------
  |  Branch (5160:11): [True: 367k, False: 32.1k]
  |  Branch (5160:32): [True: 2.66k, False: 364k]
  ------------------
 5161|       |      // HTTP/1.0 does not use "Transfer-Encoding: chunked"
 5162|   399k|      if (!is_http_1_0 &&
  ------------------
  |  Branch (5162:11): [True: 396k, False: 2.66k]
  ------------------
 5163|   396k|          (te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
  ------------------
  |  Branch (5163:11): [True: 18.7k, False: 377k]
  ------------------
 5164|  18.7k|        if (mg_strcasecmp(*te, mg_str("chunked")) == 0) {
  ------------------
  |  | 1467|  18.7k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (5164:13): [True: 18.4k, False: 339]
  ------------------
 5165|  18.4k|          is_chunked = true;
 5166|  18.4k|        } else {
 5167|    339|          mg_error(c, "Invalid Transfer-Encoding");  // See #2460
 5168|    339|          return;
 5169|    339|        }
 5170|   380k|      } else if (mg_http_get_header(&hm, "Content-length") == NULL) {
  ------------------
  |  Branch (5170:18): [True: 378k, False: 1.60k]
  ------------------
 5171|       |        // #2593: HTTP packets must contain either Transfer-Encoding or
 5172|       |        // Content-length
 5173|   378k|        bool is_response = mg_ncasecmp(hm.method.buf, "HTTP/", 5) == 0;
 5174|   378k|        bool require_content_len = false;
 5175|   378k|        if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
  ------------------
  |  | 1467|   366k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (5175:13): [True: 366k, False: 12.4k]
  |  Branch (5175:30): [True: 87, False: 366k]
  ------------------
 5176|   366k|                             mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
  ------------------
  |  | 1467|   366k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (5176:30): [True: 264, False: 366k]
  ------------------
 5177|       |          // POST and PUT should include an entity body. Therefore, they should
 5178|       |          // contain a Content-length header (unless the body length is 0, in
 5179|       |          // which case it can be omitted). Other requests can also contain a
 5180|       |          // body, but their content has no defined semantics (RFC 7231)
 5181|       |          // It is a non-chunked request, so the offset (ofs) is updated after
 5182|       |          // exiting this branch.
 5183|    351|          if (hm.body.len != 0) require_content_len = true;
  ------------------
  |  Branch (5183:15): [True: 3, False: 348]
  ------------------
 5184|   378k|        } else if (is_response) {
  ------------------
  |  Branch (5184:20): [True: 12.4k, False: 366k]
  ------------------
 5185|       |          // HTTP spec 7.2 Entity body: All other responses must include a body
 5186|       |          // or Content-Length header field defined with a value of 0.
 5187|  12.4k|          int status = mg_http_status(&hm);
 5188|  12.4k|          require_content_len = status >= 200 && status != 204 && status != 304;
  ------------------
  |  Branch (5188:33): [True: 11.1k, False: 1.26k]
  |  Branch (5188:50): [True: 117, False: 11.0k]
  |  Branch (5188:67): [True: 115, False: 2]
  ------------------
 5189|  12.4k|        }
 5190|   378k|        if (require_content_len) {
  ------------------
  |  Branch (5190:13): [True: 118, False: 378k]
  ------------------
 5191|    118|          if (!c->is_client) mg_http_reply(c, 411, "", "");
  ------------------
  |  Branch (5191:15): [True: 0, False: 118]
  ------------------
 5192|    118|          MG_ERROR(("Content length missing from %s",
  ------------------
  |  | 1766|    118|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|    118|  do {                      \
  |  |  |  | 1757|    118|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 118]
  |  |  |  |  |  Branch (1757:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|    118|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 118]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5193|    118|                    is_response ? "response" : "request"));
 5194|    118|        }
 5195|   378k|      }
 5196|       |
 5197|   398k|      if (is_chunked) {
  ------------------
  |  Branch (5197:11): [True: 18.4k, False: 380k]
  ------------------
 5198|       |        // For chunked data, strip off prefixes and suffixes from chunks
 5199|       |        // and relocate them right after the headers, then report a message
 5200|  18.4k|        char *s = (char *) c->recv.buf + ofs + n;
 5201|  18.4k|        int o = 0, pl, dl, cl, len = (int) (c->recv.len - ofs - (size_t) n);
 5202|       |
 5203|       |        // Find zero-length chunk (the end of the body)
 5204|  19.6k|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0 && dl) o += cl;
  ------------------
  |  Branch (5204:16): [True: 19.1k, False: 423]
  |  Branch (5204:67): [True: 1.16k, False: 18.0k]
  ------------------
 5205|  18.4k|        if (cl == 0) break;  // No zero-len chunk, buffer more data
  ------------------
  |  Branch (5205:13): [True: 126, False: 18.3k]
  ------------------
 5206|  18.3k|        if (cl < 0) {
  ------------------
  |  Branch (5206:13): [True: 297, False: 18.0k]
  ------------------
 5207|    297|          mg_error(c, "Invalid chunk");
 5208|    297|          break;
 5209|    297|        }
 5210|       |
 5211|       |        // Zero chunk found. Second pass: strip + relocate
 5212|  18.0k|        o = 0, hm.body.len = 0, hm.message.len = (size_t) n;
 5213|  18.6k|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0) {
  ------------------
  |  Branch (5213:16): [True: 18.6k, False: 0]
  ------------------
 5214|  18.6k|          memmove(s + hm.body.len, s + o + pl, (size_t) dl);
 5215|  18.6k|          o += cl, hm.body.len += (size_t) dl, hm.message.len += (size_t) dl;
 5216|  18.6k|          if (dl == 0) break;
  ------------------
  |  Branch (5216:15): [True: 18.0k, False: 619]
  ------------------
 5217|  18.6k|        }
 5218|  18.0k|        ofs += (size_t) (n + o);
 5219|   380k|      } else {  // Normal, non-chunked data
 5220|   380k|        size_t len = c->recv.len - ofs - (size_t) n;
 5221|   380k|        if (hm.body.len > len) break;  // Buffer more data
  ------------------
  |  Branch (5221:13): [True: 951, False: 379k]
  ------------------
 5222|   379k|        ofs += (size_t) n + hm.body.len;
 5223|   379k|      }
 5224|       |
 5225|   397k|      if (c->is_accepted) c->pfn_data = c;  // Response started
  ------------------
  |  Branch (5225:11): [True: 0, False: 397k]
  ------------------
 5226|   397k|      mg_call(c, MG_EV_HTTP_MSG, &hm);  // Handler sets pfn_data NULL when done
 5227|   397k|      if (c->is_accepted && c->pfn_data == NULL) {
  ------------------
  |  Branch (5227:11): [True: 0, False: 397k]
  |  Branch (5227:29): [True: 0, False: 0]
  ------------------
 5228|      0|        struct mg_str *cc = mg_http_get_header(&hm, "Connection");
 5229|      0|        if (cc != NULL && mg_strcasecmp(*cc, mg_str("close")) == 0) {
  ------------------
  |  | 1467|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (5229:13): [True: 0, False: 0]
  |  Branch (5229:27): [True: 0, False: 0]
  ------------------
 5230|      0|          c->is_draining = 1;  // honor "Connection: close"
 5231|      0|          break;
 5232|      0|        }
 5233|      0|      }
 5234|   397k|    }
 5235|  8.11k|    if (ofs > 0) mg_iobuf_del(&c->recv, 0, ofs);  // Delete processed data
  ------------------
  |  Branch (5235:9): [True: 1.37k, False: 6.74k]
  ------------------
 5236|  8.11k|  }
 5237|   827k|  (void) ev_data;
 5238|   827k|}
fuzz.c:_ZL10skip_chunkPKciPiS1_:
 5109|  38.2k|static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
 5110|  38.2k|  int i = 0, n = 0;  // pass int to mg_str_to_num, treats as unsigned
 5111|  38.2k|  if (len < 3) return 0;
  ------------------
  |  Branch (5111:7): [True: 10, False: 38.2k]
  ------------------
 5112|  14.6M|  while (i < len && is_hex_digit(buf[i])) i++;
  ------------------
  |  Branch (5112:10): [True: 14.6M, False: 20]
  |  Branch (5112:21): [True: 14.6M, False: 38.2k]
  ------------------
 5113|  38.2k|  if (i == 0) return -1;  // Error, no length specified
  ------------------
  |  Branch (5113:7): [True: 16, False: 38.2k]
  ------------------
 5114|  38.2k|  if (len < i + 2 || buf[i] != '\r' || buf[i + 1] != '\n') return -1;  // Error
  ------------------
  |  Branch (5114:7): [True: 30, False: 38.2k]
  |  Branch (5114:22): [True: 77, False: 38.1k]
  |  Branch (5114:40): [True: 9, False: 38.1k]
  ------------------
 5115|  38.1k|  if (mg_str_to_num(mg_str_n(buf, (size_t) i), 16, &n, sizeof(n)) == false)
  ------------------
  |  Branch (5115:7): [True: 39, False: 38.0k]
  ------------------
 5116|     39|    return -1;                    // Decode chunk length, overflow
 5117|  38.0k|  if (n < 0) return -1;           // Chunk length is too big <0 = >0x80000000
  ------------------
  |  Branch (5117:7): [True: 42, False: 38.0k]
  ------------------
 5118|  38.0k|  if (n > len - i - 4) return 0;  // Chunk not yet fully buffered
  ------------------
  |  Branch (5118:7): [True: 116, False: 37.9k]
  ------------------
 5119|  37.9k|  if (buf[i + n + 2] != '\r' || buf[i + n + 3] != '\n') return -1;  // Error
  ------------------
  |  Branch (5119:7): [True: 40, False: 37.8k]
  |  Branch (5119:33): [True: 44, False: 37.8k]
  ------------------
 5120|  37.8k|  *pl = i + 2, *dl = n;
 5121|  37.8k|  return i + 2 + n + 2;
 5122|  37.9k|}
fuzz.c:_ZL12is_hex_digiti:
 5104|  14.6M|static bool is_hex_digit(int c) {
 5105|  14.6M|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (5105:11): [True: 14.6M, False: 38.1k]
  |  Branch (5105:23): [True: 12.4M, False: 2.18M]
  |  Branch (5105:37): [True: 2.18M, False: 40.4k]
  |  Branch (5105:49): [True: 2.18M, False: 22]
  ------------------
 5106|  40.4k|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (5106:11): [True: 2.24k, False: 38.1k]
  |  Branch (5106:23): [True: 2.21k, False: 30]
  ------------------
 5107|  14.6M|}
fuzz.c:_ZL7roundupmm:
 5260|  35.0k|static size_t roundup(size_t size, size_t align) {
 5261|  35.0k|  return align == 0 ? size : (size + align - 1) / align * align;
  ------------------
  |  Branch (5261:10): [True: 0, False: 35.0k]
  ------------------
 5262|  35.0k|}
fuzz.c:_ZL7mg_atodPKciPi:
 5357|   260k|static double mg_atod(const char *p, int len, int *numlen) {
 5358|   260k|  double d = 0.0;
 5359|   260k|  int i = 0, sign = 1;
 5360|       |
 5361|       |  // Sign
 5362|   260k|  if (i < len && *p == '-') {
  ------------------
  |  Branch (5362:7): [True: 260k, False: 0]
  |  Branch (5362:18): [True: 125k, False: 134k]
  ------------------
 5363|   125k|    sign = -1, i++;
 5364|   134k|  } else if (i < len && *p == '+') {
  ------------------
  |  Branch (5364:14): [True: 134k, False: 0]
  |  Branch (5364:25): [True: 0, False: 134k]
  ------------------
 5365|      0|    i++;
 5366|      0|  }
 5367|       |
 5368|       |  // Decimal
 5369|  8.45M|  for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (5369:10): [True: 8.44M, False: 110]
  |  Branch (5369:21): [True: 8.24M, False: 206k]
  |  Branch (5369:36): [True: 8.18M, False: 53.1k]
  ------------------
 5370|  8.18M|    d *= 10.0;
 5371|  8.18M|    d += p[i] - '0';
 5372|  8.18M|  }
 5373|   260k|  d *= sign;
 5374|       |
 5375|       |  // Fractional
 5376|   260k|  if (i < len && p[i] == '.') {
  ------------------
  |  Branch (5376:7): [True: 260k, False: 110]
  |  Branch (5376:18): [True: 96.0k, False: 163k]
  ------------------
 5377|  96.0k|    double frac = 0.0, base = 0.1;
 5378|  96.0k|    i++;
 5379|  2.73M|    for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (5379:12): [True: 2.73M, False: 54]
  |  Branch (5379:23): [True: 2.63M, False: 95.9k]
  |  Branch (5379:38): [True: 2.63M, False: 81]
  ------------------
 5380|  2.63M|      frac += base * (p[i] - '0');
 5381|  2.63M|      base /= 10.0;
 5382|  2.63M|    }
 5383|  96.0k|    d += frac * sign;
 5384|  96.0k|  }
 5385|       |
 5386|       |  // Exponential
 5387|   260k|  if (i < len && (p[i] == 'e' || p[i] == 'E')) {
  ------------------
  |  Branch (5387:7): [True: 259k, False: 164]
  |  Branch (5387:19): [True: 4.81k, False: 255k]
  |  Branch (5387:34): [True: 47.1k, False: 208k]
  ------------------
 5388|  51.9k|    int exp = 0, minus = 0;
 5389|  51.9k|    i++;
 5390|  51.9k|    if (i < len && p[i] == '-') minus = 1, i++;
  ------------------
  |  Branch (5390:9): [True: 51.9k, False: 24]
  |  Branch (5390:20): [True: 41.1k, False: 10.7k]
  ------------------
 5391|  51.9k|    if (i < len && p[i] == '+') i++;
  ------------------
  |  Branch (5391:9): [True: 51.8k, False: 44]
  |  Branch (5391:20): [True: 284, False: 51.6k]
  ------------------
 5392|   153k|    while (i < len && p[i] >= '0' && p[i] <= '9' && exp < 308)
  ------------------
  |  Branch (5392:12): [True: 153k, False: 144]
  |  Branch (5392:23): [True: 105k, False: 48.3k]
  |  Branch (5392:38): [True: 101k, False: 3.40k]
  |  Branch (5392:53): [True: 101k, False: 27]
  ------------------
 5393|   101k|      exp = exp * 10 + (p[i++] - '0');
 5394|       |    // use fast exponentiation
 5395|       |    // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
 5396|  51.9k|    if (exp != 0) {
  ------------------
  |  Branch (5396:9): [True: 47.7k, False: 4.15k]
  ------------------
 5397|  47.7k|      double x = 10, y = 1;
 5398|  47.7k|      if (exp > 308) exp = 308;
  ------------------
  |  Branch (5398:11): [True: 498, False: 47.2k]
  ------------------
 5399|  47.7k|      if (minus) x = 0.1;
  ------------------
  |  Branch (5399:11): [True: 40.2k, False: 7.57k]
  ------------------
 5400|   255k|      while (exp > 1) {
  ------------------
  |  Branch (5400:14): [True: 208k, False: 47.7k]
  ------------------
 5401|   208k|        if (exp & 1) {
  ------------------
  |  Branch (5401:13): [True: 63.9k, False: 144k]
  ------------------
 5402|  63.9k|          y *= x;
 5403|  63.9k|          --exp;
 5404|  63.9k|        }
 5405|   208k|        x *= x;
 5406|   208k|        exp >>= 1;
 5407|   208k|      }
 5408|  47.7k|      d *= x * y;
 5409|  47.7k|    }
 5410|  51.9k|  }
 5411|       |
 5412|   260k|  if (numlen != NULL) *numlen = i;
  ------------------
  |  Branch (5412:7): [True: 260k, False: 0]
  ------------------
 5413|   260k|  return d;
 5414|   260k|}
fuzz.c:_ZL14mg_pass_stringPKci:
 5343|  11.5k|static int mg_pass_string(const char *s, int len) {
 5344|  11.5k|  int i;
 5345|  31.6M|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (5345:15): [True: 31.6M, False: 469]
  ------------------
 5346|  31.6M|    if (s[i] == '\\' && i + 1 < len && json_esc(s[i + 1], 1)) {
  ------------------
  |  Branch (5346:9): [True: 1.06M, False: 30.5M]
  |  Branch (5346:25): [True: 1.06M, False: 70]
  |  Branch (5346:40): [True: 920k, False: 143k]
  ------------------
 5347|   920k|      i++;
 5348|  30.7M|    } else if (s[i] == '\0') {
  ------------------
  |  Branch (5348:16): [True: 96, False: 30.7M]
  ------------------
 5349|     96|      return MG_JSON_INVALID;
 5350|  30.7M|    } else if (s[i] == '"') {
  ------------------
  |  Branch (5350:16): [True: 11.0k, False: 30.7M]
  ------------------
 5351|  11.0k|      return i;
 5352|  11.0k|    }
 5353|  31.6M|  }
 5354|    469|  return MG_JSON_INVALID;
 5355|  11.5k|}
fuzz.c:_ZL8json_escii:
 5335|  1.06M|static char json_esc(int c, int esc) {
 5336|  1.06M|  const char *p, *esc1 = escapeseq(esc), *esc2 = escapeseq(!esc);
 5337|  5.95M|  for (p = esc1; *p != '\0'; p++) {
  ------------------
  |  Branch (5337:18): [True: 5.81M, False: 143k]
  ------------------
 5338|  5.81M|    if (*p == c) return esc2[p - esc1];
  ------------------
  |  Branch (5338:9): [True: 920k, False: 4.89M]
  ------------------
 5339|  5.81M|  }
 5340|   143k|  return 0;
 5341|  1.06M|}
fuzz.c:_ZL9escapeseqi:
 5331|  2.12M|static const char *escapeseq(int esc) {
 5332|  2.12M|  return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
  ------------------
  |  Branch (5332:10): [True: 1.06M, False: 1.06M]
  ------------------
 5333|  2.12M|}
fuzz.c:_ZL13l2_ppp_header10mg_l2protoPh:
 6431|  3.70k|static uint8_t *l2_ppp_header(enum mg_l2proto proto, uint8_t *p) {
 6432|  3.70k|  uint16_t ppp_proto = proto == MG_TCPIP_L2PROTO_IPV4   ? MG_PPP_PROTO_IP
  ------------------
  |  | 6353|  3.70k|#define MG_PPP_PROTO_IP 0x0021
  ------------------
  |  Branch (6432:24): [True: 3.70k, False: 0]
  ------------------
 6433|  3.70k|                       : proto == MG_TCPIP_L2PROTO_IPV4 ? MG_PPP_PROTO_IPV6
  ------------------
  |  | 6354|      0|#define MG_PPP_PROTO_IPV6 0x0057
  ------------------
  |  Branch (6433:26): [True: 0, False: 0]
  ------------------
 6434|      0|                                                        : 0;
 6435|  3.70k|  return ppp_header(ppp_proto, p);
 6436|  3.70k|}
fuzz.c:_ZL10ppp_headertPh:
 6425|  4.83k|static uint8_t *ppp_header(uint16_t proto, uint8_t *p) {
 6426|  4.83k|  struct ppp *ppp = (struct ppp *) p;
 6427|  4.83k|  ppp->proto = mg_htons(proto);
  ------------------
  |  | 2037|  4.83k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6428|  4.83k|  return (uint8_t *) (ppp + 1);
 6429|  4.83k|}
fuzz.c:_ZL11hdlc_headerPh:
 6418|  2.97k|static uint8_t *hdlc_header(uint8_t *p) {
 6419|  2.97k|  struct hdlc_ *hdlc = (struct hdlc_ *) p;
 6420|  2.97k|  hdlc->addr = MG_PPP_ADDR;
  ------------------
  |  | 6350|  2.97k|#define MG_PPP_ADDR 0xff
  ------------------
 6421|  2.97k|  hdlc->ctrl = MG_PPP_CTRL;
  ------------------
  |  | 6351|  2.97k|#define MG_PPP_CTRL 0x03
  ------------------
 6422|  2.97k|  return (uint8_t *) (hdlc + 1);
 6423|  2.97k|}
fuzz.c:_ZL12pppoe_headerP11mg_tcpip_if10mg_l2protohtP9mg_l2addrS3_Ph:
 6453|  1.85k|                             struct mg_l2addr *dst, uint8_t *frame) {
 6454|  1.85k|  struct pppoe *pppoe =
 6455|  1.85k|      (struct pppoe *) mg_l2_eth_header(ifp, proto, src, dst, frame);
 6456|  1.85k|  pppoe->vertype = 0x11;
 6457|  1.85k|  pppoe->code = code;
 6458|  1.85k|  pppoe->id = id;
 6459|  1.85k|  return (uint8_t *) (pppoe + 1);
 6460|  1.85k|}
fuzz.c:_ZL13pppoe_trailerP11mg_tcpip_ifmPh:
 6485|  1.85k|static size_t pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6486|  1.85k|  struct pppoe *pppoe = (struct pppoe *) (cur - len - sizeof(struct pppoe));
 6487|  1.85k|  pppoe->len = mg_htons((uint16_t) len);
  ------------------
  |  | 2037|  1.85k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6488|  1.85k|  return mg_l2_eth_trailer(ifp, PDIFF(pppoe, cur), cur);
  ------------------
  |  | 6393|  1.85k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 6489|  1.85k|}
fuzz.c:_ZL6ppp_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6703|  1.37k|                   struct mg_str *pay, struct mg_str *raw) {
 6704|  1.37k|  struct ppp *ppp = (struct ppp *) pay->buf;
 6705|  1.37k|  if (pay->len < sizeof(*ppp)) return false;  // Truncated
  ------------------
  |  Branch (6705:7): [True: 1, False: 1.37k]
  ------------------
 6706|  1.37k|  pay->buf = (char *) (ppp + 1);
 6707|  1.37k|  pay->len = pay->len - sizeof(*ppp);
 6708|  1.37k|  switch (mg_ntohs(ppp->proto)) {
 6709|     30|    case MG_PPP_PROTO_LCP:
  ------------------
  |  | 6355|     30|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
  |  Branch (6709:5): [True: 30, False: 1.34k]
  ------------------
 6710|     30|      ppp_handle_lcp(ifp, (uint8_t *) pay->buf, pay->len);
 6711|     30|      return false;
 6712|     36|    case MG_PPP_PROTO_IPCP:
  ------------------
  |  | 6356|     36|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
  |  Branch (6712:5): [True: 36, False: 1.33k]
  ------------------
 6713|     36|      if (s_lcpup) ppp_handle_ipcp(ifp, (uint8_t *) pay->buf, pay->len);
  ------------------
  |  Branch (6713:11): [True: 36, False: 0]
  ------------------
 6714|     36|      return false;
 6715|     44|    case MG_PPP_PROTO_IP:
  ------------------
  |  | 6353|     44|#define MG_PPP_PROTO_IP 0x0021
  ------------------
  |  Branch (6715:5): [True: 44, False: 1.32k]
  ------------------
 6716|     44|      if (!s_lcpup) return false;
  ------------------
  |  Branch (6716:11): [True: 0, False: 44]
  ------------------
 6717|     44|      MG_VERBOSE(("got IP packet of %d bytes", pay->len));
  ------------------
  |  | 1769|     44|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|     44|  do {                      \
  |  |  |  | 1757|     44|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 44]
  |  |  |  |  ------------------
  |  |  |  | 1758|     44|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 44]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6718|     44|      *proto = MG_TCPIP_L2PROTO_IPV4;
 6719|     44|      break;
 6720|       |#if MG_ENABLE_IPV6
 6721|       |    case MG_PPP_PROTO_IPV6CP:
 6722|       |      if (s_lcpup) ppp_handle_ipv6cp(ifp, (uint8_t *) pay->buf, pay->len);
 6723|       |      return false;
 6724|       |    case MG_PPP_PROTO_IPV6:
 6725|       |      if (!s_lcpup) return false;
 6726|       |      MG_VERBOSE(("got IPv6 packet of %d bytes", pay->len));
 6727|       |      *proto = MG_TCPIP_L2PROTO_IPV6;
 6728|       |      break;
 6729|       |#endif
 6730|  1.26k|    default: {
  ------------------
  |  Branch (6730:5): [True: 1.26k, False: 110]
  ------------------
 6731|  1.26k|      struct lcp rej;
 6732|  1.26k|      uint8_t *p;
 6733|  1.26k|      size_t msglen;
 6734|  1.26k|      MG_DEBUG(("unknown %u-byte PPP frame with proto 0x%04x:",
  ------------------
  |  | 1768|  1.26k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|  1.26k|  do {                      \
  |  |  |  | 1757|  1.26k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1.26k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  1.26k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1.26k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6735|  1.26k|                pay->len + sizeof(*ppp), mg_ntohs(ppp->proto)));
 6736|  1.26k|      if (mg_log_level >= MG_LL_DEBUG)
  ------------------
  |  Branch (6736:11): [True: 0, False: 1.26k]
  ------------------
 6737|      0|        mg_hexdump(ppp, pay->len > 14 ? 16 : pay->len + sizeof(*ppp));
  ------------------
  |  Branch (6737:25): [True: 0, False: 0]
  ------------------
 6738|  1.26k|      if (!s_lcpup) return false;  // RFC-1661 5.7: must reject on link down
  ------------------
  |  Branch (6738:11): [True: 158, False: 1.10k]
  ------------------
 6739|  1.10k|      if (pay->len > (size_t) (ifp->mtu - 20))
  ------------------
  |  Branch (6739:11): [True: 3, False: 1.10k]
  ------------------
 6740|      3|        pay->len = (size_t) (ifp->mtu - 20);  // truncate to some safe limit
 6741|  1.10k|      rej.code = MG_PPP_LCP_REJECT;
  ------------------
  |  | 6367|  1.10k|#define MG_PPP_LCP_REJECT 8
  ------------------
 6742|  1.10k|      mg_random(&rej.id, sizeof(rej.id));
 6743|  1.10k|      msglen = pay->len + sizeof(*ppp);
 6744|  1.10k|      rej.len = mg_htons((uint16_t) (msglen + sizeof(rej)));
  ------------------
  |  | 2037|  1.10k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6745|  1.10k|      p = ppp_tx_frame_header(ifp, MG_PPP_PROTO_LCP);
  ------------------
  |  | 6355|  1.10k|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6746|  1.10k|      memmove(p, &rej, sizeof(rej));          // LCP reject
 6747|  1.10k|      memmove(p + sizeof(rej), ppp, msglen);  // rejected PPP message
 6748|  1.10k|      ppp_tx_frame_trailer(ifp, msglen + sizeof(rej), p + msglen + sizeof(rej));
 6749|  1.10k|    }
 6750|      0|      return false;
 6751|  1.37k|  }
 6752|     44|  (void) raw;
 6753|     44|  return true;
 6754|  1.37k|}
fuzz.c:_ZL14ppp_handle_lcpP11mg_tcpip_ifPhm:
 6521|     30|                           size_t lcpsz) {
 6522|     30|  uint8_t id;
 6523|     30|  uint16_t len;
 6524|     30|  struct lcp *lcp = (struct lcp *) lcpp;
 6525|     30|  if (lcpsz < sizeof(*lcp)) return;
  ------------------
  |  Branch (6525:7): [True: 1, False: 29]
  ------------------
 6526|     29|  id = lcp->id;
 6527|     29|  len = mg_ntohs(lcp->len);
 6528|     29|  if (len < sizeof(*lcp) || len > lcpsz) return;
  ------------------
  |  Branch (6528:7): [True: 1, False: 28]
  |  Branch (6528:29): [True: 17, False: 11]
  ------------------
 6529|     11|  switch (lcp->code) {
  ------------------
  |  Branch (6529:11): [True: 6, False: 5]
  ------------------
 6530|      3|    case MG_PPP_LCP_CFG_REQ: {
  ------------------
  |  | 6361|      3|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
  |  Branch (6530:5): [True: 3, False: 8]
  ------------------
 6531|      3|      if (len == sizeof(*lcp)) {
  ------------------
  |  Branch (6531:11): [True: 2, False: 1]
  ------------------
 6532|      2|        MG_DEBUG(("LCP config request of %d bytes, acknowledging...", len));
  ------------------
  |  | 1768|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      2|  do {                      \
  |  |  |  | 1757|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1758|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6533|      2|        lcp->code = MG_PPP_LCP_CFG_ACK;
  ------------------
  |  | 6362|      2|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
 6534|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6355|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6535|      2|        lcp->code = MG_PPP_LCP_CFG_REQ;
  ------------------
  |  | 6361|      2|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
 6536|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6355|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6537|      2|      } else {
 6538|      1|        MG_DEBUG(("LCP config request of %d bytes, rejecting...", len));
  ------------------
  |  | 1768|      1|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6539|      1|        lcp->code = MG_PPP_LCP_CFG_REJECT;
  ------------------
  |  | 6364|      1|#define MG_PPP_LCP_CFG_REJECT 4
  ------------------
 6540|      1|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6355|      1|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6541|      1|      }
 6542|      3|    } break;
 6543|      0|    case MG_PPP_LCP_CFG_ACK:
  ------------------
  |  | 6362|      0|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
  |  Branch (6543:5): [True: 0, False: 11]
  ------------------
 6544|      0|      s_lcpup = true;
 6545|      0|      break;
 6546|      1|    case MG_PPP_LCP_CFG_TERM_REQ: {
  ------------------
  |  | 6365|      1|#define MG_PPP_LCP_CFG_TERM_REQ 5
  ------------------
  |  Branch (6546:5): [True: 1, False: 10]
  ------------------
 6547|      1|      uint8_t ack[4] = {MG_PPP_LCP_CFG_TERM_ACK, id, 0, 4};
  ------------------
  |  | 6366|      1|#define MG_PPP_LCP_CFG_TERM_ACK 6
  ------------------
 6548|      1|      MG_DEBUG(("LCP termination request, acknowledging..."));
  ------------------
  |  | 1768|      1|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6549|      1|      ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, ack, sizeof(ack));
  ------------------
  |  | 6355|      1|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6550|      1|      s_lcpup = false;
 6551|      1|    } break;
 6552|      2|    case MG_PPP_LCP_ECHO_REQ:  // RFC-1661 5.8: must respond
  ------------------
  |  | 6368|      2|#define MG_PPP_LCP_ECHO_REQ 9
  ------------------
  |  Branch (6552:5): [True: 2, False: 9]
  ------------------
 6553|      2|      MG_DEBUG(("LCP echo request of %d bytes, replying...", len));
  ------------------
  |  | 1768|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      2|  do {                      \
  |  |  |  | 1757|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1758|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6554|      2|      lcp->code = MG_PPP_LCP_ECHO_REPLY;
  ------------------
  |  | 6369|      2|#define MG_PPP_LCP_ECHO_REPLY 10
  ------------------
 6555|      2|      ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6355|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6556|      2|      break;
 6557|     11|  }
 6558|     11|}
fuzz.c:_ZL12ppp_tx_frameP11mg_tcpip_iftPhm:
 6514|     24|                           uint8_t *data, size_t datasz) {
 6515|     24|  uint8_t *pay = ppp_tx_frame_header(ifp, proto);
 6516|     24|  memcpy(pay, data, datasz);
 6517|     24|  return ppp_tx_frame_trailer(ifp, datasz, pay + datasz);
 6518|     24|}
fuzz.c:_ZL15ppp_handle_ipcpP11mg_tcpip_ifPhm:
 6576|     36|                            size_t ipcpsz) {
 6577|     36|  uint16_t len;
 6578|     36|  uint8_t id;
 6579|     36|  struct ipcp *ipcp = (struct ipcp *) ipcpp;
 6580|     36|  uint8_t req[] = {
 6581|     36|      MG_PPP_IPCP_CFG_REQ, 0, 0, 10, MG_PPP_IPCP_OPT_IPADDR, 6, 0, 0, 0, 0};
  ------------------
  |  | 6371|     36|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
                    MG_PPP_IPCP_CFG_REQ, 0, 0, 10, MG_PPP_IPCP_OPT_IPADDR, 6, 0, 0, 0, 0};
  ------------------
  |  | 6375|     36|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
 6582|     36|  if (ipcpsz < sizeof(*ipcp)) return;
  ------------------
  |  Branch (6582:7): [True: 1, False: 35]
  ------------------
 6583|     35|  id = ipcp->id;
 6584|     35|  len = mg_ntohs(ipcp->len);
 6585|     35|  if (len < sizeof(*ipcp) || len > ipcpsz) return;
  ------------------
  |  Branch (6585:7): [True: 0, False: 35]
  |  Branch (6585:30): [True: 12, False: 23]
  ------------------
 6586|     23|  switch (ipcp->code) {
  ------------------
  |  Branch (6586:11): [True: 23, False: 0]
  ------------------
 6587|      7|    case MG_PPP_IPCP_CFG_REQ:
  ------------------
  |  | 6371|      7|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
  |  Branch (6587:5): [True: 7, False: 16]
  ------------------
 6588|      7|      MG_VERBOSE(("got IPCP config request, acknowledging..."));
  ------------------
  |  | 1769|      7|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      7|  do {                      \
  |  |  |  | 1757|      7|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 7]
  |  |  |  |  ------------------
  |  |  |  | 1758|      7|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 7]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6589|      7|      if (len >= 10 &&
  ------------------
  |  Branch (6589:11): [True: 7, False: 0]
  ------------------
 6590|      7|          find_opt(MG_PPP_IPCP_OPT_IPADDR, 6, (const uint8_t *) (ipcp + 1),
  ------------------
  |  | 6375|      7|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  |  Branch (6590:11): [True: 3, False: 4]
  ------------------
 6591|      7|                   len - sizeof(*ipcp), (uint8_t *) &ifp->gw)) {
 6592|      3|        MG_DEBUG(("IPCP cfg, GW IP: %M", mg_print_ip4, &ifp->gw));
  ------------------
  |  | 1768|      3|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      3|  do {                      \
  |  |  |  | 1757|      3|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  |  | 1758|      3|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6593|      3|        ipcp->code = MG_PPP_IPCP_CFG_ACK;
  ------------------
  |  | 6372|      3|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
 6594|      4|      } else if (ifp->gw == 0) {
  ------------------
  |  Branch (6594:18): [True: 0, False: 4]
  ------------------
 6595|      0|        MG_ERROR(("Peer did not provide its IP address"));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6596|       |        // NOTE: We should NACK with an added option, probably we can just store
 6597|       |        // the incoming address and offer a statically configured ifp->gw when
 6598|       |        // theirs == 0, but it is unlikely to find such a dumb PPP server and it
 6599|       |        // will complicate our config and this protocol state machine
 6600|      0|        ipcp->code = MG_PPP_IPCP_CFG_REJECT;
  ------------------
  |  | 6374|      0|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
 6601|      0|        ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6356|      0|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6602|      0|      }
 6603|      7|      ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6356|      7|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6604|      7|      req[1] = id;
 6605|      7|      memcpy(req + 6, &ifp->ip, 4);  // Request config IP address or 0.0.0.0
 6606|      7|      ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, req, sizeof(req));
  ------------------
  |  | 6356|      7|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6607|      7|      break;
 6608|      0|    case MG_PPP_IPCP_CFG_ACK:
  ------------------
  |  | 6372|      0|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
  |  Branch (6608:5): [True: 0, False: 23]
  ------------------
 6609|       |      // Our peer accepted our IP address
 6610|      0|      MG_VERBOSE(("got IPCP config ack"));
  ------------------
  |  | 1769|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6611|      0|      ifp->mask = 0xffffffff;  // send to gw
 6612|      0|      ifp->state = MG_TCPIP_STATE_IP;
  ------------------
  |  | 4762|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
 6613|      0|      ifp->gw_ready = true;
 6614|      0|      break;
 6615|     15|    case MG_PPP_IPCP_CFG_NACK:
  ------------------
  |  | 6373|     15|#define MG_PPP_IPCP_CFG_NACK 3
  ------------------
  |  Branch (6615:5): [True: 15, False: 8]
  ------------------
 6616|     15|      MG_VERBOSE(("got IPCP config nack"));
  ------------------
  |  | 1769|     15|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|     15|  do {                      \
  |  |  |  | 1757|     15|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 15]
  |  |  |  |  ------------------
  |  |  |  | 1758|     15|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 15]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6617|       |      // NACK contains our "suggested" IP address, use it
 6618|     15|      if (len >= 10 &&
  ------------------
  |  Branch (6618:11): [True: 11, False: 4]
  ------------------
 6619|     11|          find_opt(MG_PPP_IPCP_OPT_IPADDR, 6, (const uint8_t *) (ipcp + 1),
  ------------------
  |  | 6375|     11|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  |  Branch (6619:11): [True: 2, False: 9]
  ------------------
 6620|     11|                   len - sizeof(*ipcp), (uint8_t *) &ifp->ip)) {
 6621|      2|        MG_DEBUG(("IPCP cfg, IP: %M", mg_print_ip4, &ifp->ip));
  ------------------
  |  | 1768|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      2|  do {                      \
  |  |  |  | 1757|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1758|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6622|      2|        ipcp->code = MG_PPP_IPCP_CFG_REQ;
  ------------------
  |  | 6371|      2|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
 6623|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6356|      2|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6624|      2|      }
 6625|     15|      break;
 6626|      1|    case MG_PPP_IPCP_CFG_REJECT:
  ------------------
  |  | 6374|      1|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
  |  Branch (6626:5): [True: 1, False: 22]
  ------------------
 6627|      1|      MG_ERROR(("Peer rejected our IP address, need to properly set ifp->ip"));
  ------------------
  |  | 1766|      1|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6628|      1|      break;
 6629|     23|  }
 6630|     23|}
fuzz.c:_ZL8find_opthhPKhmPh:
 6561|     18|                     const uint8_t *opts, size_t optslen, uint8_t *dest) {
 6562|     18|  uint8_t *p = (uint8_t *) opts;
 6563|    115|  while (optslen >= 2) {  // parse options for requested one
  ------------------
  |  Branch (6563:10): [True: 111, False: 4]
  ------------------
 6564|    111|    if (p[1] > optslen || p[1] < 2) return false;  // truncated / malformed
  ------------------
  |  Branch (6564:9): [True: 5, False: 106]
  |  Branch (6564:27): [True: 4, False: 102]
  ------------------
 6565|    102|    if (p[0] == opt && p[1] == optlen) {
  ------------------
  |  Branch (6565:9): [True: 53, False: 49]
  |  Branch (6565:24): [True: 5, False: 48]
  ------------------
 6566|      5|      memcpy(dest, p + 2, optlen - 2);
 6567|      5|      return true;
 6568|      5|    }
 6569|     97|    optslen -= p[1];
 6570|     97|    p += p[1];
 6571|     97|  }
 6572|      4|  return false;
 6573|     18|}
fuzz.c:_ZL19ppp_tx_frame_headerP11mg_tcpip_ift:
 6497|  1.12k|static uint8_t *ppp_tx_frame_header(struct mg_tcpip_if *ifp, uint16_t proto) {
 6498|  1.12k|  uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 6499|  1.12k|  if (ifp->l2type == MG_TCPIP_L2_PPP)
  ------------------
  |  Branch (6499:7): [True: 1.12k, False: 3]
  ------------------
 6500|  1.12k|    return ppp_header(proto, hdlc_header(l2p));
 6501|      3|  return ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
 6502|      3|                                        s_id, (struct mg_l2addr *) ifp->mac,
 6503|      3|                                        (struct mg_l2addr *) ifp->gwmac, l2p));
 6504|  1.12k|}
fuzz.c:_ZL20ppp_tx_frame_trailerP11mg_tcpip_ifmPh:
 6506|  1.12k|                                   uint8_t *cur) {
 6507|  1.12k|  return mg_l2_driver_output(ifp, ifp->l2type == MG_TCPIP_L2_PPPoE
  ------------------
  |  Branch (6507:35): [True: 3, False: 1.12k]
  ------------------
 6508|  1.12k|                                      ? mg_l2_pppoe_trailer(ifp, len, cur)
 6509|  1.12k|                                      : mg_l2_ppp_trailer(ifp, len, cur));
 6510|  1.12k|}
fuzz.c:_ZL14pppoe_tx_frameP11mg_tcpip_ifhtPhmP9mg_l2addr:
 6815|      1|                             struct mg_l2addr *dst) {
 6816|      1|  uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 6817|      1|  uint8_t *p = pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_DISC, code, id,
 6818|      1|                            (struct mg_l2addr *) ifp->mac, dst, l2p);
 6819|      1|  memmove(p, data, datasz);
 6820|      1|  return mg_l2_driver_output(ifp, pppoe_trailer(ifp, datasz, p + datasz));
 6821|      1|}
fuzz.c:_ZL4logsPKcm:
 7223|  16.7k|static void logs(const char *buf, size_t len) {
 7224|  16.7k|  size_t i;
 7225|  96.4k|  for (i = 0; i < len; i++) logc(((unsigned char *) buf)[i]);
  ------------------
  |  Branch (7225:15): [True: 79.6k, False: 16.7k]
  ------------------
 7226|  16.7k|}
fuzz.c:_ZL4logch:
 7219|   199k|static void logc(unsigned char c) {
 7220|   199k|  s_log_func((char) c, s_log_func_param);
 7221|   199k|}
fuzz.c:_ZL6nibblej:
 7252|  81.0k|static unsigned char nibble(unsigned c) {
 7253|  81.0k|  return (unsigned char) (c < 10 ? c + '0' : c + 'W');
  ------------------
  |  Branch (7253:27): [True: 64.5k, False: 16.4k]
  ------------------
 7254|  81.0k|}
fuzz.c:_ZL20mqtt_prop_type_by_idh:
 8020|  6.29k|static int mqtt_prop_type_by_id(uint8_t prop_id) {
 8021|  6.29k|  size_t i, num_properties = sizeof(s_prop_map) / sizeof(s_prop_map[0]);
 8022|   127k|  for (i = 0; i < num_properties; ++i) {
  ------------------
  |  Branch (8022:15): [True: 127k, False: 100]
  ------------------
 8023|   127k|    if (s_prop_map[i].id == prop_id) return s_prop_map[i].type;
  ------------------
  |  Branch (8023:9): [True: 6.19k, False: 120k]
  ------------------
 8024|   127k|  }
 8025|    100|  return -1;  // Property ID not found
 8026|  6.29k|}
fuzz.c:_ZL13decode_varintPKhmPj:
 8008|    992|static size_t decode_varint(const uint8_t *buf, size_t len, uint32_t *value) {
 8009|    992|  uint32_t mul = 1, ofs;
 8010|    992|  *value = 0;
 8011|  1.22k|  for (ofs = 0; ofs < 4 && ofs < len; ofs++) {
  ------------------
  |  Branch (8011:17): [True: 1.20k, False: 18]
  |  Branch (8011:28): [True: 1.18k, False: 16]
  ------------------
 8012|  1.18k|    uint8_t enc_byte = buf[ofs];
 8013|  1.18k|    *value += (enc_byte & 0x7f) * mul;
 8014|  1.18k|    mul *= 128;
 8015|  1.18k|    if ((enc_byte & 0x80) == 0) return ofs + 1;
  ------------------
  |  Branch (8015:9): [True: 958, False: 231]
  ------------------
 8016|  1.18k|  }
 8017|     34|  return 0;
 8018|    992|}
fuzz.c:_ZL8mg_atone6mg_strP7mg_addr:
 8594|  5.56k|static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
 8595|  5.56k|  if (str.len > 0) return false;
  ------------------
  |  Branch (8595:7): [True: 5.56k, False: 0]
  ------------------
 8596|      0|  memset(addr->addr.ip, 0, sizeof(addr->addr.ip));
 8597|      0|  addr->is_ip6 = false;
 8598|      0|  return true;
 8599|  5.56k|}
fuzz.c:_ZL8mg_atonl6mg_strP7mg_addr:
 8586|  5.56k|static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
 8587|  5.56k|  uint32_t localhost = mg_htonl(0x7f000001);
  ------------------
  |  | 2038|  5.56k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 8588|  5.56k|  if (mg_strcasecmp(str, mg_str("localhost")) != 0) return false;
  ------------------
  |  | 1467|  5.56k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (8588:7): [True: 0, False: 5.56k]
  ------------------
 8589|  5.56k|  memcpy(addr->addr.ip, &localhost, sizeof(uint32_t));
 8590|  5.56k|  addr->is_ip6 = false;
 8591|  5.56k|  return true;
 8592|  5.56k|}
fuzz.c:_ZL13driver_outputP11mg_tcpip_ifm:
 9292|  5.56k|static size_t driver_output(struct mg_tcpip_if *ifp, size_t len) {
 9293|  5.56k|  size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
 9294|  5.56k|  if (n == len) ifp->nsent++;
  ------------------
  |  Branch (9294:7): [True: 5.56k, False: 0]
  ------------------
 9295|  5.56k|  return n;
 9296|  5.56k|}
fuzz.c:_ZL5tx_ipP11mg_tcpip_ifPhhhjjm:
 9346|  5.56k|                        size_t plen) {
 9347|       |  // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt
 9348|  5.56k|  uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 9349|  5.56k|  struct ip *ip = (struct ip *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV4,
 9350|  5.56k|                                             ifp->mac, l2_dst, l2p);
 9351|  5.56k|  memset(ip, 0, sizeof(*ip));
 9352|  5.56k|  ip->ver = 0x45;  // Version 4, header length 5 words
 9353|  5.56k|  ip->tos = (uint8_t) (dscp << 2);
 9354|  5.56k|  ip->frag = mg_htons(0x4000);  // Don't fragment
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9355|  5.56k|  ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9356|  5.56k|  ip->ttl = 64;
 9357|  5.56k|  ip->proto = proto;
 9358|  5.56k|  ip->src = ip_src;
 9359|  5.56k|  ip->dst = ip_dst;
 9360|  5.56k|  ip->csum = ipcsum(ip, sizeof(*ip));
 9361|  5.56k|  return ip;
 9362|  5.56k|}
fuzz.c:_ZL6ipcsumPKvm:
 9179|  5.59k|static uint16_t ipcsum(const void *buf, size_t len) {
 9180|  5.59k|  uint32_t sum = csumup(0, buf, len);
 9181|  5.59k|  return csumfin(sum);
 9182|  5.59k|}
fuzz.c:_ZL6csumupjPKvm:
 9167|  16.7k|static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
 9168|  16.7k|  size_t i;
 9169|  16.7k|  const uint8_t *p = (const uint8_t *) buf;
 9170|   328k|  for (i = 0; i < len; i++) sum += i & 1 ? p[i] : ((uint32_t) p[i]) << 8;
  ------------------
  |  Branch (9170:15): [True: 312k, False: 16.7k]
  |  Branch (9170:36): [True: 156k, False: 156k]
  ------------------
 9171|  16.7k|  return sum;
 9172|  16.7k|}
fuzz.c:_ZL7csumfinj:
 9174|  11.1k|static uint16_t csumfin(uint32_t sum) {
 9175|  22.3k|  while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
  ------------------
  |  Branch (9175:10): [True: 11.1k, False: 11.1k]
  ------------------
 9176|  11.1k|  return mg_htons((uint16_t) ((uint16_t) ~sum & 0xffff));
  ------------------
  |  | 2037|  11.1k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9177|  11.1k|}
fuzz.c:_ZL5pcsumPvS_m:
 9193|  5.56k|static uint16_t pcsum(void *d, void *p, size_t plen) {
 9194|  5.56k|  uint32_t sum;
 9195|  5.56k|  struct ip *ip = (struct ip *) d;
 9196|       |#if defined(__DCC__)
 9197|       |  volatile /* Makes PPC & Diab4.3 happy */
 9198|       |#endif
 9199|  5.56k|      struct pseudoip pip;
 9200|  5.56k|  pip.src = ip->src;
 9201|  5.56k|  pip.dst = ip->dst;
 9202|  5.56k|  pip.zero = 0;
 9203|  5.56k|  pip.proto = ip->proto;
 9204|  5.56k|  pip.len = mg_htons((uint16_t) plen);
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9205|  5.56k|  sum = csumup(0, &pip, sizeof(pip));  // even length
 9206|  5.56k|  sum = csumup(sum, p, plen);          // possibly odd length: last
 9207|  5.56k|  return csumfin(sum);
 9208|  5.56k|}
fuzz.c:_ZL6tx_tcpP11mg_tcpip_ifPhP7mg_addrS3_hhjjtPKvm:
10159|  5.56k|                     uint16_t win, const void *buf, size_t len) {
10160|  5.56k|  uint8_t *l3p;
10161|  5.56k|  struct ip *ip = NULL;
10162|  5.56k|  struct tcp *tcp;
10163|  5.56k|  uint16_t opts[4 / 2];
10164|  5.56k|  size_t hlen = sizeof(*tcp);
10165|       |#if MG_ENABLE_IPV6
10166|       |  struct ip6 *ip6 = NULL;
10167|       |#endif
10168|       |
10169|       |  // Handle any options first, here, to determine header size
10170|  5.56k|  if (flags & TH_SYN) {  // Send MSS
  ------------------
  |  | 9046|  5.56k|#define TH_SYN 0x02
  ------------------
  |  Branch (10170:7): [True: 5.56k, False: 0]
  ------------------
10171|  5.56k|    uint16_t mss;
10172|       |#if MG_ENABLE_IPV6  // RFC-9293 3.7.1; RFC-6691 2
10173|       |    mss = (uint16_t) (ifp->mtu - 60);
10174|       |#else
10175|  5.56k|    mss = (uint16_t) (ifp->mtu - 40);
10176|  5.56k|#endif
10177|  5.56k|    opts[0] = mg_htons(0x0204);  // RFC-9293 3.2
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
10178|  5.56k|    opts[1] = mg_htons(mss);
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
10179|  5.56k|    hlen += sizeof(opts);  // always whole number of 32-bit words
10180|  5.56k|  }
10181|       |
10182|       |#if MG_ENABLE_IPV6
10183|       |  if (ip_dst->is_ip6) {
10184|       |    ip6 = tx_ip6(ifp, l2_dst, 6, dscp, ip_src->addr.ip6, ip_dst->addr.ip6,
10185|       |                 hlen + len);
10186|       |    tcp = (struct tcp *) (ip6 + 1);
10187|       |    l3p = (uint8_t *) ip6;
10188|       |  } else
10189|       |#endif
10190|  5.56k|  {
10191|  5.56k|    ip = tx_ip(ifp, l2_dst, 6, dscp, ip_src->addr.ip4, ip_dst->addr.ip4,
10192|  5.56k|               hlen + len);
10193|  5.56k|    tcp = (struct tcp *) (ip + 1);
10194|  5.56k|    l3p = (uint8_t *) ip;
10195|  5.56k|  }
10196|  5.56k|  memset(tcp, 0, sizeof(*tcp));
10197|  5.56k|  memmove(tcp + 1, opts, hlen - sizeof(*tcp));  // copy opts if any
10198|  5.56k|  if (buf != NULL && len) memmove((uint8_t *) tcp + hlen, buf, len);
  ------------------
  |  Branch (10198:7): [True: 0, False: 5.56k]
  |  Branch (10198:22): [True: 0, False: 0]
  ------------------
10199|  5.56k|  tcp->sport = ip_src->port;
10200|  5.56k|  tcp->dport = ip_dst->port;
10201|  5.56k|  tcp->seq = seq;
10202|  5.56k|  tcp->ack = ack;
10203|  5.56k|  tcp->flags = flags;
10204|  5.56k|  tcp->win = mg_htons(win);
  ------------------
  |  | 2037|  5.56k|#define mg_htons(x) mg_ntohs(x)
  ------------------
10205|  5.56k|  tcp->off = (uint8_t) (hlen / 4 << 4);
10206|       |#if MG_ENABLE_IPV6
10207|       |  if (ip_dst->is_ip6) {
10208|       |    tcp->csum = p6csum(ip6, tcp, 6, hlen + len);
10209|       |  } else
10210|       |#endif
10211|  5.56k|  {
10212|  5.56k|    tcp->csum = pcsum(ip, tcp, hlen + len);
10213|  5.56k|  }
10214|  5.56k|  MG_VERBOSE(("TCP %M -> %M fl %x len %u", mg_print_ip_port, ip_src,
  ------------------
  |  | 1769|  5.56k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|  5.56k|  do {                      \
  |  |  |  | 1757|  5.56k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  5.56k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 5.56k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10215|  5.56k|              mg_print_ip_port, ip_dst, tcp->flags, len));
10216|  5.56k|  return driver_output(
10217|  5.56k|      ifp, mg_l2_trailer(ifp, PDIFF(l3p, (uint8_t *) tcp + hlen + len),
  ------------------
  |  | 8914|  5.56k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
10218|  5.56k|                         (uint8_t *) tcp + hlen + len));
10219|  5.56k|}
fuzz.c:_ZL8settmoutP13mg_connectionh:
 9278|  10.5k|static void settmout(struct mg_connection *c, uint8_t type) {
 9279|  10.5k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
 9280|  10.5k|  struct connstate *s = (struct connstate *) (c + 1);
 9281|  10.5k|  unsigned n = type == MIP_TTYPE_ACK   ? MG_TCPIP_ACK_MS
  ------------------
  |  | 8955|  10.5k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
                unsigned n = type == MIP_TTYPE_ACK   ? MG_TCPIP_ACK_MS
  ------------------
  |  | 8920|      0|#define MG_TCPIP_ACK_MS 150    // Timeout for ACKing
  ------------------
  |  Branch (9281:16): [True: 0, False: 10.5k]
  ------------------
 9282|  10.5k|               : type == MIP_TTYPE_ARP ? MG_TCPIP_ARP_MS
  ------------------
  |  | 8956|  10.5k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_ARP ? MG_TCPIP_ARP_MS
  ------------------
  |  | 8921|      0|#define MG_TCPIP_ARP_MS 100    // Timeout for ARP response
  ------------------
  |  Branch (9282:18): [True: 0, False: 10.5k]
  ------------------
 9283|  10.5k|               : type == MIP_TTYPE_SYN ? MG_TCPIP_SYN_MS
  ------------------
  |  | 8957|  10.5k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_SYN ? MG_TCPIP_SYN_MS
  ------------------
  |  | 8922|  5.56k|#define MG_TCPIP_SYN_MS 15000  // Timeout for connection establishment
  ------------------
  |  Branch (9283:18): [True: 5.56k, False: 4.96k]
  ------------------
 9284|  10.5k|               : type == MIP_TTYPE_FIN ? MG_TCPIP_FIN_MS
  ------------------
  |  | 8958|  4.96k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
                             : type == MIP_TTYPE_FIN ? MG_TCPIP_FIN_MS
  ------------------
  |  | 8923|      0|#define MG_TCPIP_FIN_MS 1000   // Timeout for closing connection
  ------------------
  |  Branch (9284:18): [True: 0, False: 4.96k]
  ------------------
 9285|  4.96k|                                       : MG_TCPIP_KEEPALIVE_MS;
  ------------------
  |  | 8917|  15.4k|#define MG_TCPIP_KEEPALIVE_MS 45000  // TCP keep-alive period, ms
  ------------------
 9286|  10.5k|  if (s->ttype == MIP_TTYPE_FIN) return;  // skip if 3-way closing
  ------------------
  |  | 8958|  10.5k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (9286:7): [True: 0, False: 10.5k]
  ------------------
 9287|  10.5k|  s->timer = ifp->now + n;
 9288|  10.5k|  s->ttype = type;
 9289|  10.5k|  MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
  ------------------
  |  | 1769|  10.5k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|  10.5k|  do {                      \
  |  |  |  | 1757|  10.5k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 10.5k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  10.5k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 10.5k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9290|  10.5k|}
fuzz.c:_ZL10close_connP13mg_connection:
11202|  5.56k|static void close_conn(struct mg_connection *c) {
11203|  5.56k|  struct connstate *s = (struct connstate *) (c + 1);
11204|  5.56k|  mg_iobuf_free(&s->txq);
11205|  5.56k|  mg_close_conn(c);
11206|  5.56k|}
fuzz.c:_ZL15l2addr_resolvedP13mg_connection:
11222|  5.56k|static void l2addr_resolved(struct mg_connection *c) {
11223|  5.56k|  if (c->is_udp) {
  ------------------
  |  Branch (11223:7): [True: 0, False: 5.56k]
  ------------------
11224|      0|    c->is_connecting = 0;
11225|      0|    mg_call(c, MG_EV_CONNECT, NULL);
11226|  5.56k|  } else {
11227|  5.56k|    send_syn(c);
11228|  5.56k|    settmout(c, MIP_TTYPE_SYN);
  ------------------
  |  | 8957|  5.56k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
11229|  5.56k|  }
11230|  5.56k|}
fuzz.c:_ZL8send_synP13mg_connection:
11215|  5.56k|static void send_syn(struct mg_connection *c) {
11216|  5.56k|  struct connstate *s = (struct connstate *) (c + 1);
11217|  5.56k|  uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
  ------------------
  |  | 2038|  5.56k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11218|  5.56k|  tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_SYN, isn, 0,
  ------------------
  |  | 9046|  5.56k|#define TH_SYN 0x02
  ------------------
11219|  5.56k|         MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8930|  5.56k|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
11220|  5.56k|}
fuzz.c:_ZL13mg_tcpip_pollP11mg_tcpip_ifm:
11030|  5.56k|static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
11031|  5.56k|  struct mg_connection *c;
11032|  5.56k|  bool expired_1000ms = mg_timer_expired(&ifp->timer_1000ms, 1000, now);
11033|  5.56k|  ifp->now = now;
11034|       |
11035|  5.56k|  if (expired_1000ms) {
  ------------------
  |  Branch (11035:7): [True: 5.56k, False: 0]
  ------------------
11036|       |#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
11037|       |    const char *names[] = {"down", "lnk up", "lnk rdy", "req", "ip", "ready"};
11038|       |    size_t max = sizeof(names) / sizeof(char *);
11039|       |    unsigned int state = ifp->state >= max ? max - 1 : ifp->state;
11040|       |    MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", names[state],
11041|       |             mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent, ifp->ndrop,
11042|       |             ifp->nerr));
11043|       |#if MG_ENABLE_IPV6
11044|       |    state = ifp->state6 >= max ? max - 1 : ifp->state6;
11045|       |    if (state > MG_TCPIP_STATE_UP)
11046|       |      MG_INFO(("Status: %s, IPv6: %M", names[state], mg_print_ip6, &ifp->ip6));
11047|       |#endif
11048|       |#endif
11049|  5.56k|    backlog_poll(ifp->mgr);
11050|  5.56k|  }
11051|       |  // Handle gw ARP request timeout, order is important
11052|  5.56k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4762|  5.56k|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (11052:7): [True: 5.56k, False: 0]
  |  Branch (11052:25): [True: 0, False: 5.56k]
  ------------------
11053|      0|    ifp->state = MG_TCPIP_STATE_READY;  // gw MAC not resolved, we'll retry
  ------------------
  |  | 4763|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
11054|      0|    onstatechange(ifp);
11055|      0|  }
11056|  5.56k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_READY && !ifp->gw_ready &&
  ------------------
  |  | 4763|  11.1k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (11056:7): [True: 5.56k, False: 0]
  |  Branch (11056:25): [True: 5.56k, False: 0]
  |  Branch (11056:63): [True: 0, False: 5.56k]
  ------------------
11057|      0|      ifp->gw != 0)
  ------------------
  |  Branch (11057:7): [True: 0, False: 0]
  ------------------
11058|      0|    mg_tcpip_arp_request(ifp, ifp->gw, NULL);  // retry GW ARP request
11059|       |#if MG_ENABLE_IPV6
11060|       |  // Handle gw NS/NA req/resp timeout, order is important
11061|       |  if (expired_1000ms && ifp->state6 == MG_TCPIP_STATE_IP) {
11062|       |    ifp->state6 = MG_TCPIP_STATE_READY;  // gw6 MAC not resolved, we'll retry
11063|       |    onstate6change(ifp);
11064|       |  }
11065|       |  if (expired_1000ms && ifp->state6 == MG_TCPIP_STATE_READY && !ifp->gw6_ready &&
11066|       |      (ifp->gw6[0] != 0 || ifp->gw6[1] != 0))
11067|       |    tx_ndp_ns(ifp, ifp->gw6, NULL);  // retry GW hwaddr resolution
11068|       |#endif
11069|       |
11070|  5.56k|  {  // poll driver and let L2 do its work, if any
11071|       |    // Handle physical interface up/down status
11072|  5.56k|    bool drv_up, l2_up;
11073|  5.56k|    drv_up = ifp->driver->poll ? ifp->driver->poll(ifp, expired_1000ms) : true;
  ------------------
  |  Branch (11073:14): [True: 5.56k, False: 0]
  ------------------
11074|  5.56k|    l2_up = mg_l2_poll(ifp, expired_1000ms);  // Handle L2 up/down link status;
11075|  5.56k|    if (expired_1000ms) {                     // ifp->state rules over state6
  ------------------
  |  Branch (11075:9): [True: 5.56k, False: 0]
  ------------------
11076|  5.56k|      mg_ip_link(ifp, drv_up, l2_up);         // Handle IPv4
11077|  5.56k|      mg_ip6_link(ifp, drv_up, l2_up);        // Handle IPv6
11078|  5.56k|      if (ifp->state < MG_TCPIP_STATE_UP) MG_ERROR(("Network is down"));
  ------------------
  |  | 4760|  5.56k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
                    if (ifp->state < MG_TCPIP_STATE_UP) MG_ERROR(("Network is down"));
  ------------------
  |  | 1766|    591|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|    591|  do {                      \
  |  |  |  | 1757|    591|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 591]
  |  |  |  |  ------------------
  |  |  |  | 1758|    591|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 591]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (11078:11): [True: 591, False: 4.96k]
  ------------------
11079|  5.56k|      mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
11080|  5.56k|    }
11081|  5.56k|  }
11082|       |
11083|  5.56k|  mg_ip_poll(ifp, expired_1000ms);   // Handle IPv4
11084|  5.56k|  mg_ip6_poll(ifp, expired_1000ms);  // Handle IPv6
11085|       |
11086|       |  // Read data from the network (mg_tcpip_rx() will discard for us)
11087|  5.56k|  if (ifp->driver->rx != NULL) {  // Simple polling driver, returns one frame
  ------------------
  |  Branch (11087:7): [True: 5.56k, False: 0]
  ------------------
11088|  5.56k|    size_t len =
11089|  5.56k|        ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
11090|  5.56k|    if (len > 0) {
  ------------------
  |  Branch (11090:9): [True: 0, False: 5.56k]
  ------------------
11091|      0|      ifp->nrecv++;
11092|      0|      mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
11093|      0|    }
11094|  5.56k|  } else {  // Complex poll / Interrupt-based driver. Queues recvd frames
11095|      0|    char *buf;
11096|      0|    size_t len, cnt = 7;  // Max 7 packets to fetch
11097|      0|    while (cnt-- > 0 && (len = mg_queue_next(&ifp->recv_queue, &buf)) > 0) {
  ------------------
  |  Branch (11097:12): [True: 0, False: 0]
  |  Branch (11097:25): [True: 0, False: 0]
  ------------------
11098|      0|      mg_tcpip_rx(ifp, buf, len);
11099|      0|      mg_queue_del(&ifp->recv_queue, len);
11100|      0|    }
11101|      0|  }
11102|  5.56k|  if (ifp->state < MG_TCPIP_STATE_UP) return;  // need to let L2 do its job
  ------------------
  |  | 4760|  5.56k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (11102:7): [True: 591, False: 4.96k]
  ------------------
11103|       |
11104|       |  // Process timeouts
11105|  9.93k|  for (c = ifp->mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (11105:29): [True: 4.96k, False: 4.96k]
  ------------------
11106|  4.96k|    struct connstate *s = (struct connstate *) (c + 1);
11107|  4.96k|    if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
  ------------------
  |  Branch (11107:10): [True: 0, False: 4.96k]
  |  Branch (11107:23): [True: 0, False: 0]
  |  Branch (11107:45): [True: 0, False: 4.96k]
  |  Branch (11107:64): [True: 0, False: 4.96k]
  ------------------
11108|      0|      continue;
11109|  4.96k|    if (!c->is_full && s->is_full) {
  ------------------
  |  Branch (11109:9): [True: 4.96k, False: 0]
  |  Branch (11109:24): [True: 0, False: 4.96k]
  ------------------
11110|       |      // Application resumed the connection: advertise the restored window
11111|      0|      s->is_full = false;
11112|      0|      tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 9049|      0|#define TH_ACK 0x10
  ------------------
                    tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11113|      0|             mg_htonl(s->ack), MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                           mg_htonl(s->ack), MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8930|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
11114|      0|    }
11115|  4.96k|    if (s->retransmit && s->txq.len > 0 && ifp->now > s->txq_timer) {
  ------------------
  |  Branch (11115:9): [True: 0, False: 4.96k]
  |  Branch (11115:26): [True: 0, False: 0]
  |  Branch (11115:44): [True: 0, False: 0]
  ------------------
11116|      0|      if (s->txq_retries < 255) s->txq_retries++;
  ------------------
  |  Branch (11116:11): [True: 0, False: 0]
  ------------------
11117|       |      // R1 reports a delivery problem; it does not close (RFC-9293, 3.8.3).
11118|      0|      if (s->txq_retries == MG_TCPIP_RTX_R1)
  ------------------
  |  | 8926|      0|#define MG_TCPIP_RTX_R1 3  // Delivery-problem threshold (RFC-9293, 3.8.3)
  ------------------
  |  Branch (11118:11): [True: 0, False: 0]
  ------------------
11119|      0|        MG_ERROR(("%lu retransmit", c->id));
  ------------------
  |  | 1766|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11120|      0|      retransmit(c);
11121|      0|    }
11122|  4.96k|    if (ifp->now > s->timer) {
  ------------------
  |  Branch (11122:9): [True: 4.96k, False: 0]
  ------------------
11123|  4.96k|      if (s->ttype == MIP_TTYPE_ARP) {
  ------------------
  |  | 8956|  4.96k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
  |  Branch (11123:11): [True: 0, False: 4.96k]
  ------------------
11124|      0|        proto_error(c, false, "ARP timeout");
11125|  4.96k|      } else if (c->is_udp) {
  ------------------
  |  Branch (11125:18): [True: 0, False: 4.96k]
  ------------------
11126|      0|        continue;
11127|  4.96k|      } else if (s->ttype == MIP_TTYPE_ACK && s->acked != s->ack) {
  ------------------
  |  | 8955|  9.93k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
  |  Branch (11127:18): [True: 0, False: 4.96k]
  |  Branch (11127:47): [True: 0, False: 0]
  ------------------
11128|      0|        MG_VERBOSE(("%lu ack %x %x", c->id, s->seq, s->ack));
  ------------------
  |  | 1769|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11129|      0|        tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 9049|      0|#define TH_ACK 0x10
  ------------------
                      tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11130|      0|               mg_htonl(s->ack), s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                             mg_htonl(s->ack), s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8930|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (11130:34): [True: 0, False: 0]
  ------------------
11131|      0|        s->acked = s->ack;
11132|  4.96k|      } else if (s->ttype == MIP_TTYPE_SYN) {
  ------------------
  |  | 8957|  4.96k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
  |  Branch (11132:18): [True: 4.96k, False: 0]
  ------------------
11133|  4.96k|        proto_error(c, false, "Connection timeout");
11134|  4.96k|      } else if (s->ttype == MIP_TTYPE_FIN) {
  ------------------
  |  | 8958|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (11134:18): [True: 0, False: 0]
  ------------------
11135|      0|        s->is_closing = 1;
11136|      0|        continue;
11137|      0|      } else {
11138|      0|        if (s->tmiss++ > 2) {
  ------------------
  |  Branch (11138:13): [True: 0, False: 0]
  ------------------
11139|      0|          proto_error(c, false, "keepalive");
11140|      0|        } else {
11141|      0|          MG_VERBOSE(("%lu keepalive", c->id));
  ------------------
  |  | 1769|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11142|      0|          tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK,
  ------------------
  |  | 9049|      0|#define TH_ACK 0x10
  ------------------
11143|      0|                 mg_htonl(s->seq - 1), mg_htonl(s->ack),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                               mg_htonl(s->seq - 1), mg_htonl(s->ack),
  ------------------
  |  | 2038|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11144|      0|                 s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8930|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (11144:18): [True: 0, False: 0]
  ------------------
11145|      0|        }
11146|      0|      }
11147|       |
11148|  4.96k|      settmout(c, MIP_TTYPE_KEEPALIVE);
  ------------------
  |  | 8954|  4.96k|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
11149|  4.96k|    }
11150|  4.96k|  }
11151|  4.96k|}
fuzz.c:_ZL12backlog_pollP6mg_mgr:
10630|  5.56k|static void backlog_poll(struct mg_mgr *mgr) {
10631|  5.56k|  struct mg_connection *c = NULL;
10632|  11.1k|  for (c = mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (10632:24): [True: 5.56k, False: 5.56k]
  ------------------
10633|  5.56k|    if (!c->is_udp && c->is_listening) backlog_maintain(c);
  ------------------
  |  Branch (10633:9): [True: 5.56k, False: 0]
  |  Branch (10633:23): [True: 0, False: 5.56k]
  ------------------
10634|  5.56k|  }
10635|  5.56k|}
fuzz.c:_ZL13onstatechangeP11mg_tcpip_if:
 9313|    591|static void onstatechange(struct mg_tcpip_if *ifp) {
 9314|    591|  if (ifp->state == MG_TCPIP_STATE_IP &&
  ------------------
  |  | 4762|  1.18k|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9314:7): [True: 0, False: 591]
  ------------------
 9315|      0|      (ifp->l2type == MG_TCPIP_L2_PPP || ifp->l2type == MG_TCPIP_L2_PPPoE))
  ------------------
  |  Branch (9315:8): [True: 0, False: 0]
  |  Branch (9315:42): [True: 0, False: 0]
  ------------------
 9316|      0|    ifp->state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4763|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
 9317|    591|  if (ifp->state == MG_TCPIP_STATE_READY) {
  ------------------
  |  | 4763|    591|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (9317:7): [True: 0, False: 591]
  ------------------
 9318|      0|    MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
  ------------------
  |  | 1767|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9319|      0|    MG_INFO(("       GW: %M", mg_print_ip4, &ifp->gw));
  ------------------
  |  | 1767|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9320|      0|    if (ifp->l2type == MG_TCPIP_L2_ETH ||
  ------------------
  |  Branch (9320:9): [True: 0, False: 0]
  ------------------
 9321|      0|        ifp->l2type == MG_TCPIP_L2_PPPoE)  // TODO(): print other l2
  ------------------
  |  Branch (9321:9): [True: 0, False: 0]
  ------------------
 9322|      0|      MG_INFO(("      MAC: %M", mg_print_mac, ifp->mac));
  ------------------
  |  | 1767|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9323|      0|    if (ifp->l2type == MG_TCPIP_L2_ETH)
  ------------------
  |  Branch (9323:9): [True: 0, False: 0]
  ------------------
 9324|      0|      mg_tcpip_arp_request(ifp, ifp->ip, ifp->mac);  // gratuitous ARP annc
 9325|      0|    if (ifp->is_ip_changed) {
  ------------------
  |  Branch (9325:9): [True: 0, False: 0]
  ------------------
 9326|      0|      struct mg_connection *c;
 9327|      0|      for (c = ifp->mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (9327:33): [True: 0, False: 0]
  ------------------
 9328|      0|        if (!c->is_listening && !c->is_udp) c->is_closing = 1;
  ------------------
  |  Branch (9328:13): [True: 0, False: 0]
  |  Branch (9328:33): [True: 0, False: 0]
  ------------------
 9329|      0|      }
 9330|      0|      ifp->is_ip_changed = false;
 9331|      0|    }
 9332|    591|  } else if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4762|    591|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9332:14): [True: 0, False: 591]
  ------------------
 9333|      0|    if (ifp->l2type == MG_TCPIP_L2_ETH) {
  ------------------
  |  Branch (9333:9): [True: 0, False: 0]
  ------------------
 9334|      0|      ifp->gw_ready = false;  // remove any prior state
 9335|      0|      if (ifp->gw != 0)  // send an unsolicited GW ARP request
  ------------------
  |  Branch (9335:11): [True: 0, False: 0]
  ------------------
 9336|      0|        mg_tcpip_arp_request(ifp, ifp->gw, NULL);
 9337|      0|    }
 9338|    591|  } else if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 4760|    591|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (9338:14): [True: 0, False: 591]
  ------------------
 9339|      0|    srand((unsigned int) mg_millis());
 9340|      0|  }
 9341|    591|  mg_tcpip_call(ifp, MG_TCPIP_EV_STATE_CHANGE, &ifp->state);
 9342|    591|}
fuzz.c:_ZL10mg_ip_linkP11mg_tcpip_ifbb:
10970|  5.56k|static void mg_ip_link(struct mg_tcpip_if *ifp, bool drv_up, bool l2_up) {
10971|  5.56k|  bool cur_drv = (ifp->state != MG_TCPIP_STATE_DOWN);
  ------------------
  |  | 4758|  5.56k|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
10972|  5.56k|  bool cur_l2 = (ifp->state >= MG_TCPIP_STATE_UP);
  ------------------
  |  | 4760|  5.56k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
10973|  5.56k|  if (!l2_up && ifp->enable_dhcp_client) ifp->ip = 0;
  ------------------
  |  Branch (10973:7): [True: 591, False: 4.96k]
  |  Branch (10973:17): [True: 0, False: 591]
  ------------------
10974|  5.56k|  if (drv_up != cur_drv || l2_up != cur_l2) {  // link/L2 state has changed
  ------------------
  |  Branch (10974:7): [True: 0, False: 5.56k]
  |  Branch (10974:28): [True: 591, False: 4.96k]
  ------------------
10975|    591|    ifp->state = !drv_up  ? MG_TCPIP_STATE_DOWN
  ------------------
  |  | 4758|      0|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (10975:18): [True: 0, False: 591]
  ------------------
10976|    591|                 : !l2_up ? MG_TCPIP_STATE_LINK_UP
  ------------------
  |  | 4759|    591|#define MG_TCPIP_STATE_LINK_UP 1    // Driver reports physical link is up
  ------------------
  |  Branch (10976:20): [True: 591, False: 0]
  ------------------
10977|    591|                 : ifp->enable_dhcp_client || ifp->ip == 0 ? MG_TCPIP_STATE_UP
  ------------------
  |  | 4760|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10977:20): [True: 0, False: 0]
  |  Branch (10977:47): [True: 0, False: 0]
  ------------------
10978|      0|                                                           : MG_TCPIP_STATE_IP;
  ------------------
  |  | 4762|    591|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
10979|    591|    onstatechange(ifp);
10980|  4.96k|  } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
  ------------------
  |  | 4760|  9.93k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10980:14): [True: 4.96k, False: 0]
  |  Branch (10980:42): [True: 0, False: 4.96k]
  ------------------
10981|      0|             ifp->ip) {
  ------------------
  |  Branch (10981:14): [True: 0, False: 0]
  ------------------
10982|      0|    ifp->state = MG_TCPIP_STATE_IP;  // ifp->fn has set an IP
  ------------------
  |  | 4762|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
10983|      0|    onstatechange(ifp);
10984|      0|  }
10985|  5.56k|}
fuzz.c:_ZL13mg_tcpip_callP11mg_tcpip_ifiPv:
 9142|  6.17k|static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
 9143|       |#if 0 && MG_ENABLE_PROFILE
 9144|       |  const char *names[] = {"TCPIP_EV_STATE_CHANGE",  "TCPIP_EV_DHCP_DNS",
 9145|       |                         "TCPIP_EV_DHCP_SNTP",     "TCPIP_EV_ARP",
 9146|       |                         "TCPIP_EV_TIMER_1S",      "TCPIP_EV_WIFI_SCAN_RESULT",
 9147|       |                         "TCPIP_EV_WIFI_SCAN_END", "TCPIP_EV_WIFI_CONNECT_ERR",
 9148|       |                         "TCPIP_EV_DRIVER",        "TCPIP_EV_STATE6_CHANGE",
 9149|       |                         "TCPIP_EV_USER"};
 9150|       |  if (ev != MG_TCPIP_EV_TIMER_1S && ev < (int) (sizeof(names) / sizeof(names[0]))) {
 9151|       |    MG_PROF_ADD(ifp, names[ev]); // TODO(): call MG_PROF_DUMP() MG_PROF_FREE()
 9152|       |  }
 9153|       |#endif
 9154|       |  // Fire protocol handler first, user handler second. See #2559
 9155|  6.17k|  if (ifp->pfn != NULL) ifp->pfn(ifp, ev, ev_data);
  ------------------
  |  Branch (9155:7): [True: 0, False: 6.17k]
  ------------------
 9156|  6.17k|  if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
  ------------------
  |  Branch (9156:7): [True: 0, False: 6.17k]
  ------------------
 9157|  6.17k|}
fuzz.c:_ZL10mg_ip_pollP11mg_tcpip_ifb:
10946|  5.56k|static void mg_ip_poll(struct mg_tcpip_if *ifp, bool s1) {
10947|  5.56k|  if (ifp->state < MG_TCPIP_STATE_UP) return;
  ------------------
  |  | 4760|  5.56k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10947:7): [True: 591, False: 4.96k]
  ------------------
10948|       |  // DHCP RFC-2131 (4.4)
10949|  4.96k|  if (ifp->enable_dhcp_client && s1) {
  ------------------
  |  Branch (10949:7): [True: 0, False: 4.96k]
  |  Branch (10949:34): [True: 0, False: 0]
  ------------------
10950|      0|    if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 4760|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10950:9): [True: 0, False: 0]
  ------------------
10951|      0|      tx_dhcp_discover(ifp);  // INIT (4.4.1)
10952|      0|    } else if (ifp->state == MG_TCPIP_STATE_REQ &&
  ------------------
  |  | 4761|      0|#define MG_TCPIP_STATE_REQ 3        // DHCP REQUESTING: waiting for DHCP offer
  ------------------
  |  Branch (10952:16): [True: 0, False: 0]
  ------------------
10953|      0|               ifp->now >= ifp->lease_expire) {
  ------------------
  |  Branch (10953:16): [True: 0, False: 0]
  ------------------
10954|      0|      ifp->state = MG_TCPIP_STATE_UP;  // REQUEST or ACK lost: DISCOVER again
  ------------------
  |  | 4760|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
10955|      0|    } else if (ifp->state == MG_TCPIP_STATE_READY &&
  ------------------
  |  | 4763|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (10955:16): [True: 0, False: 0]
  ------------------
10956|      0|               ifp->lease_expire > 0) {  // BOUND / RENEWING / REBINDING
  ------------------
  |  Branch (10956:16): [True: 0, False: 0]
  ------------------
10957|      0|      if (ifp->now >= ifp->lease_expire) {
  ------------------
  |  Branch (10957:11): [True: 0, False: 0]
  ------------------
10958|      0|        ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0;  // expired, release IP
  ------------------
  |  | 4760|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
10959|      0|        onstatechange(ifp);
10960|      0|      } else if (ifp->now + 30UL * 60UL * 1000UL > ifp->lease_expire &&
  ------------------
  |  Branch (10960:18): [True: 0, False: 0]
  ------------------
10961|      0|                 ((ifp->now / 1000) % 60) == 0) {
  ------------------
  |  Branch (10961:18): [True: 0, False: 0]
  ------------------
10962|       |        // hack: 30 min before deadline, try to rebind (4.3.6) every min
10963|      0|        tx_dhcp_request_re(
10964|       |            ifp, mg_l2_mapip(ifp->l2type, MG_TCPIP_L2ADDR_BCAST, NULL), ifp->ip,
10965|      0|            0xffffffff);
10966|      0|      }  // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5)
10967|      0|    }
10968|      0|  }
10969|  4.96k|}
fuzz.c:_ZL11proto_errorP13mg_connectionbPKcz:
10108|  4.96k|static void proto_error(struct mg_connection *c, bool r, const char *f, ...) {
10109|  4.96k|  char buf[64];
10110|  4.96k|  va_list ap;
10111|  4.96k|  struct connstate *s = (struct connstate *) (c + 1);
10112|  4.96k|  va_start(ap, f);
10113|  4.96k|  mg_vsnprintf(buf, sizeof(buf), f, &ap);
10114|  4.96k|  va_end(ap);
10115|  4.96k|  MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
  ------------------
  |  | 1766|  4.96k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1756|  4.96k|  do {                      \
  |  |  |  | 1757|  4.96k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 4.96k]
  |  |  |  |  ------------------
  |  |  |  | 1758|  4.96k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 4.96k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10116|  4.96k|  c->is_closing = 1;  // Stop Mongoose I/O
10117|  4.96k|  s->is_closing = 1;  // Transport-terminal; do not send FIN
10118|  4.96k|  if (r && !c->is_udp) s->send_rst = true;  // honot TCP RST request
  ------------------
  |  Branch (10118:7): [True: 0, False: 4.96k]
  |  Branch (10118:12): [True: 0, False: 0]
  ------------------
10119|  4.96k|  mg_call(c, MG_EV_ERROR, buf);
10120|  4.96k|}
fuzz.c:_ZL20mg_pfn_iobuf_privatecPvb:
14215|  43.5M|static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
14216|  43.5M|  struct mg_iobuf *io = (struct mg_iobuf *) param;
14217|  43.5M|  if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
  ------------------
  |  Branch (14217:7): [True: 25.9M, False: 17.5M]
  |  Branch (14217:17): [True: 1.71k, False: 25.9M]
  ------------------
14218|  43.5M|  if (io->len + 2 <= io->size) {
  ------------------
  |  Branch (14218:7): [True: 43.5M, False: 2.85k]
  ------------------
14219|  43.5M|    io->buf[io->len++] = (uint8_t) ch;
14220|  43.5M|    io->buf[io->len] = 0;
14221|  43.5M|  } else if (io->len < io->size) {
  ------------------
  |  Branch (14221:14): [True: 1.21k, False: 1.63k]
  ------------------
14222|  1.21k|    io->buf[io->len++] = 0;  // Guarantee to 0-terminate
14223|  1.21k|  }
14224|  43.5M|}
fuzz.c:_ZL12gettimestampPKj:
15243|    705|static int64_t gettimestamp(const uint32_t *data) {
15244|    705|  uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]);
15245|    705|  if (sec) sec -= SNTP_TIME_OFFSET;
  ------------------
  |  |15234|    678|#define SNTP_TIME_OFFSET 2208988800U  // (1970 - 1900) in seconds
  ------------------
  |  Branch (15245:7): [True: 678, False: 27]
  ------------------
15246|    705|  return ((int64_t) sec) * 1000 + (int64_t) (frac / SNTP_MAX_FRAC * 1000.0);
  ------------------
  |  |15235|    705|#define SNTP_MAX_FRAC 4294967295.0    // 2 ** 32 - 1
  ------------------
15247|    705|}
fuzz.c:_ZL7mg_tolcc:
16261|  3.51M|static int mg_tolc(char c) {
16262|  3.51M|  return (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  ------------------
  |  Branch (16262:11): [True: 3.33M, False: 181k]
  |  Branch (16262:23): [True: 2.16M, False: 1.17M]
  ------------------
16263|  3.51M|}
fuzz.c:_ZL8urlparsePKc:
29308|  11.1k|static struct url urlparse(const char *url) {
29309|  11.1k|  size_t i;
29310|  11.1k|  struct url u;
29311|  11.1k|  memset(&u, 0, sizeof(u));
29312|   255k|  for (i = 0; url[i] != '\0'; i++) {
  ------------------
  |  Branch (29312:15): [True: 244k, False: 11.1k]
  ------------------
29313|   244k|    if (url[i] == '/' && i > 0 && u.host == 0 && url[i - 1] == '/') {
  ------------------
  |  Branch (29313:9): [True: 22.2k, False: 222k]
  |  Branch (29313:26): [True: 22.2k, False: 0]
  |  Branch (29313:35): [True: 22.2k, False: 0]
  |  Branch (29313:50): [True: 11.1k, False: 11.1k]
  ------------------
29314|  11.1k|      u.host = i + 1;
29315|  11.1k|      u.port = 0;
29316|   233k|    } else if (url[i] == ']') {
  ------------------
  |  Branch (29316:16): [True: 0, False: 233k]
  ------------------
29317|      0|      u.port = 0;  // IPv6 URLs, like http://[::1]/bar
29318|   233k|    } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
  ------------------
  |  Branch (29318:16): [True: 22.2k, False: 211k]
  |  Branch (29318:33): [True: 22.2k, False: 0]
  |  Branch (29318:48): [True: 22.2k, False: 0]
  ------------------
29319|  22.2k|      u.port = i + 1;
29320|   211k|    } else if (url[i] == '@' && u.user == 0 && u.pass == 0 && u.uri == 0) {
  ------------------
  |  Branch (29320:16): [True: 0, False: 211k]
  |  Branch (29320:33): [True: 0, False: 0]
  |  Branch (29320:48): [True: 0, False: 0]
  |  Branch (29320:63): [True: 0, False: 0]
  ------------------
29321|      0|      u.user = u.host;
29322|      0|      u.pass = u.port;
29323|      0|      u.host = i + 1;
29324|      0|      u.port = 0;
29325|   211k|    } else if (url[i] == '/' && u.host && u.uri == 0) {
  ------------------
  |  Branch (29325:16): [True: 11.1k, False: 200k]
  |  Branch (29325:33): [True: 0, False: 11.1k]
  |  Branch (29325:43): [True: 0, False: 0]
  ------------------
29326|      0|      u.uri = i;
29327|      0|    }
29328|   244k|  }
29329|  11.1k|  u.end = i;
29330|       |#if 0
29331|       |  printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
29332|       |#endif
29333|  11.1k|  return u;
29334|  11.1k|}
fuzz.c:_ZL11mg_tcpip_rxP11mg_tcpip_ifPvm:
10923|  5.56k|static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
10924|  5.56k|  struct pkt pkt;
10925|  5.56k|  enum mg_l2proto proto;
10926|  5.56k|  memset(&pkt, 0, sizeof(pkt));
10927|  5.56k|  pkt.raw.buf = (char *) buf;
10928|  5.56k|  pkt.raw.len = len;
10929|  5.56k|  pkt.l2 = (uint8_t *) pkt.raw.buf;
10930|  5.56k|  if (!mg_l2_rx(ifp, &proto, &pkt.pay, &pkt.raw)) return;
  ------------------
  |  Branch (10930:7): [True: 5.40k, False: 159]
  ------------------
10931|    159|  if (ifp->state < MG_TCPIP_STATE_UP) return;  // discard while L2 is not up
  ------------------
  |  | 4760|    159|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10931:7): [True: 0, False: 159]
  ------------------
10932|    159|  if (proto == MG_TCPIP_L2PROTO_ARP) {
  ------------------
  |  Branch (10932:7): [True: 28, False: 131]
  ------------------
10933|     28|    pkt.arp = (struct arp *) (pkt.pay.buf);
10934|     28|    if (pkt.pay.len < sizeof(*pkt.arp)) return;  // Truncated
  ------------------
  |  Branch (10934:9): [True: 0, False: 28]
  ------------------
10935|     28|    mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
10936|     28|    rx_arp(ifp, &pkt);
10937|    131|  } else if (proto == MG_TCPIP_L2PROTO_IPV6) {
  ------------------
  |  Branch (10937:14): [True: 5, False: 126]
  ------------------
10938|      5|    pkt.ip6 = (struct ip6 *) (pkt.pay.buf);
10939|      5|    rx_ip6(ifp, &pkt);
10940|    126|  } else if (proto == MG_TCPIP_L2PROTO_IPV4) {
  ------------------
  |  Branch (10940:14): [True: 89, False: 37]
  ------------------
10941|     89|    pkt.ip = (struct ip *) (pkt.pay.buf);
10942|     89|    rx_ip(ifp, &pkt);
10943|     89|  }
10944|    159|}
fuzz.c:_ZL6rx_arpP11mg_tcpip_ifP3pkt:
 9520|     28|static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 9521|     28|  if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) {
  ------------------
  |  | 2037|     56|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (9521:7): [True: 12, False: 16]
  |  Branch (9521:38): [True: 1, False: 11]
  ------------------
 9522|       |    // ARP request. Make a response, then send
 9523|       |    // MG_VERBOSE(("ARP req from %M", mg_print_ip4, &pkt->arp->spa));
 9524|      1|    uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 9525|      1|    struct arp *arp = (struct arp *) mg_l2_header(
 9526|      1|        ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_getaddr(ifp, pkt->l2), l2p);
 9527|      1|    *arp = *pkt->arp;
 9528|      1|    arp->op = mg_htons(2);
  ------------------
  |  | 2037|      1|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9529|      1|    memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha));
 9530|      1|    memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha));
 9531|      1|    arp->tpa = pkt->arp->spa;
 9532|      1|    arp->spa = ifp->ip;
 9533|      1|    MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac,
  ------------------
  |  | 1768|      1|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      1|  do {                      \
  |  |  |  | 1757|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1758|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9534|      1|              ifp->mac));
 9535|      1|    driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1)));
 9536|     27|  } else if (pkt->arp->op == mg_htons(2)) {
  ------------------
  |  | 2037|     27|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (9536:14): [True: 0, False: 27]
  ------------------
 9537|      0|    if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
  ------------------
  |  Branch (9537:9): [True: 0, False: 0]
  ------------------
 9538|       |    // MG_VERBOSE(("ARP resp from %M", mg_print_ip4, &pkt->arp->spa));
 9539|      0|    if (pkt->arp->spa == ifp->gw) {
  ------------------
  |  Branch (9539:9): [True: 0, False: 0]
  ------------------
 9540|       |      // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
 9541|      0|      memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
 9542|      0|      ifp->gw_ready = true;
 9543|      0|      if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4762|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9543:11): [True: 0, False: 0]
  ------------------
 9544|      0|        ifp->state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4763|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
 9545|      0|        onstatechange(ifp);
 9546|      0|      }
 9547|      0|    } else {
 9548|      0|      struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
 9549|      0|      if (c != NULL && c->is_arplooking) {
  ------------------
  |  Branch (9549:11): [True: 0, False: 0]
  |  Branch (9549:24): [True: 0, False: 0]
  ------------------
 9550|      0|        struct connstate *s = (struct connstate *) (c + 1);
 9551|      0|        memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
 9552|      0|        MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4,
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9553|      0|                  &c->rem.addr.ip4, mg_print_mac, s->mac));
 9554|      0|        c->is_arplooking = 0;
 9555|      0|        l2addr_resolved(c);
 9556|      0|      }
 9557|      0|    }
 9558|      0|  }
 9559|     28|}
fuzz.c:_ZL5rx_ipP11mg_tcpip_ifP3pkt:
10753|     89|static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
10754|     89|  uint8_t ihl;
10755|     89|  uint16_t frag, len;
10756|     89|  if (pkt->pay.len < sizeof(*pkt->ip)) return;  // Truncated
  ------------------
  |  Branch (10756:7): [True: 11, False: 78]
  ------------------
10757|     78|  if ((pkt->ip->ver >> 4) != 4) return;         // Not IP
  ------------------
  |  Branch (10757:7): [True: 1, False: 77]
  ------------------
10758|     77|  ihl = pkt->ip->ver & 0x0F;
10759|     77|  if (ihl < 5) return;                              // bad IHL
  ------------------
  |  Branch (10759:7): [True: 6, False: 71]
  ------------------
10760|     71|  if (pkt->pay.len < (uint16_t) (ihl * 4)) return;  // Truncated / malformed
  ------------------
  |  Branch (10760:7): [True: 11, False: 60]
  ------------------
10761|       |  // There can be link padding, take length from IP header
10762|     60|  len = mg_ntohs(pkt->ip->len);  // IP datagram length
10763|     60|  if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return;  // malformed
  ------------------
  |  Branch (10763:7): [True: 1, False: 59]
  |  Branch (10763:37): [True: 30, False: 29]
  ------------------
10764|     29|  pkt->pay.len = len;                      // strip padding
10765|     29|  mkpay(pkt, (uint32_t *) pkt->ip + ihl);  // account for opts
10766|     29|  if (!ipcsum_ok(pkt->ip)) return;
  ------------------
  |  Branch (10766:7): [True: 24, False: 5]
  ------------------
10767|      5|  frag = mg_ntohs(pkt->ip->frag);
10768|      5|  if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 8983|     10|#define IP_MORE_FRAGS_MSK 0x2000
  ------------------
                if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 8982|      5|#define IP_FRAG_OFFSET_MSK 0x1fff
  ------------------
  |  Branch (10768:7): [True: 0, False: 5]
  |  Branch (10768:35): [True: 0, False: 5]
  ------------------
10769|      0|    struct mg_connection *c;
10770|      0|    if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->pay.buf);
  ------------------
  |  Branch (10770:9): [True: 0, False: 0]
  ------------------
10771|      0|    if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->pay.buf);
  ------------------
  |  Branch (10771:9): [True: 0, False: 0]
  ------------------
10772|      0|    c = getpeer(ifp->mgr, pkt, false);
10773|      0|    if (c) proto_error(c, false, "Received fragmented packet");
  ------------------
  |  Branch (10773:9): [True: 0, False: 0]
  ------------------
10774|      5|  } else if (pkt->ip->proto == 1) {
  ------------------
  |  Branch (10774:14): [True: 5, False: 0]
  ------------------
10775|      5|    pkt->icmp = (struct icmp *) (pkt->pay.buf);
10776|      5|    if (pkt->pay.len < sizeof(*pkt->icmp)) return;
  ------------------
  |  Branch (10776:9): [True: 0, False: 5]
  ------------------
10777|      5|    mkpay(pkt, pkt->icmp + 1);
10778|      5|    rx_icmp(ifp, pkt);
10779|      5|  } else if (pkt->ip->proto == 17) {
  ------------------
  |  Branch (10779:14): [True: 0, False: 0]
  ------------------
10780|      0|    pkt->udp = (struct udp *) (pkt->pay.buf);
10781|      0|    if (pkt->pay.len < sizeof(*pkt->udp)) return;  // truncated
  ------------------
  |  Branch (10781:9): [True: 0, False: 0]
  ------------------
10782|       |    // Take length from UDP header
10783|      0|    len = mg_ntohs(pkt->udp->len);  // UDP datagram length
10784|      0|    if (len < sizeof(*pkt->udp) || len > pkt->pay.len) return;  // malformed
  ------------------
  |  Branch (10784:9): [True: 0, False: 0]
  |  Branch (10784:36): [True: 0, False: 0]
  ------------------
10785|      0|    pkt->pay.len = len;  // strip excess data
10786|      0|    mkpay(pkt, pkt->udp + 1);
10787|      0|    MG_VERBOSE(("UDP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1769|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10788|      0|                mg_ntohs(pkt->udp->sport), mg_print_ip4, &pkt->ip->dst,
10789|      0|                mg_ntohs(pkt->udp->dport), (int) pkt->pay.len));
10790|      0|    if (ifp->enable_dhcp_client && pkt->udp->dport == mg_htons(68) &&
  ------------------
  |  | 2037|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (10790:9): [True: 0, False: 0]
  |  Branch (10790:36): [True: 0, False: 0]
  ------------------
10791|      0|        len >= offsetof(struct dhcp, options)) {
  ------------------
  |  Branch (10791:9): [True: 0, False: 0]
  ------------------
10792|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
10793|      0|      mkpay(pkt, &pkt->dhcp->options);
10794|      0|      rx_dhcp_client(ifp, pkt);
10795|      0|    } else if (ifp->enable_dhcp_server && pkt->udp->dport == mg_htons(67) &&
  ------------------
  |  | 2037|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (10795:16): [True: 0, False: 0]
  |  Branch (10795:43): [True: 0, False: 0]
  ------------------
10796|      0|               len >= offsetof(struct dhcp, options)) {
  ------------------
  |  Branch (10796:16): [True: 0, False: 0]
  ------------------
10797|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
10798|      0|      mkpay(pkt, &pkt->dhcp->options);
10799|      0|      rx_dhcp_server(ifp, pkt);
10800|      0|    } else if (!rx_udp(ifp, pkt)) {
  ------------------
  |  Branch (10800:16): [True: 0, False: 0]
  ------------------
10801|       |      // Should send ICMP Destination Unreachable for unicasts, but keep
10802|       |      // silent
10803|      0|    }
10804|      0|  } else if (pkt->ip->proto == 6) {
  ------------------
  |  Branch (10804:14): [True: 0, False: 0]
  ------------------
10805|      0|    uint8_t off;
10806|      0|    pkt->tcp = (struct tcp *) (pkt->pay.buf);
10807|      0|    if (pkt->pay.len < sizeof(*pkt->tcp)) return;
  ------------------
  |  Branch (10807:9): [True: 0, False: 0]
  ------------------
10808|      0|    off = pkt->tcp->off >> 4;  // account for opts
10809|      0|    if (off < sizeof(*pkt->tcp) / 4 || pkt->pay.len < (uint16_t) (4 * off))
  ------------------
  |  Branch (10809:9): [True: 0, False: 0]
  |  Branch (10809:40): [True: 0, False: 0]
  ------------------
10810|      0|      return;
10811|      0|    mkpay(pkt, (uint32_t *) pkt->tcp + off);
10812|      0|    MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1769|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10813|      0|                mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
10814|      0|                mg_ntohs(pkt->tcp->dport), (int) pkt->pay.len));
10815|      0|    rx_tcp(ifp, pkt);
10816|      0|  } else {
10817|      0|    MG_DEBUG(("Unknown IP proto %x", (int) pkt->ip->proto));
  ------------------
  |  | 1768|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1756|      0|  do {                      \
  |  |  |  | 1757|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1757:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1758|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1758:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10818|      0|    if (mg_log_level >= MG_LL_VERBOSE)
  ------------------
  |  Branch (10818:9): [True: 0, False: 0]
  ------------------
10819|      0|      mg_hexdump(pkt->ip, pkt->pay.len >= 32 ? 32 : pkt->pay.len);
  ------------------
  |  Branch (10819:27): [True: 0, False: 0]
  ------------------
10820|      0|  }
10821|      5|}
fuzz.c:_ZL5mkpayP3pktPv:
 9161|     34|static void mkpay(struct pkt *pkt, void *p) {
 9162|     34|  pkt->pay =
 9163|     34|      mg_str_n((char *) p, (size_t) (&pkt->pay.buf[pkt->pay.len] - (char *) p));
 9164|     34|}
fuzz.c:_ZL9ipcsum_okPKv:
 9184|     29|static bool ipcsum_ok(const void *d) {
 9185|     29|  struct ip *ip = (struct ip *) d;
 9186|     29|  return (ipcsum(d, (ip->ver & 0x0F) * 4) == 0);
 9187|     29|}
fuzz.c:_ZL7rx_icmpP11mg_tcpip_ifP3pkt:
 9561|      5|static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 9562|      5|  size_t plen = pkt->pay.len;
 9563|      5|  if (!icmpcsum_ok(pkt->icmp, sizeof(struct icmp) + plen)) return;
  ------------------
  |  Branch (9563:7): [True: 5, False: 0]
  ------------------
 9564|      0|  if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
  ------------------
  |  Branch (9564:7): [True: 0, False: 0]
  |  Branch (9564:31): [True: 0, False: 0]
  |  Branch (9564:50): [True: 0, False: 0]
  ------------------
 9565|      0|    size_t l2_max_overhead = ifp->framesize - ifp->l2mtu;
 9566|      0|    size_t hlen = sizeof(struct ip) + sizeof(struct icmp);
 9567|      0|    size_t room = ifp->tx.len - hlen - l2_max_overhead;
 9568|      0|    uint8_t *l2addr;
 9569|      0|    struct ip *ip;
 9570|      0|    struct icmp *icmp;
 9571|      0|    struct mg_addr ips;
 9572|      0|    ips.addr.ip4 = pkt->ip->src;
 9573|      0|    ips.is_ip6 = false;
 9574|      0|    if ((l2addr = get_return_l2addr(ifp, &ips, false, pkt)) == NULL)
  ------------------
  |  Branch (9574:9): [True: 0, False: 0]
  ------------------
 9575|      0|      return;  // safety net for lousy networks
 9576|      0|    if (plen > room) plen = room;
  ------------------
  |  Branch (9576:9): [True: 0, False: 0]
  ------------------
 9577|      0|    ip = tx_ip(ifp, l2addr, 1, 0, ifp->ip, pkt->ip->src, sizeof(*icmp) + plen);
 9578|      0|    icmp = (struct icmp *) (ip + 1);
 9579|      0|    memset(icmp, 0, sizeof(*icmp));        // Set csum, type, code to 0
 9580|      0|    memcpy(icmp + 1, pkt->pay.buf, plen);  // Copy RX payload to TX
 9581|      0|    icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
 9582|      0|    driver_output(
 9583|      0|        ifp, mg_l2_trailer(ifp, hlen + plen, (uint8_t *) ip + hlen + plen));
 9584|      0|  }
 9585|      0|}
fuzz.c:_ZL11icmpcsum_okPKvm:
 9189|      5|static bool icmpcsum_ok(const void *d, size_t len) {
 9190|      5|  return (ipcsum(d, len) == 0);
 9191|      5|}

