About Social Code
aboutsummaryrefslogtreecommitdiff
path: root/src/util/bitset.h
diff options
context:
space:
mode:
authorTimothy Arceri <tarceri@itsqueeze.com>2025-07-29 10:24:04 +1000
committerMarge Bot <marge-bot@fdo.invalid>2025-07-29 23:07:12 +0000
commit6a217a06d9e08f79b6f71ab1cb3f1b432374fe01 (patch)
treea29081dd51a2478b7271bac4a92c80d8e1c34669 /src/util/bitset.h
parent3a9157a10b827e07ac728e320640babe8b81bdfe (diff)
util: remove recursion from bitset helpers
Recursion can cause a stack overflow when the range is very large. Fixes: cb558b2b88c2 ("glsl: add mark_array_elements_referenced() fast path") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13617 Reviewed-by: Gert Wollny <gert.wollny@collabora.com> Reviewed-by: Caio Oliveira <caio.oliveira@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36430>
Diffstat (limited to 'src/util/bitset.h')
-rw-r--r--src/util/bitset.h44
1 files changed, 18 insertions, 26 deletions
diff --git a/src/util/bitset.h b/src/util/bitset.h
index cf9e59a01cf..594f8cc56db 100644
--- a/src/util/bitset.h
+++ b/src/util/bitset.h
@@ -226,17 +226,17 @@ __bitset_shl(BITSET_WORD *x, unsigned amount, unsigned n)
static inline bool
__bitset_test_range(const BITSET_WORD *r, unsigned start, unsigned end)
{
- const unsigned size = end - start + 1;
- const unsigned start_mod = start % BITSET_WORDBITS;
+ while (start <= end) {
+ unsigned start_mod = start % BITSET_WORDBITS;
+ unsigned size = MIN2(BITSET_WORDBITS - start_mod, end - start + 1);
- if (start_mod + size <= BITSET_WORDBITS) {
- return !BITSET_TEST_RANGE_INSIDE_WORD(r, start, end, 0);
- } else {
- const unsigned first_size = BITSET_WORDBITS - start_mod;
+ if (!BITSET_TEST_RANGE_INSIDE_WORD(r, start, start + size - 1, 0))
+ return true;
- return __bitset_test_range(r, start, start + first_size - 1) ||
- __bitset_test_range(r, start + first_size, end);
+ start += size;
}
+
+ return false;
}
#define BITSET_TEST_RANGE(x, b, e) \
@@ -245,16 +245,12 @@ __bitset_test_range(const BITSET_WORD *r, unsigned start, unsigned end)
static inline void
__bitset_set_range(BITSET_WORD *r, unsigned start, unsigned end)
{
- const unsigned size = end - start + 1;
- const unsigned start_mod = start % BITSET_WORDBITS;
-
- if (start_mod + size <= BITSET_WORDBITS) {
- BITSET_SET_RANGE_INSIDE_WORD(r, start, end);
- } else {
- const unsigned first_size = BITSET_WORDBITS - start_mod;
+ while (start <= end) {
+ unsigned start_mod = start % BITSET_WORDBITS;
+ unsigned size = MIN2(BITSET_WORDBITS - start_mod, end - start + 1);
- __bitset_set_range(r, start, start + first_size - 1);
- __bitset_set_range(r, start + first_size, end);
+ BITSET_SET_RANGE_INSIDE_WORD(r, start, start + size - 1);
+ start += size;
}
}
@@ -264,16 +260,12 @@ __bitset_set_range(BITSET_WORD *r, unsigned start, unsigned end)
static inline void
__bitclear_clear_range(BITSET_WORD *r, unsigned start, unsigned end)
{
- const unsigned size = end - start + 1;
- const unsigned start_mod = start % BITSET_WORDBITS;
-
- if (start_mod + size <= BITSET_WORDBITS) {
- BITSET_CLEAR_RANGE_INSIDE_WORD(r, start, end);
- } else {
- const unsigned first_size = BITSET_WORDBITS - start_mod;
+ while (start <= end) {
+ unsigned start_mod = start % BITSET_WORDBITS;
+ unsigned size = MIN2(BITSET_WORDBITS - start_mod, end - start + 1);
- __bitclear_clear_range(r, start, start + first_size - 1);
- __bitclear_clear_range(r, start + first_size, end);
+ BITSET_CLEAR_RANGE_INSIDE_WORD(r, start, start + size - 1);
+ start += size;
}
}