libpldm: Fix logical errors between length check and cc decoding

When calling the encode_xxx_resp method in the registration method of
libpldmresponder, if the return value isn't PLDM_SUCCESS, the
payload_length value is only 1(return ccOnlyResponse method) and not a
complete responder data length, so we must first check cc in the
decode_xxx_resp method to avoid logic errors.

if cc != PLDM_SUCCESS, return PLDM_SUCCESS and don't need check
payload_length.
if cc == PLDM_SUCCESS, then check payload_length.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Iaf27c3a6b45638375a4ad1542dd5c4067bbd67b1
diff --git a/libpldm/base.c b/libpldm/base.c
index 0447112..6d9a67f 100644
--- a/libpldm/base.c
+++ b/libpldm/base.c
@@ -179,16 +179,17 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_GET_TYPES_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_types_resp *response =
 	    (struct pldm_get_types_resp *)msg->payload;
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	};
 
 	memcpy(&(types->byte), response->types, PLDM_MAX_TYPES / 8);
 
@@ -202,16 +203,17 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_GET_COMMANDS_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_commands_resp *response =
 	    (struct pldm_get_commands_resp *)msg->payload;
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	};
 
 	memcpy(&(commands->byte), response->commands,
 	       PLDM_MAX_CMDS_PER_TYPE / 8);
@@ -305,16 +307,17 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length < PLDM_GET_VERSION_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_version_resp *response =
 	    (struct pldm_get_version_resp *)msg->payload;
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	};
 
 	*next_transfer_handle = le32toh(response->next_transfer_handle);
 	*transfer_flag = response->transfer_flag;
@@ -366,16 +369,17 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_GET_TID_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_tid_resp *response =
 	    (struct pldm_get_tid_resp *)msg->payload;
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	};
 
 	*tid = response->tid;
 
diff --git a/libpldm/base.h b/libpldm/base.h
index d0e917f..bdecc20 100644
--- a/libpldm/base.h
+++ b/libpldm/base.h
@@ -234,6 +234,12 @@
 
 /** @brief Decode a GetPLDMTypes response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
@@ -261,6 +267,12 @@
 
 /** @brief Decode a GetPLDMCommands response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of reponse message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
@@ -293,6 +305,12 @@
 
 /** @brief Decode a GetPLDMVersion response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of reponse message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
@@ -309,6 +327,12 @@
 
 /** @brief Decode a GetTID response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
diff --git a/libpldm/bios.c b/libpldm/bios.c
index 1a705ff..c09696e 100644
--- a/libpldm/bios.c
+++ b/libpldm/bios.c
@@ -67,17 +67,18 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_GET_DATE_TIME_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_date_time_resp *response =
 	    (struct pldm_get_date_time_resp *)msg->payload;
-	*completion_code = response->completion_code;
 
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	}
 	*seconds = response->seconds;
 	*minutes = response->minutes;
 	*hours = response->hours;
@@ -187,14 +188,15 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != sizeof(struct pldm_only_cc_resp)) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
-	const struct pldm_only_cc_resp *response =
-	    (struct pldm_only_cc_resp *)msg->payload;
-	*completion_code = response->completion_code;
-
 	return PLDM_SUCCESS;
 }
 
@@ -415,6 +417,12 @@
 	    next_transfer_handle == NULL) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
+
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
@@ -422,10 +430,6 @@
 	struct pldm_set_bios_attribute_current_value_resp *response =
 	    (struct pldm_set_bios_attribute_current_value_resp *)msg->payload;
 
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	}
 	*next_transfer_handle = le32toh(response->next_transfer_handle);
 
 	return PLDM_SUCCESS;
diff --git a/libpldm/bios.h b/libpldm/bios.h
index 8306576..065e53e 100644
--- a/libpldm/bios.h
+++ b/libpldm/bios.h
@@ -192,6 +192,12 @@
 
 /** @brief Decode a GetDateTime response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
@@ -231,11 +237,17 @@
 
 /** @brief Decode a SetBiosAttributeCurrentValue response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
  *  @param[out] next_transfer_handle - Pointer to a handle that identify the
- * next portion of the transfer
+ *              next portion of the transfer
  *  @return pldm_completion_codes
  */
 int decode_set_bios_attribute_current_value_resp(
@@ -453,6 +465,12 @@
 
 /** @brief Decode a SetDateTime response message
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
diff --git a/libpldm/fru.c b/libpldm/fru.c
index b5801d7..f28231b 100644
--- a/libpldm/fru.c
+++ b/libpldm/fru.c
@@ -37,16 +37,17 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
 	struct pldm_get_fru_record_table_metadata_resp *response =
 	    (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
-	*completion_code = response->completion_code;
-	if (PLDM_SUCCESS != *completion_code) {
-		return PLDM_SUCCESS;
-	};
 
 	*fru_data_major_version = response->fru_data_major_version;
 	*fru_data_minor_version = response->fru_data_minor_version;
diff --git a/libpldm/fru.h b/libpldm/fru.h
index 2b5dd9f..6a14956 100644
--- a/libpldm/fru.h
+++ b/libpldm/fru.h
@@ -138,6 +138,12 @@
 
 /** @brief Decode GetFruRecordTable response data
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Response message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
diff --git a/libpldm/platform.c b/libpldm/platform.c
index 8b9506f..1eb4656 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -63,12 +63,15 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
 	if (payload_length > PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
-	*completion_code = msg->payload[0];
-
 	return PLDM_SUCCESS;
 }
 
@@ -220,7 +223,7 @@
 
 	*completion_code = msg->payload[0];
 	if (PLDM_SUCCESS != *completion_code) {
-		return *completion_code;
+		return PLDM_SUCCESS;
 	}
 
 	if (payload_length < PLDM_GET_PDR_MIN_RESP_BYTES) {
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 0935e04..5341f6f 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -314,6 +314,12 @@
 
 /** @brief Decode GetPDR response data
  *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Request message
  *  @param[in] payload_length - Length of request message payload
  *  @param[out] completion_code - PLDM completion code
@@ -367,6 +373,13 @@
 					 struct pldm_msg *msg);
 
 /** @brief Decode SetStateEffecterStates response data
+ *
+ *  Note:
+ *  * If the return value is not PLDM_SUCCESS, it represents a
+ * transport layer error.
+ *  * If the completion_code value is not PLDM_SUCCESS, it represents a
+ * protocol layer error and all the out-parameters are invalid.
+ *
  *  @param[in] msg - Request message
  *  @param[in] payload_length - Length of response message payload
  *  @param[out] completion_code - PLDM completion code