fuzz.c:recv_validate_datagram:
  579|    386|static bool recv_validate_datagram(const recv_ntb_t *ntb, uint32_t len) {
  580|    386|  const nth16_t *nth16 = &(ntb->nth);
  581|       |
  582|    386|  TU_LOG_DRV("recv_validate_datagram(%p, %d)\n", ntb, (int) len);
  583|       |
  584|       |  // check header
  585|    386|  if (nth16->wHeaderLength != sizeof(nth16_t)) {
  ------------------
  |  Branch (585:7): [True: 22, False: 364]
  ------------------
  586|     22|    TU_LOG_DRV("(EE) ill nth16 length: %d\n", nth16->wHeaderLength);
  587|     22|    return false;
  588|     22|  }
  589|    364|  if (nth16->dwSignature != NTH16_SIGNATURE) {
  ------------------
  |  |   83|    364|#define NTH16_SIGNATURE 0x484D434E
  ------------------
  |  Branch (589:7): [True: 54, False: 310]
  ------------------
  590|     54|    TU_LOG_DRV("(EE) ill signature: 0x%08x\n", (unsigned) nth16->dwSignature);
  591|     54|    return false;
  592|     54|  }
  593|    310|  if (len < sizeof(nth16_t) + sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)) {
  ------------------
  |  Branch (593:7): [True: 8, False: 302]
  ------------------
  594|      8|    TU_LOG_DRV("(EE) ill min len: %lu\n", len);
  595|      8|    return false;
  596|      8|  }
  597|    302|  if (nth16->wBlockLength > len) {
  ------------------
  |  Branch (597:7): [True: 16, False: 286]
  ------------------
  598|     16|    TU_LOG_DRV("(EE) ill block length: %d > %lu\n", nth16->wBlockLength, len);
  599|     16|    return false;
  600|     16|  }
  601|    286|  if (nth16->wBlockLength > CFG_TUD_NCM_OUT_NTB_MAX_SIZE) {
  ------------------
  |  |   17|    286|  #define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200
  ------------------
  |  Branch (601:7): [True: 0, False: 286]
  ------------------
  602|      0|    TU_LOG_DRV("(EE) ill block length2: %d > %d\n", nth16->wBlockLength, CFG_TUD_NCM_OUT_NTB_MAX_SIZE);
  603|      0|    return false;
  604|      0|  }
  605|    286|  if (nth16->wNdpIndex < sizeof(nth16_t) || nth16->wNdpIndex > len - (sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t))) {
  ------------------
  |  Branch (605:7): [True: 11, False: 275]
  |  Branch (605:45): [True: 25, False: 250]
  ------------------
  606|     36|    TU_LOG_DRV("(EE) ill position of first ndp: %d (%lu)\n", nth16->wNdpIndex, len);
  607|     36|    return false;
  608|     36|  }
  609|       |
  610|       |  // check (first) NDP(16)
  611|    250|  const ndp16_t *ndp16 = (const ndp16_t *) (ntb->data + nth16->wNdpIndex);
  612|       |
  613|    250|  if (ndp16->wLength < sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)) {
  ------------------
  |  Branch (613:7): [True: 7, False: 243]
  ------------------
  614|      7|    TU_LOG_DRV("(EE) ill ndp16 length: %d\n", ndp16->wLength);
  615|      7|    return false;
  616|      7|  }
  617|       |  // the NDP block (wLength bytes from wNdpIndex) must fit within the received NTB, otherwise the
  618|       |  // datagram pointer array walked below (max_ndx is derived from wLength) runs past ntb->data
  619|    243|  if ((uint32_t) nth16->wNdpIndex + ndp16->wLength > len) {
  ------------------
  |  Branch (619:7): [True: 40, False: 203]
  ------------------
  620|     40|    TU_LOG_DRV("(EE) ill ndp16 length: %d (%lu)\n", ndp16->wLength, len);
  621|     40|    return false;
  622|     40|  }
  623|    203|  if (ndp16->dwSignature != NDP16_SIGNATURE_NCM0 && ndp16->dwSignature != NDP16_SIGNATURE_NCM1) {
  ------------------
  |  |   84|    406|#define NDP16_SIGNATURE_NCM0 0x304D434E
  ------------------
                if (ndp16->dwSignature != NDP16_SIGNATURE_NCM0 && ndp16->dwSignature != NDP16_SIGNATURE_NCM1) {
  ------------------
  |  |   85|    135|#define NDP16_SIGNATURE_NCM1 0x314D434E
  ------------------
  |  Branch (623:7): [True: 135, False: 68]
  |  Branch (623:53): [True: 86, False: 49]
  ------------------
  624|     86|    TU_LOG_DRV("(EE) ill signature: 0x%08x\n", (unsigned) ndp16->dwSignature);
  625|     86|    return false;
  626|     86|  }
  627|    117|  if (ndp16->wNextNdpIndex != 0) {
  ------------------
  |  Branch (627:7): [True: 18, False: 99]
  ------------------
  628|     18|    TU_LOG_DRV("(EE) cannot handle wNextNdpIndex!=0 (%d)\n", ndp16->wNextNdpIndex);
  629|     18|    return false;
  630|     18|  }
  631|       |
  632|     99|  const ndp16_datagram_t *ndp16_datagram = (const ndp16_datagram_t *) (ntb->data + nth16->wNdpIndex + sizeof(ndp16_t));
  633|     99|  int ndx = 0;
  634|     99|  uint16_t max_ndx = (uint16_t) ((ndp16->wLength - sizeof(ndp16_t)) / sizeof(ndp16_datagram_t));
  635|       |
  636|     99|  if (max_ndx > 2) { // number of datagrams in NTB > 1
  ------------------
  |  Branch (636:7): [True: 24, False: 75]
  ------------------
  637|     24|    TU_LOG_DRV("<< %d (%d)\n", max_ndx - 1, ntb->nth.wBlockLength);
  638|     24|  }
  639|     99|  if (ndp16_datagram[max_ndx - 1].wDatagramIndex != 0 || ndp16_datagram[max_ndx - 1].wDatagramLength != 0) {
  ------------------
  |  Branch (639:7): [True: 21, False: 78]
  |  Branch (639:58): [True: 19, False: 59]
  ------------------
  640|     40|    TU_LOG_DRV("  max_ndx != 0\n");
  641|     40|    return false;
  642|     40|  }
  643|    292|  while (ndp16_datagram[ndx].wDatagramIndex != 0 && ndp16_datagram[ndx].wDatagramLength != 0) {
  ------------------
  |  Branch (643:10): [True: 281, False: 11]
  |  Branch (643:53): [True: 278, False: 3]
  ------------------
  644|    278|    TU_LOG_DRV("  << %d %d\n", ndp16_datagram[ndx].wDatagramIndex, ndp16_datagram[ndx].wDatagramLength);
  645|    278|    if (ndp16_datagram[ndx].wDatagramIndex > len) {
  ------------------
  |  Branch (645:9): [True: 29, False: 249]
  ------------------
  646|     29|      TU_LOG_DRV("(EE) ill start of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex, len);
  647|     29|      return false;
  648|     29|    }
  649|    249|    if (ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength > len) {
  ------------------
  |  Branch (649:9): [True: 16, False: 233]
  ------------------
  650|     16|      TU_LOG_DRV("(EE) ill end of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength, len);
  651|     16|      return false;
  652|     16|    }
  653|    233|    ++ndx;
  654|    233|  }
  655|       |
  656|       |  #if CFG_TUD_NCM_LOG_LEVEL >= 3
  657|       |  TU_LOG_BUF(3, ntb->data[i], len);
  658|       |  #endif
  659|       |
  660|       |  // -> ntb contains a valid packet structure
  661|       |  //    ok... I did not check for garbage within the datagram indices...
  662|     14|  return true;
  663|     59|} // recv_validate_datagram

LLVMFuzzerTestOneInput:
   77|    386|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   78|       |  // Give the NTB a heap allocation of the exact receive-buffer size so any read
   79|       |  // past ntb->data is caught by AddressSanitizer.
   80|    386|  recv_ntb_t *ntb = (recv_ntb_t *) malloc(sizeof(recv_ntb_t));
   81|    386|  if (ntb == NULL) {
  ------------------
  |  Branch (81:7): [True: 0, False: 386]
  ------------------
   82|      0|    return 0;
   83|      0|  }
   84|    386|  size_t n = size < sizeof(ntb->data) ? size : sizeof(ntb->data);
  ------------------
  |  Branch (84:14): [True: 376, False: 10]
  ------------------
   85|    386|  memset(ntb->data, 0, sizeof(ntb->data));
   86|    386|  memcpy(ntb->data, data, n);
   87|    386|  recv_validate_datagram(ntb, (uint32_t) n);
   88|    386|  free(ntb);
   89|    386|  return 0;
   90|    386|}

