-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
gh-143050: correct PyLong_FromString() to use _PyLong_Negate() #145901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
fbcec5a
b8333ba
20e79c6
413e56d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3118,11 +3118,11 @@ PyLong_FromString(const char *str, char **pend, int base) | |
| } | ||
|
|
||
| /* Set sign and normalize */ | ||
| if (sign < 0) { | ||
| _PyLong_FlipSign(z); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling The In a similar way we could add an assert to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, but any small int will trigger this. We can add test case for
My suggestion would be using
This will affect all "setters" in Include/internal/pycore_long.h (i.e. also _PyLong_SetDigitCount).
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added
I tried to add assert here and in |
||
| } | ||
| long_normalize(z); | ||
| z = maybe_small_long(z); | ||
| if (sign < 0) { | ||
| _PyLong_Negate(&z); | ||
| } | ||
|
|
||
| if (pend != NULL) { | ||
| *pend = (char *)str; | ||
|
|
@@ -3622,21 +3622,11 @@ long_richcompare(PyObject *self, PyObject *other, int op) | |
| Py_RETURN_RICHCOMPARE(result, 0, op); | ||
| } | ||
|
|
||
| static inline int | ||
| /// Return 1 if the object is one of the immortal small ints | ||
| _long_is_small_int(PyObject *op) | ||
| { | ||
| PyLongObject *long_object = (PyLongObject *)op; | ||
| int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; | ||
| assert((!is_small_int) || PyLong_CheckExact(op)); | ||
| return is_small_int; | ||
| } | ||
|
|
||
| void | ||
| _PyLong_ExactDealloc(PyObject *self) | ||
| { | ||
| assert(PyLong_CheckExact(self)); | ||
| if (_long_is_small_int(self)) { | ||
| if (_PyLong_IsImmortal((PyLongObject *)self)) { | ||
| // See PEP 683, section Accidental De-Immortalizing for details | ||
| _Py_SetImmortal(self); | ||
| return; | ||
|
|
@@ -3651,7 +3641,7 @@ _PyLong_ExactDealloc(PyObject *self) | |
| static void | ||
| long_dealloc(PyObject *self) | ||
| { | ||
| if (_long_is_small_int(self)) { | ||
| if (_PyLong_IsImmortal((PyLongObject *)self)) { | ||
| /* This should never get called, but we also don't want to SEGV if | ||
| * we accidentally decref small Ints out of existence. Instead, | ||
| * since small Ints are immortal, re-set the reference count. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm slightly worry that this pass will non-debug builds.
@corona10 (author of #103962), are you sure there is no other way to implement this helper? Return a different value, raise an error?