[v2] net/cpfl: fix cpfl parser issue
Checks
Commit Message
CPFL parser was incorrectly parsing the mask value of the
next_proto_id field from recipe.json file as a string
instead of unsigned integer.
Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
Cc: stable@dpdk.org
Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v2:
* Fixed CI issues.
---
drivers/net/cpfl/cpfl_flow_parser.c | 34 +++++++++++++++++++----------
1 file changed, 22 insertions(+), 12 deletions(-)
Comments
On Wed, Jul 31, 2024 at 07:23:03AM +0000, Praveen Shetty wrote:
> CPFL parser was incorrectly parsing the mask value of the
> next_proto_id field from recipe.json file as a string
> instead of unsigned integer.
>
> Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
> Cc: stable@dpdk.org
>
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
>
> ---
> v2:
> * Fixed CI issues.
> ---
> drivers/net/cpfl/cpfl_flow_parser.c | 34 +++++++++++++++++++----------
> 1 file changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c
> index 40569ddc6f..7800ad97ea 100644
> --- a/drivers/net/cpfl/cpfl_flow_parser.c
> +++ b/drivers/net/cpfl/cpfl_flow_parser.c
> @@ -198,6 +198,8 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
> for (i = 0; i < len; i++) {
> json_t *object;
> const char *name, *mask;
> + uint32_t mask_32b = 0;
> + int ret;
>
> object = json_array_get(ob_fields, i);
> name = cpfl_json_t_to_string(object, "name");
> @@ -213,20 +215,28 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>
> if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
> js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
> - mask = cpfl_json_t_to_string(object, "mask");
> - if (!mask) {
> - PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> - goto err;
> - }
> - if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> - PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> - goto err;
> + /* Added a check for parsing mask value of the next_proto_id field. */
> + if (strcmp(name, "next_proto_id") == 0) {
> + ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
> + if (ret < 0) {
> + PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
> + goto err;
> + }
> + js_field->fields[i].mask_32b = mask_32b;
> + } else {
> + mask = cpfl_json_t_to_string(object, "mask");
> + if (!mask) {
> + PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> + goto err;
> + }
> + if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> + PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> + goto err;
> + }
> + rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);
+1 for replacing strncpy with something safer, since original code is wrong
and can leave a non-null-terminated string, but unfortunately the copy here
isn't quite right. For strlcpy and rte_strscpy, you specify the exact
buffer size, not the size-1.
Also, you don't need to check the length and then do the copy, you might as
well just do the copy using strscpy or strlcpy and check the return value
from it. Saves iterating the string twice (once for length, second time for
copy). For example:
if (rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE) < 0) {
PMD_DRV_LOG(ERR, "The 'mask' is too long.");
goto err;
}
Regards,
/Bruce
> CPFL parser was incorrectly parsing the mask value of the
> next_proto_id field from recipe.json file as a string instead of
> unsigned integer.
>
> Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
> Cc: stable@dpdk.org
>
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
>
> ---
> v2:
> * Fixed CI issues.
> ---
> drivers/net/cpfl/cpfl_flow_parser.c | 34
> +++++++++++++++++++----------
> 1 file changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/cpfl/cpfl_flow_parser.c
> b/drivers/net/cpfl/cpfl_flow_parser.c
> index 40569ddc6f..7800ad97ea 100644
> --- a/drivers/net/cpfl/cpfl_flow_parser.c
> +++ b/drivers/net/cpfl/cpfl_flow_parser.c
> @@ -198,6 +198,8 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
> for (i = 0; i < len; i++) {
> json_t *object;
> const char *name, *mask;
> + uint32_t mask_32b = 0;
> + int ret;
>
> object = json_array_get(ob_fields, i);
> name = cpfl_json_t_to_string(object, "name"); @@ -213,20 +215,28 @@
> cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>
> if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
> js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
> - mask = cpfl_json_t_to_string(object, "mask");
> - if (!mask) {
> - PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> - goto err;
> - }
> - if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> - PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> - goto err;
> + /* Added a check for parsing mask value of the next_proto_id field. */
> + if (strcmp(name, "next_proto_id") == 0) {
> + ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
> + if (ret < 0) {
> + PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
> + goto err;
> + }
> + js_field->fields[i].mask_32b = mask_32b;
> + } else {
> + mask = cpfl_json_t_to_string(object, "mask");
> + if (!mask) {
> + PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> + goto err;
> + }
> + if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> + PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> + goto err;
> + }
> + rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE -
> +1);
+1 for replacing strncpy with something safer, since original code is
+wrong
and can leave a non-null-terminated string, but unfortunately the copy here isn't quite right. For strlcpy and rte_strscpy, you specify the exact buffer size, not the size-1.
Also, you don't need to check the length and then do the copy, you might as well just do the copy using strscpy or strlcpy and check the return value from it. Saves iterating the string twice (once for length, second time for copy). For example:
if (rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE) < 0) {
PMD_DRV_LOG(ERR, "The 'mask' is too long.");
goto err;
}
Thanks, will fix this in v3.
Regards,
/Bruce
@@ -198,6 +198,8 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
for (i = 0; i < len; i++) {
json_t *object;
const char *name, *mask;
+ uint32_t mask_32b = 0;
+ int ret;
object = json_array_get(ob_fields, i);
name = cpfl_json_t_to_string(object, "name");
@@ -213,20 +215,28 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
- mask = cpfl_json_t_to_string(object, "mask");
- if (!mask) {
- PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
- goto err;
- }
- if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
- PMD_DRV_LOG(ERR, "The 'mask' is too long.");
- goto err;
+ /* Added a check for parsing mask value of the next_proto_id field. */
+ if (strcmp(name, "next_proto_id") == 0) {
+ ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
+ goto err;
+ }
+ js_field->fields[i].mask_32b = mask_32b;
+ } else {
+ mask = cpfl_json_t_to_string(object, "mask");
+ if (!mask) {
+ PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
+ goto err;
+ }
+ if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
+ PMD_DRV_LOG(ERR, "The 'mask' is too long.");
+ goto err;
+ }
+ rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);
}
- strncpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);
- } else {
- uint32_t mask_32b;
- int ret;
+ } else {
ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
if (ret < 0) {
PMD_DRV_LOG(ERR, "Can not parse uint32 'mask'.");