|SUCCESS| examples/flow_filtering: fix null derefs and memory leaks
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Tue Mar 31 20:46:06 CEST 2026
Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/162794
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-03-31
git sha: 3ebb8789136a
Author: Shani Peretz <shperetz at nvidia.com>
Subject: [PATCH] examples/flow_filtering: fix null derefs and memory leaks
This patch adds missing return statements after failed calloc NULL checks
to prevent null pointer dereferences, and frees previously allocated
memory on error paths to prevent leaked storage when a subsequent
allocation fails.
> diff --git a/examples/flow_filtering/snippets/snippet_match_gre.c b/examples/flow_filtering/snippets/snippet_match_gre.c
> index 477ec59451..f1638f38c5 100644
> --- a/examples/flow_filtering/snippets/snippet_match_gre.c
> +++ b/examples/flow_filtering/snippets/snippet_match_gre.c
[ ... ]
> @@ -40,12 +42,17 @@ snippet_match_gre_create_patterns(struct rte_flow_item *pattern)
> struct rte_flow_item_gre_opt *gre_opt_spec;
>
> gre_spec = calloc(1, sizeof(struct rte_flow_item_gre));
> - if (gre_spec == NULL)
> + if (gre_spec == NULL) {
> fprintf(stderr, "Failed to allocate memory for gre_spec\n");
> + return;
> + }
>
> gre_opt_spec = calloc(1, sizeof(struct rte_flow_item_gre_opt));
> - if (gre_opt_spec == NULL)
> + if (gre_opt_spec == NULL) {
> fprintf(stderr, "Failed to allocate memory for gre_opt_spec\n");
> + free(gre_spec);
> + return;
> + }
Does the caller of snippet_match_gre_create_patterns() ever free the
gre_spec or gre_opt_spec structures that are being allocated here? These
are stored into the pattern array but the caller may not have visibility
into what was allocated on the error path.
[ ... ]
> diff --git a/examples/flow_filtering/snippets/snippet_match_integrity_flags.c b/examples/flow_filtering/snippets/snippet_match_integrity_flags.c
[ ... ]
> @@ -38,16 +40,21 @@ snippet_match_integrity_flags_create_patterns(struct rte_flow_item *pattern)
> struct rte_flow_item_integrity *integrity_mask;
>
> integrity_spec = calloc(1, sizeof(struct rte_flow_item_integrity));
> - if (integrity_spec == NULL)
> + if (integrity_spec == NULL) {
> fprintf(stderr, "Failed to allocate memory for integrity_spec\n");
> + return;
> + }
>
> integrity_spec->level = 0;
> integrity_spec->l3_ok = 1;
> integrity_spec->ipv4_csum_ok = 1;
>
> integrity_mask = calloc(1, sizeof(struct rte_flow_item_integrity));
> - if (integrity_mask == NULL)
> + if (integrity_mask == NULL) {
> fprintf(stderr, "Failed to allocate memory for integrity_mask\n");
> + free(integrity_spec);
> + return;
> + }
[ ... ]
> @@ -55,12 +62,21 @@ snippet_match_integrity_flags_create_patterns(struct rte_flow_item *pattern)
> integrity_mask->ipv4_csum_ok = 1;
>
> ip_spec = calloc(1, sizeof(struct rte_flow_item_ipv4));
> - if (ip_spec == NULL)
> + if (ip_spec == NULL) {
> fprintf(stderr, "Failed to allocate memory for ip_spec\n");
> + free(integrity_spec);
> + free(integrity_mask);
> + return;
> + }
>
> ip_mask = calloc(1, sizeof(struct rte_flow_item_ipv4));
> - if (ip_mask == NULL)
> + if (ip_mask == NULL) {
> fprintf(stderr, "Failed to allocate memory for ip_mask\n");
> + free(integrity_spec);
> + free(integrity_mask);
> + free(ip_spec);
> + return;
> + }
Does the successful path in snippet_match_integrity_flags_create_patterns()
properly handle all four allocated structures? Are they all added to the
pattern array and freed by the caller?
[ ... ]
> diff --git a/examples/flow_filtering/snippets/snippet_match_mpls.c b/examples/flow_filtering/snippets/snippet_match_mpls.c
[ ... ]
> @@ -43,8 +45,10 @@ snippet_mpls_create_patterns(struct rte_flow_item *pattern)
> struct rte_flow_item_mpls *mpls_item;
>
> mpls_item = calloc(1, sizeof(struct rte_flow_item_ipv4));
> - if (mpls_item == NULL)
> + if (mpls_item == NULL) {
> fprintf(stderr, "Failed to allocate memory for mpls_item\n");
> + return;
> + }
Does this code allocate the wrong size? The allocation uses
sizeof(struct rte_flow_item_ipv4) but the pointer is of type
rte_flow_item_mpls.
[ ... ]
> diff --git a/examples/flow_filtering/snippets/snippet_match_nvgre.c b/examples/flow_filtering/snippets/snippet_match_nvgre.c
[ ... ]
> @@ -36,20 +38,34 @@ void
> snippet_match_nvgre_create_patterns(struct rte_flow_item *pattern)
> {
> struct rte_flow_item_nvgre *nvgre = calloc(1, sizeof(struct rte_flow_item_nvgre));
> - if (nvgre == NULL)
> + if (nvgre == NULL) {
> fprintf(stderr, "Failed to allocate memory for nvgre\n");
> + return;
> + }
>
> struct rte_flow_item_udp *udp = calloc(1, sizeof(struct rte_flow_item_udp));
> - if (udp == NULL)
> + if (udp == NULL) {
> fprintf(stderr, "Failed to allocate memory for udp\n");
> + free(nvgre);
> + return;
> + }
>
> struct rte_flow_item_nvgre *nvgre_mask = calloc(1, sizeof(struct rte_flow_item_nvgre));
> - if (nvgre_mask == NULL)
> + if (nvgre_mask == NULL) {
> fprintf(stderr, "Failed to allocate memory for nvgre_mask\n");
> + free(nvgre);
> + free(udp);
> + return;
> + }
>
> struct rte_flow_item_udp *udp_mask = calloc(1, sizeof(struct rte_flow_item_udp));
> - if (udp_mask == NULL)
> + if (udp_mask == NULL) {
> fprintf(stderr, "Failed to allocate memory for udp_mask\n");
> + free(nvgre);
> + free(udp);
> + free(nvgre_mask);
> + return;
> + }
Does the successful path in snippet_match_nvgre_create_patterns() ensure
all four allocated structures are properly freed by the caller?
More information about the test-report
mailing list