8000 gh-99248: [Enum] fix negative number infinite loop (GH-99256) · python/cpython@0b4ffb0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0b4ffb0

Browse files
authored
gh-99248: [Enum] fix negative number infinite loop (GH-99256)
[Enum] fix negative number infinite loop - _iter_bits_lsb() now raises a ValueError if a negative number is passed in - verify() now skips checking negative numbers for named flags
1 parent 52f91c6 commit 0b4ffb0

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

Lib/enum.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,12 @@ def _break_on_call_reduce(self, proto):
114114
setattr(obj, '__module__', '<unknown>')
115115

116116
def _iter_bits_lsb(num):
117-
# num must be an integer
117+
# num must be a positive integer
118+
original = num
118119
if isinstance(num, Enum):
119120
num = num.value
121+
if num < 0:
122+
raise ValueError('%r is not a positive integer' % original)
120123
while num:
121124
b = num & (~num + 1)
122125
yield b
@@ -1839,6 +1842,9 @@ def __call__(self, enumeration):
18391842
if name in member_names:
18401843
# not an alias
18411844
continue
1845+
if alias.value < 0:
1846+
# negative numbers are not checked
1847+
continue
18421848
values = list(_iter_bits_lsb(alias.value))
18431849
missed = [v for v in values if v not in member_values]
18441850
if missed:

Lib/test/test_enum.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from enum import Enum, IntEnum, StrEnum, EnumType, Flag, IntFlag, unique, auto
1515
from enum import STRICT, CONFORM, EJECT, KEEP, _simple_enum, _test_simple_enum
1616
from enum import verify, UNIQUE, CONTINUOUS, NAMED_FLAGS, ReprEnum
17-
from enum import member, nonmember
17+
from enum import member, nonmember, _iter_bits_lsb
1818
from io import StringIO
1919
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
2020
from test import support
@@ -174,6 +174,10 @@ def test_is_private(self):
174174
for name in self.sunder_names + self.dunder_names + self.random_names:
175175
self.assertFalse(enum._is_private('MyEnum', name), '%r is a private name?')
176176

177+
def test_iter_bits_lsb(self):
178+
self.assertEqual(list(_iter_bits_lsb(7)), [1, 2, 4])
179+
self.assertRaisesRegex(ValueError, '-8 is not a positive integer', list, _iter_bits_lsb(-8))
180+
177181

178182
# for subclassing tests
179183

@@ -3960,6 +3964,16 @@ class Sillier(IntEnum):
39603964
triple = 3
39613965
value = 4
39623966

3967+
def test_negative_alias(self):
3968+
@verify(NAMED_FLAGS)
3969+
class Color(Flag):
3970+
RED = 1
3971+
GREEN = 2
3972+
BLUE = 4
3973+
WHITE = -1
3974+
# no error means success
3975+
3976+
39633977
class TestInternals(unittest.TestCase):
39643978

39653979
sunder_names = '_bad_', '_good_', '_what_ho_'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix negative numbers failing in verify()

0 commit comments

Comments
 (0)
0