Uh oh!
There was an error while loading. Please reload this page.
gh-143050: add helper _PyLong_InitTag() - #147956
Conversation
With this we can assume, that _PyLong_Set*() operate on non-immortal integers.
Uh oh!
There was an error while loading. Please reload this page.
| _PyLong_SetSignAndDigitCount(result, size != 0, size); | ||
| /* The digit has to be initialized explicitly to avoid | ||
| * use-of-uninitialized-value. */ | ||
| result->long_value.ob_digit[0] = 0; |
There was a problem hiding this comment.
While I'm not convinced that this initialization is useful, the comment says that it is. We should keep it, no?
There was a problem hiding this comment.
I suggested to keep this initialization. You marked my comment as resolved, I don't understand. Do you consider that it's not needed?
An alternative would be to fill digits with a pattern to detect usage of non-initialized memory when Python is built in debug mode:
#ifdefPy_DEBUG// Fill digits with a known pattern to detect usage of uninitialized memorymemset(result->long_value.ob_digit, 0xff,
sizeof(result->long_value.ob_digit[0]) *ndigits);
#endifWe use this strategy for:
str: seeunicode_fill_invalid()function.PyBytesWriter:memset(byteswriter_data(writer), 0xff, byteswriter_allocated(writer))inPyBytesWriter_Create()
There was a problem hiding this comment.
Do you suggest to keep this just here? BTW, tests pass - I rerun one job again.
There was a problem hiding this comment.
ob_digit[0] = 0; was added by commit fc130c4 of issue gh-102509 to fix the OSS Fuzz report https://issues.oss-fuzz.com/issues/42516166.
Looks like it's complaining about a use of unit values in _PyLong_FromByteArray
Allocation happens here as part of _PyLong_NewLine 911 in 41bc101
and the claimed use is atLine 957 in 41bc101
inside of maybe_small_long and IS_SMALL_INT
I understand that the maybe_small_long() at the end of _PyLong_FromByteArray() triggered the issue when Python was built with --with-memory-sanitizer (-fsanitize=memory). From what I understood, the sign was initialized (to zero) but not ob_digit[0].
Oh interesting, k_mul() already does what I proposed above:
#ifdefPy_DEBUG/* Fill with trash, to catch reference to uninitialized digits. */memset(ret->long_value.ob_digit, 0xDF, _PyLong_DigitCount(ret) *sizeof(digit));
#endifk_lopsided_mul() sets explicitly all digits to zero:
memset(ret->long_value.ob_digit, 0, _PyLong_DigitCount(ret) *sizeof(digit));vstinner
commented
Apr 1, 2026
"Tests / Android (x86_64)" failed with: |
skirpichev
commented
Apr 1, 2026
via email
This yes, but linked above fuzzer failure is relevant. …On Wed, Apr 1, 2026, 15:10 Victor Stinner ***@***.***> wrote:
*vstinner* left a comment (python/cpython#147956)
<#147956?email_source=notifications&email_token=AAQOKGA5T2QHBNZ3SVWPVWT4TUBM7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMJWHE3DGNZXGIZKM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2LK4DSL5RW63LNMVXHIX3POBSW4X3DNRUWG2Y#issuecomment-4169637722>
"Tests / Android (x86_64)" failed with: Error on ZipFile unknown archive.
It's unrelated to this change.
> Task :app:maxVersionSetup
"Install Android Emulator v.36.4.10" ready.
Installing Android Emulator in /usr/local/lib/android/sdk/emulator
"Install Android Emulator v.36.4.10" complete.
"Install Android Emulator v.36.4.10" finished.
Checking the license for package AOSP ATD Intel x86_64 Atom System Image in /usr/local/lib/android/sdk/licenses
License for package AOSP ATD Intel x86_64 Atom System Image accepted.
Preparing "Install AOSP ATD Intel x86_64 Atom System Image API 32 (revision 1)".
Warning: An error occurred while preparing SDK package AOSP ATD Intel x86_64 Atom System Image: Error on ZipFile unknown archive.:
java.io.IOException: Error on ZipFile unknown archive
at org.apache.commons.compress.archivers.zip.ZipFile.<init>(ZipFile.java:383)
at org.apache.commons.compress.archivers.zip.ZipFile.<init>(ZipFile.java:323)
at org.apache.commons.compress.archivers.zip.ZipFile.<init>(ZipFile.java:279)
at com.android.repository.util.InstallerUtil.unzip(InstallerUtil.java:101)
at com.android.repository.impl.installer.BasicInstaller.doPrepare(BasicInstaller.java:91)
—
Reply to this email directly, view it on GitHub
<#147956?email_source=notifications&email_token=AAQOKGA5T2QHBNZ3SVWPVWT4TUBM7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMJWHE3DGNZXGIZKM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2LK4DSL5RW63LNMVXHIX3POBSW4X3DNRUWG2Y#issuecomment-4169637722>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAQOKGB4LCCKKOKT66AWXQD4TUBM7AVCNFSM6AAAAACXIS7L4WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DCNRZGYZTONZSGI>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
vstinner
commented
Apr 1, 2026
"Tests / CIFuzz / cpython3 (memory)" CI logs an pycore_long.h:243 is the following assertion in assert((_PyLong_IsCompact(op)
&&_PY_IS_SMALL_INT(_PyLong_CompactValue(op)))
|| (!is_small_int));Oh right, |
vstinner
left a comment
There was a problem hiding this comment.
What do you think of changing _PyLong_IsSmallInt() implementation like that?
staticinlinebool_PyLong_IsSmallInt(constPyLongObject*op)
{
assert(PyLong_Check(op));
boolis_small_int= (op->long_value.lv_tag&IMMORTALITY_BIT_MASK) !=0;
if (is_small_int) {
assert(PyLong_CheckExact(op));
assert(_Py_IsImmortal(op));
assert((_PyLong_IsCompact(op)
&&_PY_IS_SMALL_INT(_PyLong_CompactValue(op))));
}
returnis_small_int;
}The current code runs many checks when is_small_int is false which are not needed.
skirpichev
commented
Apr 1, 2026
Lets try, but I suspect it might fall in other place. |
Uh oh!
There was an error while loading. Please reload this page.
| _PyLong_SetSignAndDigitCount(result, size != 0, size); | ||
| /* The digit has to be initialized explicitly to avoid | ||
| * use-of-uninitialized-value. */ | ||
| result->long_value.ob_digit[0] = 0; |
There was a problem hiding this comment.
I suggested to keep this initialization. You marked my comment as resolved, I don't understand. Do you consider that it's not needed?
An alternative would be to fill digits with a pattern to detect usage of non-initialized memory when Python is built in debug mode:
#ifdefPy_DEBUG// Fill digits with a known pattern to detect usage of uninitialized memorymemset(result->long_value.ob_digit, 0xff,
sizeof(result->long_value.ob_digit[0]) *ndigits);
#endifWe use this strategy for:
str: seeunicode_fill_invalid()function.PyBytesWriter:memset(byteswriter_data(writer), 0xff, byteswriter_allocated(writer))inPyBytesWriter_Create()
vstinner
commented
Apr 1, 2026
Ok, I managed to reproduce the MSAN ( Apply the patch: diff --git a/Objects/longobject.c b/Objects/longobject.c
index b74a435b541..d46dbf0bd82 100644
--- a/Objects/longobject.c+++ b/Objects/longobject.c@@ -170,7 +170,7 @@ long_alloc(Py_ssize_t size)
Py_ssize_t ndigits = size ? size : 1;
if (ndigits == 1) {
- result = (PyLongObject *)_Py_FREELIST_POP(PyLongObject, ints);+ //result = (PyLongObject *)_Py_FREELIST_POP(PyLongObject, ints);
}
if (result == NULL) {
/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +Build Python with: Then run: |
vstinner
commented
Apr 1, 2026
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
vstinner
commented
Apr 1, 2026
It's a good thing that these two functions now fail in debug mode if they are called on a small integer. It will catch bugs earlier. So I merged the change. Thanks for this enhancement. |
With this we can assume, that _PyLong_SetSignAndDigitCount() and _PyLong_SetDigitCount() operate on non-immortal integers. Co-authored-by: Victor Stinner <vstinner@python.org>
With this we can assume, that _PyLong_SetSignAndDigitCount() and _PyLong_SetDigitCount() operate on non-immortal integers. Co-authored-by: Victor Stinner <vstinner@python.org>
With this we can assume, that _PyLong_Set*() operate on non-immortal integers.