iscsi: properly handle partial keys

This includes properly detecting when a key's name
extends past the end of the valid data.

Note that the unit tests were using sizeof() instead
of strlen() since some of the strings contain
NULL characters.  This means that we should be
subtracting one to account for the implicit null
character at the end of the string.  Note that the
iSCSI spec only says that the key/value pair has to
end with a null character - a key/value pair that
is split across two PDUs will not have a NULL character
at the end of the first PDU.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: Ie95d6dd3b9ffa6a3902a31771ac4edb482418cce

Reviewed-on: https://review.gerrithub.io/c/442450
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Jim Harris 2019-01-28 16:25:48 -07:00
parent a95f341361
commit 7d1db86f54
2 changed files with 36 additions and 6 deletions

View File

@ -223,7 +223,9 @@ spdk_iscsi_parse_param(struct iscsi_param **params, const uint8_t *data, uint32_
int key_len, val_len;
int max_len;
key_end = strchr(data, '=');
data_len = strnlen(data, data_len);
/* No such thing as strnchr so use memchr instead. */
key_end = memchr(data, '=', data_len);
if (!key_end) {
SPDK_ERRLOG("'=' not found\n");
return -1;
@ -343,13 +345,29 @@ spdk_iscsi_parse_params(struct iscsi_param **params, const uint8_t *data,
/*
* reverse iterate the string from the tail not including '\0'
* index of last '\0' is len -1.
*/
for (i = len - 2; data[i] != '\0' && i > 0; i--) {
for (i = len - 1; data[i] != '\0' && i > 0; i--) {
;
}
*partial_parameter = xstrdup(&data[i == 0 ? 0 : i + 1]);
len = (i == 0 ? 0 : i + 1);
if (i != 0) {
/* We found a NULL character - don't copy it into the
* partial parameter.
*/
i++;
}
*partial_parameter = calloc(1, len - i + 1);
if (*partial_parameter == NULL) {
SPDK_ERRLOG("could not allocate partial parameter\n");
return -1;
}
memcpy(*partial_parameter, &data[i], len - i);
if (i == 0) {
/* No full parameters to parse - so return now. */
return 0;
} else {
len = i - 1;
}
}
while (offset < len && data[offset] != '\0') {

View File

@ -188,7 +188,7 @@ list_negotiation_test(void)
#define PARSE(strconst, partial_enabled, partial_text) \
data = strconst; \
len = sizeof(strconst); \
len = sizeof(strconst) - 1; \
rc = spdk_iscsi_parse_params(&params, data, len, partial_enabled, partial_text)
#define EXPECT_VAL(key, expected_value) \
@ -274,6 +274,18 @@ parse_valid_test(void)
EXPECT_VAL("OOOOLL", "MMMM");
CU_ASSERT_PTR_NULL(partial_parameter);
partial_parameter = NULL;
data = "PartialKey=";
len = 7;
rc = spdk_iscsi_parse_params(&params, data, len, true, &partial_parameter);
CU_ASSERT(rc == 0);
CU_ASSERT_STRING_EQUAL(partial_parameter, "Partial");
EXPECT_NULL("PartialKey");
PARSE("Key=Value", false, &partial_parameter);
CU_ASSERT(rc == 0);
EXPECT_VAL("PartialKey", "Value");
CU_ASSERT_PTR_NULL(partial_parameter);
spdk_iscsi_param_free(params);
}