GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-143050: correct PyLong_FromString() to use _PyLong_Negate() by skirpichev · Pull Request #145901 · python/cpython

Conversation

@skirpichev

@skirpichev skirpichev commented Mar 13, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

The long_from_string_base() might return a small integer, when the _pylong.py is used to do conversion. Hence, we must be careful here to not smash it "small int" bit by using the _PyLong_FlipSign().

Co-authored-by: Sam Gross [email protected]

  • Issue: Remove redundant decref from _PyLong_Negate #143050

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@skirpichev
pythongh-143050: correct PyLong_FromString() to use _PyLong_Negate()
fbcec5a
The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().
@skirpichev
skirpichev requested a review from a team as a code owner March 13, 2026 07:53
@skirpichev skirpichev added the skip news label Mar 13, 2026
@skirpichev
skirpichev requested review from AA-Turner, emmatyping and erlend-aasland as code owners March 13, 2026 07:53
@bedevere-app bedevere-app Bot added the awaiting review label Mar 13, 2026
@bedevere-app bedevere-app Bot mentioned this pull request Mar 13, 2026
Remove redundant decref from _PyLong_Negate #143050
Closed
@skirpichev

skirpichev commented Mar 13, 2026

Copy link
Copy Markdown
Member Author

Shouldn't affect users, so - no news.

CC @colesbury, @eendebakpt

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@skirpichev
cleanup, use _testcapi.test_immortal_small_ints()
b8333ba
@skirpichev

skirpichev commented Mar 13, 2026

Copy link
Copy Markdown
Member Author

_long_is_small_int() logic used also in Modules/_testcapi/immortal.c. What about moving this inlined function to the Include/internal/pycore_long.h as _PyLong_IsImmortal()?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

skirpichev
skirpichev commented Mar 13, 2026
View reviewed changes
Comment thread Lib/test/test_capi/test_long.py
with support.adjust_int_max_str_digits(0):
a = int('-' + '0' * 7000, 10)
del a
_testcapi.test_immortal_small_ints()

@skirpichev skirpichev Mar 13, 2026

Copy link
Copy Markdown
Member Author

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?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@colesbury colesbury Mar 17, 2026

Copy link
Copy Markdown
Contributor

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.

That's okay as long as it catches the regression in a debug build.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Mar 31, 2026

Copy link
Copy Markdown
Member

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.

_testcapi is always built with assertions, even in release mode.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Mar 31, 2026

Copy link
Copy Markdown
Member

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 built Python in release mode without PyLong_FromString() fix. _PyLong_FlipSign() assertion didn't catch the bug since Python was built without assertions. But at least, test_immortal_small_ints() was able to detect that small integers were corrupted:

test_bug_143050 (test.test_capi.test_long.LongTests.test_bug_143050) ...
python: ./Modules/_testcapi/immortal.c:35: test_immortal_small_ints: Assertion `has_int_immortal_bit' failed.
Fatal Python error: Aborted

Current thread 0x00007f617b91b780 [python] (most recent call first):
  File "/home/vstinner/python/main/Lib/test/test_capi/test_long.py", line 811 in test_bug_143050

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
eendebakpt
eendebakpt reviewed Mar 13, 2026
View reviewed changes
Comment thread Objects/longobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt
eendebakpt reviewed Mar 13, 2026
View reviewed changes
Comment thread Lib/test/test_capi/test_long.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

skirpichev added 2 commits March 14, 2026 03:02
@skirpichev
+ add also test with nonzero small int
20e79c6
@skirpichev
_long_is_small_int() -> _PyLong_IsImmortal() helper
413e56d
@skirpichev
skirpichev requested review from colesbury and eendebakpt March 15, 2026 04:13
eendebakpt
eendebakpt approved these changes Mar 17, 2026
View reviewed changes

@eendebakpt eendebakpt left a comment

Copy link
Copy Markdown
Contributor

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.

Minor comment on the naming. But the PR fixes a bug, adds a test and cleans up along the way, so good enough for me!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Include/internal/pycore_long.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot added awaiting core review and removed awaiting review labels Mar 17, 2026
colesbury
colesbury reviewed Mar 17, 2026
View reviewed changes

@colesbury colesbury left a comment

Copy link
Copy Markdown
Contributor

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.

Looks good to me. Small comment about the function name below.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/test_capi/test_long.py
with support.adjust_int_max_str_digits(0):
a = int('-' + '0' * 7000, 10)
del a
_testcapi.test_immortal_small_ints()

@colesbury colesbury Mar 17, 2026

Copy link
Copy Markdown
Contributor

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.

That's okay as long as it catches the regression in a debug build.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Include/internal/pycore_long.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

colesbury
colesbury approved these changes Mar 17, 2026
View reviewed changes

@colesbury colesbury left a comment

Copy link
Copy Markdown
Contributor

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.

Let me know if you change the function name or keep it as is.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Mar 17, 2026
skirpichev added 2 commits March 18, 2026 02:12
@skirpichev
Merge branch 'master' into fix-PyLong_FromString/143050
b892216
@skirpichev
address review: rename _PyLong_IsImmortal -> _PyLong_HasImmortalTag
78c5b4b
@skirpichev
skirpichev force-pushed the fix-PyLong_FromString/143050 branch from e28e94c to 78c5b4b Compare March 17, 2026 23:27
@skirpichev

skirpichev commented Mar 17, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

@colesbury, I did renaming.

I've tried also to add an assert(_Py_IsImmortal(op)), but this fails build like check in the _PyLong_SetSignAndDigitCount (see #145901 (comment)):

make: *** [Makefile:1957: Python/frozen_modules/importlib._bootstrap.h] Error 134
./Programs/_freeze_module importlib._bootstrap_external ../cpython-ro-srcdir/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h
_freeze_module: ../cpython-ro-srcdir/Include/internal/pycore_long.h:238: _PyLong_IsImmortal: Assertion `_Py_IsImmortal(op)' failed.
Aborted (core dumped)
make: *** [Makefile:1960: Python/frozen_modules/importlib._bootstrap_external.h] Error 134
Error: Process completed with exit code 2.

I believe it's a bug, but lets fix this separately.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@skirpichev
add assert
69d35bd
vstinner
vstinner reviewed Mar 27, 2026
View reviewed changes
Comment thread Lib/test/test_capi/test_long.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_capi/test_long.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Include/internal/pycore_long.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

skirpichev added 2 commits March 28, 2026 02:56
@skirpichev
Merge branch 'master' into fix-PyLong_FromString/143050
53523de
@skirpichev
address review: some comments
1f363f4
@skirpichev
skirpichev requested a review from vstinner March 28, 2026 00:11
vstinner
vstinner reviewed Mar 30, 2026
View reviewed changes
Comment thread Include/internal/pycore_long.h Outdated

/* Return true if the argument is a small int */
static inline bool
_PyLong_HasImmortalTag(const PyLongObject *op)

@vstinner vstinner Mar 30, 2026

Copy link
Copy Markdown
Member

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.

IMO the intent here is to check if an integer is a small integer, rather than checking for a tag. So I would prefer to rename the function to _PyLong_IsSmallInt().

I wanted to suggest referring to _PY_IS_SMALL_INT() but I noticed the macro is wrong. I wrote #146631 to fix the macro.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@skirpichev skirpichev Mar 30, 2026

Copy link
Copy Markdown
Member Author

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.

There are two notions for "small int"'s. One - by value and other is - this. If @colesbury is ok - I'm fine with renaming..

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Mar 30, 2026

Copy link
Copy Markdown
Member

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.

_PyLong_HasImmortalTag() and _PY_IS_SMALL_INT() should be true or false for the same values.

For example, you can add the following check for _PyLong_HasImmortalTag():

+    assert((_PyLong_IsCompact(op) && _PY_IS_SMALL_INT(_PyLong_CompactValue(op)))
+           || (!is_small_int));

(You need to update your branch to retrieve my _PY_IS_SMALL_INT() change.)

For me, testing IMMORTALITY_BIT_MASK is just an implementation detail to check if an integer is "a small int".

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

skirpichev reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@skirpichev skirpichev Mar 31, 2026

Copy link
Copy Markdown
Member Author

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've added an assert. BTW, what do you think on #145901 (comment)?

I don't think we should mention _PY_IS_SMALL_INT in the description of the function, assert is readable enough.

For me, testing IMMORTALITY_BIT_MASK is just an implementation detail to check if an integer is "a small int".

For now, we use _PY_IS_SMALL_INT() to check this. But eventually this could be just testing a flag.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Mar 31, 2026

Copy link
Copy Markdown
Member

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 would prefer to rename the function to _PyLong_IsSmallInt().

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@skirpichev skirpichev Mar 31, 2026

Copy link
Copy Markdown
Member Author

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've added suggestions.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
skirpichev added 2 commits March 31, 2026 02:41
@skirpichev
Merge branch 'main' into fix-PyLong_FromString/143050
41961ed
@skirpichev
address review: add assert on _PY_IS_SMALL_INT
0b29e28
@skirpichev
skirpichev requested a review from vstinner March 31, 2026 00:22
skirpichev
skirpichev commented Mar 31, 2026
View reviewed changes
Comment thread Include/internal/pycore_long.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Include/internal/pycore_long.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Modules/_testcapi/immortal.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Modules/_testcapi/immortal.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/longobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Modules/_testcapi/immortal.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/longobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@vstinner @skirpichev
Rename to _PyLong_IsSmallInt()
45b3b04
Co-authored-by: Sergey B Kirpichev <[email protected]>
vstinner
vstinner approved these changes Mar 31, 2026
View reviewed changes

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

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.

LGTM

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@vstinner

vstinner commented Mar 31, 2026

Copy link
Copy Markdown
Member

test_opcache crashed on "Tests / Sanitizers / TSan (free-threading)" CI:

0:13:12 load avg: 4.44 [61/77/1] test_opcache worker non-zero exit code (Exit code -11 (SIGSEGV)) -- running (1): test_io.test_textio (34.1 sec)
Fatal Python error: Segmentation fault

<Cannot show all threads while the GIL is disabled>
Stack (most recent call first):
  File "/home/runner/work/cpython/cpython/Lib/test/test_opcache.py", line 1019 in read
  File "/home/runner/work/cpython/cpython/Lib/test/test_opcache.py", line 659 in assert_races_do_not_crash
  File "/home/runner/work/cpython/cpython/Lib/test/test_opcache.py", line 1032 in test_load_attr_property

It looks unrelated to this change. I just re-ran the CI.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Mar 31, 2026

Copy link
Copy Markdown
Member

To backport this change to 3.14, _PY_IS_SMALL_INT() macro should be fixed first. So I prepared #147187 for that.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner enabled auto-merge (squash) March 31, 2026 12:59
@skirpichev

skirpichev commented Mar 31, 2026

Copy link
Copy Markdown
Member Author

Why we need a backport?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Mar 31, 2026

Copy link
Copy Markdown
Member

Why we need a backport?

This change uses _PY_IS_SMALL_INT(). I prefer to backport the change as it is, so _PY_IS_SMALL_INT() has to be fixed in 3.14.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner merged commit db5936c into python:main Mar 31, 2026
92 of 94 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label Mar 31, 2026
@vstinner vstinner added the needs backport to 3.14 bugs and security fixes label Mar 31, 2026
@miss-islington-app

miss-islington-app Bot commented Mar 31, 2026

Copy link
Copy Markdown

Thanks @skirpichev for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app

bedevere-app Bot commented Mar 31, 2026

Copy link
Copy Markdown

GH-147331 is a backport of this pull request to the 3.14 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Mar 31, 2026
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Mar 31, 2026
@skirpichev @vstinner @miss-islington
pythongh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (p…
ced1164
…ythonGH-145901)

The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().
(cherry picked from commit db5936c)

Co-authored-by: Sergey B Kirpichev <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
@bedevere-app

bedevere-app Bot commented Mar 31, 2026

Copy link
Copy Markdown

GH-147437 is a backport of this pull request to the 3.13 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@skirpichev
skirpichev deleted the fix-PyLong_FromString/143050 branch March 31, 2026 14:06
vstinner added a commit that referenced this pull request Mar 31, 2026
@miss-islington @skirpichev @vstinner
[3.14] gh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (…
25b48b8
…GH-145901) (#147331)

gh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (GH-145901)

The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().
(cherry picked from commit db5936c)

Co-authored-by: Sergey B Kirpichev <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
vstinner added a commit that referenced this pull request Mar 31, 2026
@vstinner @skirpichev
[3.13] gh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (…
01af34a
…#145901) (#147437)

The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().

Co-authored-by: Victor Stinner <[email protected]>
(cherry picked from commit db5936c)

Co-authored-by: Sergey B Kirpichev <[email protected]>
@pablogsal pablogsal mentioned this pull request Apr 4, 2026
gh-130273: Fix traceback color output with unicode characters #142529
Merged
clin1234 pushed a commit to clin1234/cpython that referenced this pull request Apr 16, 2026
@skirpichev @vstinner @clin1234
pythongh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (p…
a7070f3
…ython#145901)

The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().

Co-authored-by: Victor Stinner <[email protected]>
ljfp pushed a commit to ljfp/cpython that referenced this pull request Apr 25, 2026
@skirpichev @vstinner @ljfp
pythongh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (p…
2f7f76e
…ython#145901)

The long_from_string_base() might return a small integer, when the
_pylong.py is used to do conversion.  Hence, we must be careful here to
not smash it "small int" bit by using the _PyLong_FlipSign().

Co-authored-by: Victor Stinner <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@colesbury colesbury colesbury approved these changes
@eendebakpt eendebakpt eendebakpt approved these changes
@vstinner vstinner vstinner approved these changes
@erlend-aasland erlend-aasland Awaiting requested review from erlend-aasland
@AA-Turner AA-Turner Awaiting requested review from AA-Turner
@emmatyping emmatyping Awaiting requested review from emmatyping

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

skip news

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@skirpichev @vstinner @colesbury @eendebakpt
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.