diff options
| author | Timothy Arceri <tarceri@itsqueeze.com> | 2025-07-29 10:24:04 +1000 |
|---|---|---|
| committer | Marge Bot <marge-bot@fdo.invalid> | 2025-07-29 23:07:12 +0000 |
| commit | 6a217a06d9e08f79b6f71ab1cb3f1b432374fe01 (patch) | |
| tree | a29081dd51a2478b7271bac4a92c80d8e1c34669 /src/util/bitset.h | |
| parent | 3a9157a10b827e07ac728e320640babe8b81bdfe (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.h | 44 |
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; } } |