fuzz.c:recv_validate_datagram:
  586|    375|static bool recv_validate_datagram(const recv_ntb_t *ntb, uint32_t len) {
  587|    375|  const nth16_t *nth16 = &(ntb->nth);
  588|       |
  589|    375|  TU_LOG_DRV("recv_validate_datagram(%p, %d)\n", ntb, (int) len);
  590|       |
  591|       |  // check header
  592|    375|  if (nth16->wHeaderLength != sizeof(nth16_t)) {
  ------------------
  |  Branch (592:7): [True: 25, False: 350]
  ------------------
  593|     25|    TU_LOG_DRV("(EE) ill nth16 length: %d\n", nth16->wHeaderLength);
  594|     25|    return false;
  595|     25|  }
  596|    350|  if (nth16->dwSignature != NTH16_SIGNATURE) {
  ------------------
  |  |   83|    350|#define NTH16_SIGNATURE 0x484D434E
  ------------------
  |  Branch (596:7): [True: 53, False: 297]
  ------------------
  597|     53|    TU_LOG_DRV("(EE) ill signature: 0x%08x\n", (unsigned) nth16->dwSignature);
  598|     53|    return false;
  599|     53|  }
  600|    297|  if (len < sizeof(nth16_t) + sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)) {
  ------------------
  |  Branch (600:7): [True: 8, False: 289]
  ------------------
  601|      8|    TU_LOG_DRV("(EE) ill min len: %lu\n", len);
  602|      8|    return false;
  603|      8|  }
  604|    289|  if (nth16->wBlockLength > len) {
  ------------------
  |  Branch (604:7): [True: 13, False: 276]
  ------------------
  605|     13|    TU_LOG_DRV("(EE) ill block length: %d > %lu\n", nth16->wBlockLength, len);
  606|     13|    return false;
  607|     13|  }
  608|    276|  if (nth16->wBlockLength > CFG_TUD_NCM_OUT_NTB_MAX_SIZE) {
  ------------------
  |  |   17|    276|  #define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200
  ------------------
  |  Branch (608:7): [True: 0, False: 276]
  ------------------
  609|      0|    TU_LOG_DRV("(EE) ill block length2: %d > %d\n", nth16->wBlockLength, CFG_TUD_NCM_OUT_NTB_MAX_SIZE);
  610|      0|    return false;
  611|      0|  }
  612|    276|  if (nth16->wNdpIndex < sizeof(nth16_t) || nth16->wNdpIndex > len - (sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t))) {
  ------------------
  |  Branch (612:7): [True: 10, False: 266]
  |  Branch (612:45): [True: 23, False: 243]
  ------------------
  613|     33|    TU_LOG_DRV("(EE) ill position of first ndp: %d (%lu)\n", nth16->wNdpIndex, len);
  614|     33|    return false;
  615|     33|  }
  616|       |
  617|       |  // check (first) NDP(16)
  618|    243|  const ndp16_t *ndp16 = (const ndp16_t *) (ntb->data + nth16->wNdpIndex);
  619|       |
  620|    243|  if (ndp16->wLength < sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)) {
  ------------------
  |  Branch (620:7): [True: 7, False: 236]
  ------------------
  621|      7|    TU_LOG_DRV("(EE) ill ndp16 length: %d\n", ndp16->wLength);
  622|      7|    return false;
  623|      7|  }
  624|       |  // the NDP block (wLength bytes from wNdpIndex) must fit within the received NTB, otherwise the
  625|       |  // datagram pointer array walked below (max_ndx is derived from wLength) runs past ntb->data
  626|    236|  if ((uint32_t) nth16->wNdpIndex + ndp16->wLength > len) {
  ------------------
  |  Branch (626:7): [True: 37, False: 199]
  ------------------
  627|     37|    TU_LOG_DRV("(EE) ill ndp16 length: %d (%lu)\n", ndp16->wLength, len);
  628|     37|    return false;
  629|     37|  }
  630|    199|  if (ndp16->dwSignature != NDP16_SIGNATURE_NCM0 && ndp16->dwSignature != NDP16_SIGNATURE_NCM1) {
  ------------------
  |  |   84|    398|#define NDP16_SIGNATURE_NCM0 0x304D434E
  ------------------
                if (ndp16->dwSignature != NDP16_SIGNATURE_NCM0 && ndp16->dwSignature != NDP16_SIGNATURE_NCM1) {
  ------------------
  |  |   85|    117|#define NDP16_SIGNATURE_NCM1 0x314D434E
  ------------------
  |  Branch (630:7): [True: 117, False: 82]
  |  Branch (630:53): [True: 82, False: 35]
  ------------------
  631|     82|    TU_LOG_DRV("(EE) ill signature: 0x%08x\n", (unsigned) ndp16->dwSignature);
  632|     82|    return false;
  633|     82|  }
  634|    117|  if (ndp16->wNextNdpIndex != 0) {
  ------------------
  |  Branch (634:7): [True: 16, False: 101]
  ------------------
  635|     16|    TU_LOG_DRV("(EE) cannot handle wNextNdpIndex!=0 (%d)\n", ndp16->wNextNdpIndex);
  636|     16|    return false;
  637|     16|  }
  638|       |
  639|    101|  const ndp16_datagram_t *ndp16_datagram = (const ndp16_datagram_t *) (ntb->data + nth16->wNdpIndex + sizeof(ndp16_t));
  640|    101|  int ndx = 0;
  641|    101|  uint16_t max_ndx = (uint16_t) ((ndp16->wLength - sizeof(ndp16_t)) / sizeof(ndp16_datagram_t));
  642|       |
  643|    101|  if (max_ndx > 2) { // number of datagrams in NTB > 1
  ------------------
  |  Branch (643:7): [True: 28, False: 73]
  ------------------
  644|     28|    TU_LOG_DRV("<< %d (%d)\n", max_ndx - 1, ntb->nth.wBlockLength);
  645|     28|  }
  646|    101|  if (ndp16_datagram[max_ndx - 1].wDatagramIndex != 0 || ndp16_datagram[max_ndx - 1].wDatagramLength != 0) {
  ------------------
  |  Branch (646:7): [True: 26, False: 75]
  |  Branch (646:58): [True: 18, False: 57]
  ------------------
  647|     44|    TU_LOG_DRV("  max_ndx != 0\n");
  648|     44|    return false;
  649|     44|  }
  650|    399|  while (ndp16_datagram[ndx].wDatagramIndex != 0 && ndp16_datagram[ndx].wDatagramLength != 0) {
  ------------------
  |  Branch (650:10): [True: 384, False: 15]
  |  Branch (650:53): [True: 378, False: 6]
  ------------------
  651|    378|    TU_LOG_DRV("  << %d %d\n", ndp16_datagram[ndx].wDatagramIndex, ndp16_datagram[ndx].wDatagramLength);
  652|    378|    if (ndp16_datagram[ndx].wDatagramIndex > len) {
  ------------------
  |  Branch (652:9): [True: 22, False: 356]
  ------------------
  653|     22|      TU_LOG_DRV("(EE) ill start of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex, len);
  654|     22|      return false;
  655|     22|    }
  656|    356|    if (ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength > len) {
  ------------------
  |  Branch (656:9): [True: 14, False: 342]
  ------------------
  657|     14|      TU_LOG_DRV("(EE) ill end of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength, len);
  658|     14|      return false;
  659|     14|    }
  660|    342|    ++ndx;
  661|    342|  }
  662|       |
  663|       |  #if CFG_TUD_NCM_LOG_LEVEL >= 3
  664|       |  TU_LOG_BUF(3, ntb->data[i], len);
  665|       |  #endif
  666|       |
  667|       |  // -> ntb contains a valid packet structure
  668|       |  //    ok... I did not check for garbage within the datagram indices...
  669|     21|  return true;
  670|     57|} // recv_validate_datagram

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

