Skip to contentSkip to conversation

lib/ring: do not allow zero size ring

PATCH Superseded Isaac Boukris 5 participants 7 messages Nov 10, 2025 – Nov 11, 2025

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 lib/ring: do not allow zero size ring

this might happen when for instance the ring size is read from config, and would cause runtime crash.

---
 app/test/test_ring.c | 7 +++++++
 lib/ring/rte_ring.c  | 4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)
app/test/test_ring.c +7 -0
index ba1fec1de3..81231ecfc2 100644
@@ -505,6 +505,13 @@ test_ring_negative_tests(void)
 	struct rte_ring *rt = NULL;
 	unsigned int i;
 
+        /* Test zero size ring */
+	rp = test_ring_create("test_zero_size_ring", -1, 0, SOCKET_ID_ANY, 0);
+	if (rp != NULL) {
+		printf("Test failed to detect zero size ring\n");
+		goto test_fail;
+	}
+
 	/* Test with esize not a multiple of 4 */
 	rp = test_ring_create("test_bad_element_size", 23,
 				RING_SIZE + 1, SOCKET_ID_ANY, 0);
lib/ring/rte_ring.c +2 -2
index edd63aa535..f9434de536 100644
@@ -67,7 +67,7 @@ rte_ring_get_memsize_elem(unsigned int esize, unsigned int count)
 	}
 
 	/* count must be a power of 2 */
-	if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK )) {
+	if ((count == 0) || (!POWEROF2(count)) || (count > RTE_RING_SZ_MASK )) {
 		RING_LOG(ERR,
 			"Requested number of elements is invalid, must be power of 2, and not exceed %u",
 			RTE_RING_SZ_MASK);
@@ -227,7 +227,7 @@ rte_ring_init(struct rte_ring *r, const char *name, unsigned int count,
 		r->mask = r->size - 1;
 		r->capacity = count;
 	} else {
-		if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK)) {
+		if ((count == 0) || (!POWEROF2(count)) || (count > RTE_RING_SZ_MASK)) {
 			RING_LOG(ERR,
 				"Requested size is invalid, must be power of 2, and not exceed the size limit %u",
 				RTE_RING_SZ_MASK);
Signature · 1 line
2.49.0
#1 lore raw

PATCH v2 1/1 lib/ring: do not allow zero size ring

this might happen when for instance the ring size is read from config, and would cause runtime crash.

---

v2:
* move the fix to the POWEROF2 macro itself.
* fixed style in the test code.

 app/test/test_ring.c | 7 +++++++
 lib/ring/rte_ring.c  | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)
app/test/test_ring.c +7 -0
index ba1fec1de3..3078348b2f 100644
@@ -505,6 +505,13 @@ test_ring_negative_tests(void)
 	struct rte_ring *rt = NULL;
 	unsigned int i;
 
+	/* Test zero size ring */
+	rp = test_ring_create("test_zero_size_ring", -1, 0, SOCKET_ID_ANY, 0);
+	if (rp != NULL) {
+		printf("Test failed to detect zero size ring\n");
+		goto test_fail;
+	}
+
 	/* Test with esize not a multiple of 4 */
 	rp = test_ring_create("test_bad_element_size", 23,
 				RING_SIZE + 1, SOCKET_ID_ANY, 0);
lib/ring/rte_ring.c +1 -1
index edd63aa535..0a9fc31530 100644
@@ -47,7 +47,7 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
 		     RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ)
 
 /* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
+#define POWEROF2(x) ((x != 0) && (((x)-1) & (x)) == 0)
 
 /* by default set head/tail distance as 1/8 of ring capacity */
 #define HTD_MAX_DEF	8
Signature · 1 line
2.49.0
Acked-by on v2 1/1
#2 lore raw
Quoted 37 lines · Isaac Boukris

this might happen when for instance the ring size is read from config, and would cause runtime crash.

---

v2:
* move the fix to the POWEROF2 macro itself.
* fixed style in the test code.

  app/test/test_ring.c | 7 +++++++
  lib/ring/rte_ring.c  | 2 +-
  2 files changed, 8 insertions(+), 1 deletion(-)
app/test/test_ring.c +7 -0
index ba1fec1de3..3078348b2f 100644
@@ -505,6 +505,13 @@ test_ring_negative_tests(void)
  	struct rte_ring *rt = NULL;
  	unsigned int i;
 
+	/* Test zero size ring */
+	rp = test_ring_create("test_zero_size_ring", -1, 0, SOCKET_ID_ANY, 0);
+	if (rp != NULL) {
+		printf("Test failed to detect zero size ring\n");
+		goto test_fail;
+	}
+
  	/* Test with esize not a multiple of 4 */
  	rp = test_ring_create("test_bad_element_size", 23,
  				RING_SIZE + 1, SOCKET_ID_ANY, 0);
lib/ring/rte_ring.c +0 -0
index edd63aa535..0a9fc31530 100644

lib/ring/rte_ring.c EAL_REGISTER_TAILQ(rte_ring_tailq) · line 53

Quoted 8 lines
lib/ring/rte_ring.c +1 -1
@@ -47,7 +47,7 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
  		     RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ)
 
  /* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
+#define POWEROF2(x) ((x != 0) && (((x)-1) & (x)) == 0)
 
  /* by default set head/tail distance as 1/8 of ring capacity */
  #define HTD_MAX_DEF	8
Acked-by on v2 1/1
#3 lore raw
In reply to Isaac Boukris

lib/ring/rte_ring.c EAL_REGISTER_TAILQ(rte_ring_tailq) · line 50

Quoted 10 lines
lib/ring/rte_ring.c +1 -1
index edd63aa535..0a9fc31530 100644
@@ -47,7 +47,7 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
 		     RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ)
 
 /* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
+#define POWEROF2(x) ((x != 0) && (((x)-1) & (x)) == 0)

Please remove this private macro and use the RTE_IS_POWER_OF_2() macro from rte_bitops.h instead. With such modification,

<feature creep>
app/pdump/main.c also defines a POWEROF2() macro, which could be replaced by RTE_IS_POWER_OF_2(). But changing that is unrelated to your improvement in this patch, and should be an independent patch. Not your responsibility to fix that; just mentioning it for someone to pick it up. </feature creep>

#4 lore raw

PATCH v3 1/1 lib/ring: do not allow zero size ring

In reply to Isaac Boukris

this might happen when for instance the ring size is read from config, and would cause runtime crash. Do so by using the RTE_IS_POWER_OF_2 macro.

---

v3:
* changed to use the RTE_IS_POWER_OF_2 macro.

v2:
* move the fix to the POWEROF2 macro itself.
* fixed style in the test code.

 app/test/test_ring.c | 7 +++++++
 lib/ring/rte_ring.c  | 8 +++-----
 2 files changed, 10 insertions(+), 5 deletions(-)
app/test/test_ring.c +7 -0
index ba1fec1de3..3078348b2f 100644
@@ -505,6 +505,13 @@ test_ring_negative_tests(void)
 	struct rte_ring *rt = NULL;
 	unsigned int i;
 
+	/* Test zero size ring */
+	rp = test_ring_create("test_zero_size_ring", -1, 0, SOCKET_ID_ANY, 0);
+	if (rp != NULL) {
+		printf("Test failed to detect zero size ring\n");
+		goto test_fail;
+	}
+
 	/* Test with esize not a multiple of 4 */
 	rp = test_ring_create("test_bad_element_size", 23,
 				RING_SIZE + 1, SOCKET_ID_ANY, 0);
lib/ring/rte_ring.c +3 -5
index edd63aa535..f10050a1c4 100644
@@ -25,6 +25,7 @@
 #include <rte_string_fns.h>
 #include <rte_tailq.h>
 #include <rte_telemetry.h>
+#include <rte_bitops.h>
 
 #include "rte_ring.h"
 #include "rte_ring_elem.h"
@@ -46,9 +47,6 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
 		     RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ |	       \
 		     RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ)
 
-/* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
-
 /* by default set head/tail distance as 1/8 of ring capacity */
 #define HTD_MAX_DEF	8
 
@@ -67,7 +65,7 @@ rte_ring_get_memsize_elem(unsigned int esize, unsigned int count)
 	}
 
 	/* count must be a power of 2 */
-	if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK )) {
+	if ((!RTE_IS_POWER_OF_2(count)) || (count > RTE_RING_SZ_MASK)) {
 		RING_LOG(ERR,
 			"Requested number of elements is invalid, must be power of 2, and not exceed %u",
 			RTE_RING_SZ_MASK);
@@ -227,7 +225,7 @@ rte_ring_init(struct rte_ring *r, const char *name, unsigned int count,
 		r->mask = r->size - 1;
 		r->capacity = count;
 	} else {
-		if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK)) {
+		if ((!RTE_IS_POWER_OF_2(count)) || (count > RTE_RING_SZ_MASK)) {
 			RING_LOG(ERR,
 				"Requested size is invalid, must be power of 2, and not exceed the size limit %u",
 				RTE_RING_SZ_MASK);
Signature · 1 line
2.49.0
Acked-by on v3 1/1
#5 lore raw
Quoted 82 lines

this might happen when for instance the ring size is read from config, and would cause runtime crash. Do so by using the RTE_IS_POWER_OF_2 macro.

---

v3:
* changed to use the RTE_IS_POWER_OF_2 macro.

v2:
* move the fix to the POWEROF2 macro itself.
* fixed style in the test code.

 app/test/test_ring.c | 7 +++++++
 lib/ring/rte_ring.c  | 8 +++-----
 2 files changed, 10 insertions(+), 5 deletions(-)
app/test/test_ring.c +7 -0
index ba1fec1de3..3078348b2f 100644
@@ -505,6 +505,13 @@ test_ring_negative_tests(void)
 	struct rte_ring *rt = NULL;
 	unsigned int i;
 
+	/* Test zero size ring */
+	rp = test_ring_create("test_zero_size_ring", -1, 0, SOCKET_ID_ANY, 0);
+	if (rp != NULL) {
+		printf("Test failed to detect zero size ring\n");
+		goto test_fail;
+	}
+
 	/* Test with esize not a multiple of 4 */
 	rp = test_ring_create("test_bad_element_size", 23,
 				RING_SIZE + 1, SOCKET_ID_ANY, 0);
lib/ring/rte_ring.c +2 -4
index edd63aa535..f10050a1c4 100644
@@ -25,6 +25,7 @@
 #include <rte_string_fns.h>
 #include <rte_tailq.h>
 #include <rte_telemetry.h>
+#include <rte_bitops.h>
 
 #include "rte_ring.h"
 #include "rte_ring_elem.h"
@@ -46,9 +47,6 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
 		     RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ |	       \
 		     RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ)
 
-/* true if x is a power of 2 */
-#define POWEROF2(x) ((((x)-1) & (x)) == 0)
-
 /* by default set head/tail distance as 1/8 of ring capacity */
 #define HTD_MAX_DEF	8
 
@@ -67,7 +65,7 @@ rte_ring_get_memsize_elem(unsigned int esize, unsigned int
 count)
 	}
 
 	/* count must be a power of 2 */
-	if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK )) {
+	if ((!RTE_IS_POWER_OF_2(count)) || (count > RTE_RING_SZ_MASK)) {
 		RING_LOG(ERR,
 			"Requested number of elements is invalid, must be power of

2, and not exceed %u",

lib/ring/rte_ring.c +1 -1
 			RTE_RING_SZ_MASK);
@@ -227,7 +225,7 @@ rte_ring_init(struct rte_ring *r, const char *name, unsigned
 int count,
 		r->mask = r->size - 1;
 		r->capacity = count;
 	} else {
-		if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK)) {
+		if ((!RTE_IS_POWER_OF_2(count)) || (count > RTE_RING_SZ_MASK))
 {
 			RING_LOG(ERR,
Quoted 4 lines

"Requested size is invalid, must be power of 2, and
not exceed the size limit %u",
RTE_RING_SZ_MASK);
--

Quoted 1 line

2.49.0