Bluetooth: Check buffer length in GATT rsp functions

Add length checks local to the parsing function. This removes the need
for a separate data validation step.

Signed-off-by: Aleksander Wasaznik <aleksander.wasaznik@nordicsemi.no>
(cherry picked from commit 3eeb8f8d18d02962e0a842e46ad247648f84fa41)
diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c
index 69d43de..6744d77 100644
--- a/subsys/bluetooth/host/gatt.c
+++ b/subsys/bluetooth/host/gatt.c
@@ -3910,7 +3910,7 @@
 			   struct bt_gatt_discover_params *params,
 			   uint16_t length)
 {
-	const struct bt_att_read_type_rsp *rsp = pdu;
+	const struct bt_att_read_type_rsp *rsp;
 	uint16_t handle = 0U;
 	struct bt_gatt_include value;
 	union {
@@ -3919,6 +3919,13 @@
 		struct bt_uuid_128 u128;
 	} u;
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto done;
+	}
+
+	rsp = pdu;
+
 	/* Data can be either in UUID16 or UUID128 */
 	switch (rsp->len) {
 	case 8: /* UUID16 */
@@ -4003,7 +4010,7 @@
 				  struct bt_gatt_discover_params *params,
 				  uint16_t length)
 {
-	const struct bt_att_read_type_rsp *rsp = pdu;
+	const struct bt_att_read_type_rsp *rsp;
 	uint16_t handle = 0U;
 	union {
 		struct bt_uuid uuid;
@@ -4011,6 +4018,13 @@
 		struct bt_uuid_128 u128;
 	} u;
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto done;
+	}
+
+	rsp = pdu;
+
 	/* Data can be either in UUID16 or UUID128 */
 	switch (rsp->len) {
 	case 7: /* UUID16 */
@@ -4084,7 +4098,7 @@
 					 struct bt_gatt_discover_params *params,
 					 uint16_t length)
 {
-	const struct bt_att_read_type_rsp *rsp = pdu;
+	const struct bt_att_read_type_rsp *rsp;
 	uint16_t handle = 0U;
 	uint16_t uuid_val;
 
@@ -4094,6 +4108,13 @@
 
 	uuid_val = BT_UUID_16(params->uuid)->val;
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto done;
+	}
+
+	rsp = pdu;
+
 	/* Parse characteristics found */
 	for (length--, pdu = rsp->data; length >= rsp->len;
 	     length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
@@ -4103,9 +4124,16 @@
 			struct bt_gatt_cep cep;
 			struct bt_gatt_scc scc;
 		} value;
-		const struct bt_att_data *data = pdu;
+		const struct bt_att_data *data;
 		struct bt_gatt_attr attr;
 
+		if (length < sizeof(*data)) {
+			LOG_WRN("Parse err dat");
+			goto done;
+		}
+
+		data = pdu;
+
 		handle = sys_le16_to_cpu(data->handle);
 		/* Handle 0 is invalid */
 		if (!handle) {
@@ -4114,17 +4142,39 @@
 
 		switch (uuid_val) {
 		case BT_UUID_GATT_CEP_VAL:
+			if (length < sizeof(*data) + sizeof(uint16_t)) {
+				LOG_WRN("Parse err cep");
+				goto done;
+			}
+
 			value.cep.properties = sys_get_le16(data->value);
 			break;
 		case BT_UUID_GATT_CCC_VAL:
+			if (length < sizeof(*data) + sizeof(uint16_t)) {
+				LOG_WRN("Parse err ccc");
+				goto done;
+			}
+
 			value.ccc.flags = sys_get_le16(data->value);
 			break;
 		case BT_UUID_GATT_SCC_VAL:
+			if (length < sizeof(*data) + sizeof(uint16_t)) {
+				LOG_WRN("Parse err scc");
+				goto done;
+			}
+
 			value.scc.flags = sys_get_le16(data->value);
 			break;
 		case BT_UUID_GATT_CPF_VAL:
 		{
-			struct gatt_cpf *cpf = (struct gatt_cpf *)data->value;
+			struct gatt_cpf *cpf;
+
+			if (length < sizeof(*data) + sizeof(*cpf)) {
+				LOG_WRN("Parse err cpf");
+				goto done;
+			}
+
+			cpf = (void *)data->value;
 
 			value.cpf.format = cpf->format;
 			value.cpf.exponent = cpf->exponent;
@@ -4227,7 +4277,7 @@
 				  struct bt_gatt_discover_params *params,
 				  uint16_t length)
 {
-	const struct bt_att_read_group_rsp *rsp = pdu;
+	const struct bt_att_read_group_rsp *rsp;
 	uint16_t start_handle, end_handle = 0U;
 	union {
 		struct bt_uuid uuid;
@@ -4235,6 +4285,13 @@
 		struct bt_uuid_128 u128;
 	} u;
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto done;
+	}
+
+	rsp = pdu;
+
 	/* Data can be either in UUID16 or UUID128 */
 	switch (rsp->len) {
 	case 6: /* UUID16 */
@@ -4365,7 +4422,7 @@
 			       const void *pdu, uint16_t length,
 			       void *user_data)
 {
-	const struct bt_att_find_info_rsp *rsp = pdu;
+	const struct bt_att_find_info_rsp *rsp;
 	struct bt_gatt_discover_params *params = user_data;
 	uint16_t handle = 0U;
 	uint16_t len;
@@ -4387,6 +4444,13 @@
 		goto done;
 	}
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto done;
+	}
+
+	rsp = pdu;
+
 	/* Data can be either in UUID16 or UUID128 */
 	switch (rsp->format) {
 	case BT_ATT_INFO_16:
@@ -4992,7 +5056,7 @@
 				   void *user_data)
 {
 	struct bt_gatt_write_params *params = user_data;
-	const struct bt_att_prepare_write_rsp *rsp = pdu;
+	const struct bt_att_prepare_write_rsp *rsp;
 	size_t len;
 	bool data_valid;
 
@@ -5004,6 +5068,13 @@
 		return;
 	}
 
+	if (length < sizeof(*rsp)) {
+		LOG_WRN("Parse err");
+		goto fail;
+	}
+
+	rsp = pdu;
+
 	len = length - sizeof(*rsp);
 	if (len > params->length) {
 		LOG_ERR("Incorrect length, canceling write");