Merge "Prevent OOB read in nfa_dm_handle_message" into qt-qpr1-dev
diff --git a/src/nfa/hci/nfa_hci_main.cc b/src/nfa/hci/nfa_hci_main.cc
index d6667e1..b4c43be 100644
--- a/src/nfa/hci/nfa_hci_main.cc
+++ b/src/nfa/hci/nfa_hci_main.cc
@@ -741,11 +741,26 @@
   p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
   pkt_len = p_pkt->len;
 
+  if (pkt_len < 1) {
+    LOG(ERROR) << StringPrintf("Insufficient packet length! Dropping :%u bytes",
+                               pkt_len);
+    /* release GKI buffer */
+    GKI_freebuf(p_pkt);
+    return;
+  }
+
   chaining_bit = ((*p) >> 0x07) & 0x01;
   pipe = (*p++) & 0x7F;
   if (pkt_len != 0) pkt_len--;
 
   if (nfa_hci_cb.assembling == false) {
+    if (pkt_len < 1) {
+      LOG(ERROR) << StringPrintf(
+          "Insufficient packet length! Dropping :%u bytes", pkt_len);
+      /* release GKI buffer */
+      GKI_freebuf(p_pkt);
+      return;
+    }
     /* First Segment of a packet */
     nfa_hci_cb.type = ((*p) >> 0x06) & 0x03;
     nfa_hci_cb.inst = (*p++ & 0x3F);
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 0322a97..f14e6f2 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -370,16 +370,34 @@
 **
 *******************************************************************************/
 bool nfc_ncif_process_event(NFC_HDR* p_msg) {
-  uint8_t mt, pbf, gid, *p, *pp;
+  uint8_t mt, pbf, gid, *p;
   bool free = true;
   uint8_t oid;
+  uint16_t len;
   uint8_t *p_old, old_gid, old_oid, old_mt;
 
   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
 
-  pp = p;
-  NCI_MSG_PRS_HDR0(pp, mt, pbf, gid);
-  oid = ((*pp) & NCI_OID_MASK);
+  if (p_msg->len < 3) {
+    // Per NCI spec, every packets should have at least 3 bytes: HDR0, HDR1, and
+    // LEN field.
+    LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len: %d",
+                               p_msg->len);
+    return free;
+  }
+
+  // LEN field contains the size of the payload, not including the 3-byte packet
+  // header.
+  len = p[2] + 3;
+  if (p_msg->len < len) {
+    // Making sure the packet holds enough data than it claims.
+    LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len (%d) < len (%d)",
+                               p_msg->len, len);
+    return free;
+  }
+
+  NCI_MSG_PRS_HDR0(p, mt, pbf, gid);
+  oid = ((*p) & NCI_OID_MASK);
   if (nfc_cb.rawVsCbflag == true &&
       nfc_ncif_proc_proprietary_rsp(mt, gid, oid) == true) {
     nci_proc_prop_raw_vs_rsp(p_msg);
@@ -398,7 +416,7 @@
     case NCI_MT_RSP:
       DLOG_IF(INFO, nfc_debug_enabled)
           << StringPrintf("NFC received rsp gid:%d", gid);
-      oid = ((*pp) & NCI_OID_MASK);
+      oid = ((*p) & NCI_OID_MASK);
       p_old = nfc_cb.last_hdr;
       NCI_MSG_PRS_HDR0(p_old, old_mt, pbf, old_gid);
       old_oid = ((*p_old) & NCI_OID_MASK);
@@ -1541,6 +1559,10 @@
   uint8_t status;
   uint8_t num_responses;
 
+  if (plen < NFC_TL_SIZE) {
+    return;
+  }
+
   /* Pass result to RW_T3T for processing */
   STREAM_TO_UINT8(status, p);
   STREAM_TO_UINT8(num_responses, p);
diff --git a/src/nfc/tags/rw_mfc.cc b/src/nfc/tags/rw_mfc.cc
index 22cfc35..7fff8c8 100644
--- a/src/nfc/tags/rw_mfc.cc
+++ b/src/nfc/tags/rw_mfc.cc
@@ -404,10 +404,7 @@
 
     if (p_mfc->work_offset == p_mfc->ndef_length) {
       UINT8_TO_BE_STREAM(p, 0xFE);
-      index = index + 1;
-    }
-
-    if (p_mfc->work_offset > p_mfc->ndef_length) {
+    } else if (p_mfc->work_offset > p_mfc->ndef_length) {
       UINT8_TO_BE_STREAM(p, 0x00);
     } else {
       UINT8_TO_BE_STREAM(p, p_mfc->p_ndef_buffer[p_mfc->work_offset]);
diff --git a/src/nfc/tags/rw_t3t.cc b/src/nfc/tags/rw_t3t.cc
index 6ac933d..dce6ba8 100644
--- a/src/nfc/tags/rw_t3t.cc
+++ b/src/nfc/tags/rw_t3t.cc
@@ -1018,6 +1018,14 @@
 
       /* Add service code to T3T message */
       UINT16_TO_STREAM((*p), cur_service_code);
+
+      /* Validate num_services */
+      if (num_services >= T3T_MSG_SERVICE_LIST_MAX) {
+        LOG(ERROR) << StringPrintf(
+            "RW T3T: num_services (%i) reaches maximum (%i)", num_services,
+            T3T_MSG_SERVICE_LIST_MAX);
+        break;
+      }
     }
   }