Merge cherrypicks of ['googleplex-android-review.googlesource.com/22948134', 'googleplex-android-review.googlesource.com/25503067', 'googleplex-android-review.googlesource.com/25494184'] into security-aosp-tm-release.

Change-Id: Ie7c4dc397d6aeac9155f495fbabd99c60c222b18
diff --git a/system/btif/src/btif_gatt_util.cc b/system/btif/src/btif_gatt_util.cc
index 290c431..404dc6a 100644
--- a/system/btif/src/btif_gatt_util.cc
+++ b/system/btif/src/btif_gatt_util.cc
@@ -18,6 +18,8 @@
 
 #define LOG_TAG "bt_btif_gatt"
 
+#include <algorithm>
+
 #include "btif_gatt_util.h"
 
 #include <errno.h>
@@ -51,9 +53,9 @@
 void btif_to_bta_response(tGATTS_RSP* p_dest, btgatt_response_t* p_src) {
   p_dest->attr_value.auth_req = p_src->attr_value.auth_req;
   p_dest->attr_value.handle = p_src->attr_value.handle;
-  p_dest->attr_value.len = p_src->attr_value.len;
+  p_dest->attr_value.len = std::min<uint16_t>(p_src->attr_value.len, GATT_MAX_ATTR_LEN);
   p_dest->attr_value.offset = p_src->attr_value.offset;
-  memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
+  memcpy(p_dest->attr_value.value, p_src->attr_value.value, p_dest->attr_value.len);
 }
 
 /*******************************************************************************
diff --git a/system/stack/gatt/att_protocol.cc b/system/stack/gatt/att_protocol.cc
index 63847db..f055fb8 100644
--- a/system/stack/gatt/att_protocol.cc
+++ b/system/stack/gatt/att_protocol.cc
@@ -164,7 +164,13 @@
     uint16_t payload_size, tGATT_FIND_TYPE_VALUE* p_value_type) {
   uint8_t* p;
   uint16_t len = p_value_type->value_len;
-  BT_HDR* p_buf =
+  BT_HDR* p_buf = nullptr;
+
+  if (payload_size < 5) {
+    return nullptr;
+  }
+
+  p_buf =
       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
@@ -280,46 +286,79 @@
 static BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code,
                                     uint16_t handle, uint16_t offset,
                                     uint16_t len, uint8_t* p_data) {
-  uint8_t *p, *pp, pair_len, *p_pair_len;
+  uint8_t *p, *pp, *p_pair_len;
+  size_t pair_len;
+  size_t size_now = 1;
+
+  #define CHECK_SIZE() do {                      \
+    if (size_now > payload_size) {               \
+      LOG(ERROR) << "payload size too small";    \
+      osi_free(p_buf);                           \
+      return nullptr;                            \
+    }                                            \
+  } while (false)
+
   BT_HDR* p_buf =
       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
 
   p = pp = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+  CHECK_SIZE();
   UINT8_TO_STREAM(p, op_code);
   p_buf->offset = L2CAP_MIN_OFFSET;
-  p_buf->len = 1;
 
   if (op_code == GATT_RSP_READ_BY_TYPE) {
     p_pair_len = p;
     pair_len = len + 2;
-    UINT8_TO_STREAM(p, pair_len);
-    p_buf->len += 1;
+    size_now += 1;
+    CHECK_SIZE();
+    // this field will be backfilled in the end of this function
   }
+
   if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) {
+    size_now += 2;
+    CHECK_SIZE();
     UINT16_TO_STREAM(p, handle);
-    p_buf->len += 2;
   }
 
   if (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_RSP_PREPARE_WRITE) {
+    size_now += 2;
+    CHECK_SIZE();
     UINT16_TO_STREAM(p, offset);
-    p_buf->len += 2;
   }
 
-  if (len > 0 && p_data != NULL) {
+  if (len > 0 && p_data != NULL && payload_size > size_now) {
     /* ensure data not exceed MTU size */
-    if (payload_size - p_buf->len < len) {
-      len = payload_size - p_buf->len;
+    if (payload_size - size_now < len) {
+      len = payload_size - size_now;
       /* update handle value pair length */
-      if (op_code == GATT_RSP_READ_BY_TYPE) *p_pair_len = (len + 2);
+      if (op_code == GATT_RSP_READ_BY_TYPE) {
+        pair_len = (len + 2);
+      }
 
       LOG(WARNING) << StringPrintf(
           "attribute value too long, to be truncated to %d", len);
     }
 
+    size_now += len;
+    CHECK_SIZE();
     ARRAY_TO_STREAM(p, p_data, len);
-    p_buf->len += len;
   }
 
+  // backfill pair len field
+  if (op_code == GATT_RSP_READ_BY_TYPE) {
+    if (pair_len > UINT8_MAX) {
+      LOG(ERROR) << "pair_len greater than" << UINT8_MAX;
+      osi_free(p_buf);
+      return nullptr;
+    }
+
+    *p_pair_len = (uint8_t) pair_len;
+  }
+
+  #undef CHECK_SIZE
+
+  p_buf->len = (uint16_t) size_now;
   return p_buf;
 }