Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5ba99a1 authored by Mehmet Murat Sevim's avatar Mehmet Murat Sevim Committed by Automerger Merge Worker
Browse files

Merge "Revert "Fix an OOB write bug in attp_build_value_cmd"" into tm-dev am: 24ed2f4e

parents 4aacdd47 24ed2f4e
Loading
Loading
Loading
Loading
+11 −44
Original line number Diff line number Diff line
@@ -286,79 +286,46 @@ static BT_HDR* attp_build_opcode_cmd(uint8_t op_code) {
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, *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)

  uint8_t *p, *pp, pair_len, *p_pair_len;
  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;
    size_now += 1;
    CHECK_SIZE();
    // this field will be backfilled in the end of this function
    UINT8_TO_STREAM(p, pair_len);
    p_buf->len += 1;
  }

  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 && payload_size > size_now) {
  if (len > 0 && p_data != NULL) {
    /* ensure data not exceed MTU size */
    if (payload_size - size_now < len) {
      len = payload_size - size_now;
    if (payload_size - p_buf->len < len) {
      len = payload_size - p_buf->len;
      /* update handle value pair length */
      if (op_code == GATT_RSP_READ_BY_TYPE) {
        pair_len = (len + 2);
      }
      if (op_code == GATT_RSP_READ_BY_TYPE) *p_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;
}