Title: PEP 670: Convert _PyObject_SIZE() and _PyObject_VAR_SIZE() macros to functions · Issue #99845 · python/cpython · GitHub
Open Graph Title: PEP 670: Convert _PyObject_SIZE() and _PyObject_VAR_SIZE() macros to functions · Issue #99845 · python/cpython
X Title: PEP 670: Convert _PyObject_SIZE() and _PyObject_VAR_SIZE() macros to functions · Issue #99845 · python/cpython
Description: The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see PEP 670 for the rationale. My problem is that I don't know if the return type should be signed (Py_ssize_t) or unsigned (size_t). CPython usage of...
Open Graph Description: The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see PEP 670 for the rationale. My problem is that I don't know if the return type should be signed (Py_ssize_t...
X Description: The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see PEP 670 for the rationale. My problem is that I don't know if the return type should be signed (Py_ssi...
Opengraph URL: https://github.com/python/cpython/issues/99845
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"PEP 670: Convert _PyObject_SIZE() and _PyObject_VAR_SIZE() macros to functions","articleBody":"The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see [PEP 670](https://peps.python.org/pep-0670/) for the rationale.\r\n\r\nMy problem is that I don't know if the return type should be signed (Py_ssize_t) or unsigned (size_t).\r\n\r\nCPython usage of _PyObject_SIZE():\r\n\r\n* Signed: 18. Implementation of ``__sizeof__()`` methods.\r\n* Unsigned: 0\r\n* Implicit cast to unsigned: 2. Calls ``PyObject_Malloc(_PyObject_SIZE(tp))`` and ``gc_alloc(_PyObject_SIZE(tp), presize)`` where the first argument type is ``size_t``.\r\n\r\nCPython usage of _PyObject_VAR_SIZE():\r\n\r\n* Signed: 5\r\n* Unsigned: 1\r\n* Implicit cast to unsigned: 1. Call ``_PyDebugAllocatorStats(..., _PyObject_VAR_SIZE(\u0026PyTuple_Type, len))`` where the argument type is ``size_t``.\r\n\r\nTo get a **container length**, the C API uses signed type (``Py_ssize_t``): PyList_Size(), PyDict_Size(), Py_SIZE(), etc.\r\n\r\nTo **allocate memory**, the C API prefers unsigned type (``size_t``): PyMem_Malloc(), PyObject_Realloc(), etc.\r\n\r\nPython allocator functions reject size greater than ``PY_SSIZE_T_MAX``:\r\n\r\n```\r\nvoid *\r\nPyMem_RawMalloc(size_t size)\r\n{\r\n /*\r\n * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.\r\n * Most python internals blindly use a signed Py_ssize_t to track\r\n * things without checking for overflows or negatives.\r\n * As size_t is unsigned, checking for size \u003c 0 is not required.\r\n */\r\n if (size \u003e (size_t)PY_SSIZE_T_MAX)\r\n return NULL;\r\n return _PyMem_Raw.malloc(_PyMem_Raw.ctx, size);\r\n}\r\n```\r\n\r\nSome \"sizeof\" functions freely mix signed and unsigned types. Example:\r\n\r\n```\r\nstatic PyObject *\r\ndeque_sizeof(dequeobject *deque, void *unused)\r\n{\r\n Py_ssize_t res;\r\n Py_ssize_t blocks;\r\n\r\n res = _PyObject_SIZE(Py_TYPE(deque));\r\n blocks = (size_t)(deque-\u003eleftindex + Py_SIZE(deque) + BLOCKLEN - 1) / BLOCKLEN;\r\n assert(deque-\u003eleftindex + Py_SIZE(deque) - 1 ==\r\n (blocks - 1) * BLOCKLEN + deque-\u003erightindex);\r\n res += blocks * sizeof(block);\r\n return PyLong_FromSsize_t(res);\r\n}\r\n```\r\n\r\n``blocks`` and ``sizeof(block)`` are unsigned, but ``res`` is signed.\r\n\r\n---\r\n\r\nAnother problem is that _PyObject_VAR_SIZE() has an undefined behavior on integer overflow. Maybe it should return ``SIZE_MAX`` on oveflow, to make sure that Python allocator function fail (return ``NULL``)?\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-99846\n* gh-99847\n* gh-99848\n* gh-99850\n* gh-99903\n* gh-99922\n* gh-99924\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/vstinner","@type":"Person","name":"vstinner"},"datePublished":"2022-11-28T16:00:17.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/99845/cpython/issues/99845"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:76c2eb68-ac5e-b050-6104-a5dcf35c4131 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | AFF2:D1023:F539E4:14A7C12:69699209 |
| html-safe-nonce | 60f73c7a6ad5ef57e0af3f965a1c6fde12d48f84c1e02b5a55b110df4475849c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBRkYyOkQxMDIzOkY1MzlFNDoxNEE3QzEyOjY5Njk5MjA5IiwidmlzaXRvcl9pZCI6IjIyNzYwMDI3ODgxMjcyNTc2OSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 18285025323ff8a80efb4f6d734a2c694bd96a06494207ec35d42c48c218bd87 |
| hovercard-subject-tag | issue:1466671640 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/99845/issue_layout |
| twitter:image | https://opengraph.githubassets.com/5798816d80f812ef1616afab80cf42215cc4440a2d917fa18b2a3ea381f9c263/python/cpython/issues/99845 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/5798816d80f812ef1616afab80cf42215cc4440a2d917fa18b2a3ea381f9c263/python/cpython/issues/99845 |
| og:image:alt | The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see PEP 670 for the rationale. My problem is that I don't know if the return type should be signed (Py_ssize_t... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | vstinner |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3542e147982176a7ebaa23dfb559c8af16f721c03ec560c68c56b64a0f35e751 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | af80af7cc9e3de9c336f18b208a600950a3c187c |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width