| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -287,6 +287,22 @@ def test_index(self): | |||
| 287 | 287 | else: | |
| 288 | 288 | self.assertEqual(d.index(element, start, stop), target) | |
| 289 | 289 | ||
| 290 | + # Test stop argument | ||
| 291 | + for elem in d: | ||
| 292 | + index = d.index(elem) | ||
| 293 | + self.assertEqual( | ||
| 294 | + index, | ||
| 295 | + d.index(elem, 0), | ||
| 296 | + ) | ||
| 297 | + self.assertEqual( | ||
| 298 | + index, | ||
| 299 | + d.index(elem, 0, len(d)), | ||
| 300 | + ) | ||
| 301 | + self.assertEqual( | ||
| 302 | + index, | ||
| 303 | + d.index(elem, 0, len(d) + 100), | ||
| 304 | + ) | ||
| 305 | + | ||
| 290 | 306 | # Test large start argument | |
| 291 | 307 | d = deque(range(0, 10000, 10)) | |
| 292 | 308 | for step in range(100): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,30 @@ def copy_loop(): | |||
| 24 | 24 | ||
| 25 | 25 | threading_helper.run_concurrently([mutate, copy_loop]) | |
| 26 | 26 | ||
| 27 | + def test_index_race_in_ac(self): | ||
| 28 | + # gh-150750: There was a c_default specified as `Py_SIZE(self)`, | ||
| 29 | + # it was used without a critical section. | ||
| 30 | + | ||
| 31 | + d = deque(range(100)) | ||
| 32 | + | ||
| 33 | + def index(): | ||
| 34 | + for _ in range(10000): | ||
| 35 | + try: | ||
| 36 | + d.index(50) | ||
| 37 | + except ValueError: | ||
| 38 | + pass | ||
| 39 | + | ||
| 40 | + def mutate(): | ||
| 41 | + for _ in range(10000): | ||
| 42 | + d.append(0) | ||
| 43 | + d.clear() | ||
| 44 | + d.extend(range(100)) | ||
| 45 | + d.appendleft(-1) | ||
| 46 | + | ||
| 47 | + threading_helper.run_concurrently( | ||
| 48 | + [index, *[mutate for _ in range(3)]], | ||
| 49 | + ) | ||
| 50 | + | ||
| 27 | 51 | ||
| 28 | 52 | if __name__ == "__main__": | |
| 29 | 53 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Fix a race condition in :meth:`collections.deque.index` with free-threading. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1251,7 +1251,7 @@ _collections.deque.index as deque_index | |||
| 1251 | 1251 | deque: dequeobject | |
| 1252 | 1252 | value as v: object | |
| 1253 | 1253 | start: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='0') = NULL | |
| 1254 | - stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='Py_SIZE(deque)') = NULL | ||
| 1254 | + stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='PY_SSIZE_T_MAX') = NULL | ||
| 1255 | 1255 | / | |
| 1256 | 1256 | ||
| 1257 | 1257 | Return first index of value. | |
@@ -1262,30 +1262,31 @@ Raises ValueError if the value is not present. | |||
| 1262 | 1262 | static PyObject * | |
| 1263 | 1263 | deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, | |
| 1264 | 1264 | Py_ssize_t stop) | |
| 1265 | - /*[clinic end generated code: output=df45132753175ef9 input=90f48833a91e1743]*/ | ||
| 1265 | + /*[clinic end generated code: output=df45132753175ef9 input=1c3b19632cf3484f]*/ | ||
| 1266 | 1266 | { | |
| 1267 | 1267 | Py_ssize_t i, n; | |
| 1268 | 1268 | PyObject *item; | |
| 1269 | 1269 | block *b = deque->leftblock; | |
| 1270 | 1270 | Py_ssize_t index = deque->leftindex; | |
| 1271 | 1271 | size_t start_state = deque->state; | |
| 1272 | 1272 | int cmp; | |
| 1273 | + Py_ssize_t size = Py_SIZE(deque); | ||
| 1273 | 1274 | ||
| 1274 | 1275 | if (start < 0) { | |
| 1275 | - start += Py_SIZE(deque); | ||
| 1276 | + start += size; | ||
| 1276 | 1277 | if (start < 0) | |
| 1277 | 1278 | start = 0; | |
| 1278 | 1279 | } | |
| 1279 | 1280 | if (stop < 0) { | |
| 1280 | - stop += Py_SIZE(deque); | ||
| 1281 | + stop += size; | ||
| 1281 | 1282 | if (stop < 0) | |
| 1282 | 1283 | stop = 0; | |
| 1283 | 1284 | } | |
| 1284 | - if (stop > Py_SIZE(deque)) | ||
| 1285 | - stop = Py_SIZE(deque); | ||
| 1285 | + if (stop > size) | ||
| 1286 | + stop = size; | ||
| 1286 | 1287 | if (start > stop) | |
| 1287 | 1288 | start = stop; | |
| 1288 | - assert(0 <= start && start <= stop && stop <= Py_SIZE(deque)); | ||
| 1289 | + assert(0 <= start && start <= stop && stop <= size); | ||
| 1289 | 1290 | ||
| 1290 | 1291 | for (i=0 ; i < start - BLOCKLEN ; i += BLOCKLEN) { | |
| 1291 | 1292 | b = b->rightlink; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3123,7 +3123,7 @@ class path_t_converter(CConverter): | |||
| 3123 | 3123 | impl_by_reference = True | |
| 3124 | 3124 | parse_by_reference = True | |
| 3125 | 3125 | default_type = () | |
| 3126 | - c_init_default = "<placeholder>" # overridden in pre_render(() | ||
| 3126 | + c_init_default = "<placeholder>" # overridden in pre_render() | ||
| 3127 | 3127 | ||
| 3128 | 3128 | converter = 'path_converter' | |
| 3129 | 3129 | ||
@@ -3266,7 +3266,7 @@ class confname_converter(CConverter): | |||
| 3266 | 3266 | """, argname=argname, converter=self.converter, table=self.table) | |
| 3267 | 3267 | ||
| 3268 | 3268 | [python start generated code]*/ | |
| 3269 | - /*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/ | ||
| 3269 | + /*[python end generated code: output=da39a3ee5e6b4b0d input=ddbf3ac90a981122]*/ | ||
| 3270 | 3270 | ||
| 3271 | 3271 | /*[clinic input] | |
| 3272 | 3272 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments