Tag-mismatch in nci_proc_ee_management_ntf

Bug: 136565424
Test: build ok
Change-Id: I30672c41bd2501b642983b5587694ec93818dc5f
Merged-In: I2dd8471a31b3996d4d3ce5b2532beb0b4d5cd544
diff --git a/src/nfc/nci/nci_hrcv.cc b/src/nfc/nci/nci_hrcv.cc
index 737bc9d..9329771 100644
--- a/src/nfc/nci/nci_hrcv.cc
+++ b/src/nfc/nci/nci_hrcv.cc
@@ -408,58 +408,93 @@
       << StringPrintf("nci_proc_ee_management_ntf opcode:0x%x", op_code);
   len = *pp++;
 
-  if (op_code == NCI_MSG_NFCEE_DISCOVER) {
-    nfc_response.nfcee_info.nfcee_id = *pp++;
+  switch (op_code) {
+    case NCI_MSG_NFCEE_DISCOVER:
+      if (len < 3) {
+        p_cback = nullptr;
+        break;
+      } else {
+        len -= 3;
+      }
+      nfc_response.nfcee_info.nfcee_id = *pp++;
 
-    nfc_response.nfcee_info.ee_status = *pp++;
-    yy = *pp;
-    nfc_response.nfcee_info.num_interface = *pp++;
-    p = pp;
-
-    if (nfc_response.nfcee_info.num_interface > NFC_MAX_EE_INTERFACE)
-      nfc_response.nfcee_info.num_interface = NFC_MAX_EE_INTERFACE;
-
-    for (xx = 0; xx < nfc_response.nfcee_info.num_interface; xx++) {
-      nfc_response.nfcee_info.ee_interface[xx] = *pp++;
-    }
-
-    pp = p + yy;
-    nfc_response.nfcee_info.num_tlvs = *pp++;
-    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
-        "nfcee_id: 0x%x num_interface:0x%x/0x%x, num_tlvs:0x%x",
-        nfc_response.nfcee_info.nfcee_id, nfc_response.nfcee_info.num_interface,
-        yy, nfc_response.nfcee_info.num_tlvs);
-
-    if (nfc_response.nfcee_info.num_tlvs > NFC_MAX_EE_TLVS)
-      nfc_response.nfcee_info.num_tlvs = NFC_MAX_EE_TLVS;
-
-    p_tlv = &nfc_response.nfcee_info.ee_tlv[0];
-
-    for (xx = 0; xx < nfc_response.nfcee_info.num_tlvs; xx++, p_tlv++) {
-      p_tlv->tag = *pp++;
-      p_tlv->len = yy = *pp++;
-      DLOG_IF(INFO, nfc_debug_enabled)
-          << StringPrintf("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len);
-      if (p_tlv->len > NFC_MAX_EE_INFO) p_tlv->len = NFC_MAX_EE_INFO;
+      nfc_response.nfcee_info.ee_status = *pp++;
+      yy = *pp;
+      nfc_response.nfcee_info.num_interface = *pp++;
+      if (len < yy + 1) {
+        p_cback = nullptr;
+        break;
+      } else {
+        len -= yy + 1;
+      }
       p = pp;
-      STREAM_TO_ARRAY(p_tlv->info, pp, p_tlv->len);
-      pp = p += yy;
-    }
-  } else if (op_code == NCI_MSG_NFCEE_MODE_SET) {
-    nfc_response.mode_set.status = *pp;
-    nfc_response.mode_set.nfcee_id = *p_old++;
-    nfc_response.mode_set.mode = *p_old++;
-    event = NFC_NFCEE_MODE_SET_REVT;
-    nfc_cb.flags &= ~NFC_FL_WAIT_MODE_SET_NTF;
-    nfc_stop_timer(&nfc_cb.nci_mode_set_ntf_timer);
-  } else if (op_code == NCI_MSG_NFCEE_STATUS) {
-    event = NFC_NFCEE_STATUS_REVT;
-    nfc_response.nfcee_status.status = NCI_STATUS_OK;
-    nfc_response.nfcee_status.nfcee_id = *pp++;
-    nfc_response.nfcee_status.nfcee_status = *pp;
-  } else {
-    p_cback = nullptr;
-    LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
+
+      if (nfc_response.nfcee_info.num_interface > NFC_MAX_EE_INTERFACE)
+        nfc_response.nfcee_info.num_interface = NFC_MAX_EE_INTERFACE;
+
+      for (xx = 0; xx < nfc_response.nfcee_info.num_interface; xx++) {
+        nfc_response.nfcee_info.ee_interface[xx] = *pp++;
+      }
+
+      pp = p + yy;
+      nfc_response.nfcee_info.num_tlvs = *pp++;
+      DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+          "nfcee_id: 0x%x num_interface:0x%x/0x%x, num_tlvs:0x%x",
+          nfc_response.nfcee_info.nfcee_id,
+          nfc_response.nfcee_info.num_interface, yy,
+          nfc_response.nfcee_info.num_tlvs);
+
+      if (nfc_response.nfcee_info.num_tlvs > 0 && len < 2) {
+        p_cback = nullptr;
+        break;
+      }
+      if (nfc_response.nfcee_info.num_tlvs > NFC_MAX_EE_TLVS)
+        nfc_response.nfcee_info.num_tlvs = NFC_MAX_EE_TLVS;
+
+      p_tlv = &nfc_response.nfcee_info.ee_tlv[0];
+
+      for (xx = 0; xx < nfc_response.nfcee_info.num_tlvs; xx++, p_tlv++) {
+        p_tlv->tag = *pp++;
+        p_tlv->len = yy = *pp++;
+        if (len < yy + 2) {
+          p_cback = nullptr;
+          break;
+        } else {
+          len -= yy + 2;
+        }
+        DLOG_IF(INFO, nfc_debug_enabled)
+            << StringPrintf("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len);
+        if (p_tlv->len > NFC_MAX_EE_INFO) p_tlv->len = NFC_MAX_EE_INFO;
+        p = pp;
+        STREAM_TO_ARRAY(p_tlv->info, pp, p_tlv->len);
+        pp = p += yy;
+      }
+      break;
+    case NCI_MSG_NFCEE_MODE_SET:
+      if (len < 1) {
+        nfc_response.mode_set.status = NCI_STATUS_MESSAGE_CORRUPTED;
+      } else {
+        nfc_response.mode_set.status = *pp;
+      }
+      nfc_response.mode_set.nfcee_id = *p_old++;
+      nfc_response.mode_set.mode = *p_old++;
+      event = NFC_NFCEE_MODE_SET_REVT;
+      nfc_cb.flags &= ~NFC_FL_WAIT_MODE_SET_NTF;
+      nfc_stop_timer(&nfc_cb.nci_mode_set_ntf_timer);
+      break;
+    case NCI_MSG_NFCEE_STATUS:
+      event = NFC_NFCEE_STATUS_REVT;
+      if (len < 2) {
+        nfc_response.nfcee_status.status = NCI_STATUS_MESSAGE_CORRUPTED;
+        break;
+      }
+      nfc_response.nfcee_status.status = NCI_STATUS_OK;
+      nfc_response.nfcee_status.nfcee_id = *pp++;
+      nfc_response.nfcee_status.nfcee_status = *pp;
+      break;
+    default:
+      p_cback = nullptr;
+      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
   }
 
   if (p_cback) (*p_cback)(event, &nfc_response);