Skip to content
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

New warning in the main (-Warray-bounds) #131820

Closed
skirpichev opened this issue Mar 28, 2025 · 8 comments
Closed

New warning in the main (-Warray-bounds) #131820

skirpichev opened this issue Mar 28, 2025 · 8 comments
Labels
build The build process and cross-build interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@skirpichev
Copy link
Member

skirpichev commented Mar 28, 2025

Bug report

Bug description:

$ cc --version
cc (Debian 12.2.0-14) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./configure -q && make -s
In file included from ./Include/internal/pycore_dict.h:11,
                 from Objects/typeobject.c:7:
In function ‘Py_DECREF_MORTAL’,
    inlined from ‘PyStackRef_XCLOSE’ at ./Include/internal/pycore_stackref.h:577:9,
    inlined from ‘_PyThreadState_PopCStackRef’ at ./Include/internal/pycore_stackref.h:662:5,
    inlined from ‘vectorcall_maybe.constprop’ at Objects/typeobject.c:2956:9:
./Include/internal/pycore_object.h:481:8: warning: array subscript 0 is outside array bounds of ‘PyObject[0]’ {aka ‘struct _object[]’} [-Warray-bounds]
  481 |     if (--op->ob_refcnt == 0) {
      |        ^
Written build/lib.linux-x86_64-3.14/_sysconfigdata__linux_x86_64-linux-gnu.py
Written build/lib.linux-x86_64-3.14/_sysconfig_vars__linux_x86_64-linux-gnu.json
Checked 112 modules (34 built-in, 77 shared, 1 n/a on linux-x86_64, 0 disabled, 0 missing, 0 failed on import)

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

@skirpichev skirpichev added the type-bug An unexpected behavior, bug, or error label Mar 28, 2025
@vstinner
Copy link
Member

I don't understand the warning, the function uses a pointer, it doesn't use an array:

static inline void Py_DECREF_MORTAL(PyObject *op)
{
    assert(!_Py_IsStaticImmortal(op));
    _Py_DECREF_STAT_INC();
    if (--op->ob_refcnt == 0) {
        _Py_Dealloc(op);
    }
}

@picnixz picnixz added build The build process and cross-build interpreter-core (Objects, Python, Grammar, and Parser dirs) labels Mar 28, 2025
@ZeroIntensity
Copy link
Member

I think it has to do with the compiler performing the decrement on the op address, not the ob_refcnt field. It should be fixable by changing it to --(op->ob_refcnt) instead.

@picnixz
Copy link
Member

picnixz commented Mar 28, 2025

IIRC, according to precedence rules -> is before --, so it's surprising that the compiler complains here. But it doesn't hurt putting some () to avoid warnings.

@brandtbucher
Copy link
Member

But it doesn't hurt putting some () to avoid warnings.

I mean, this is a bug in the compiler, not in our code.

I understand adding parens as a way of silencing certain warnings about unclear operator precedence for human readers, etc. But if the compiler just doesn't understand C operator precedence, it’s just incorrect and should be fixed in the compiler.

@brandtbucher
Copy link
Member

This looks like a bug in GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104828

It’s probably because this particular pointer is cast from an integer (_PyStackRef.bits), and it somehow breaks the compiler’s pointer analysis.

@ZeroIntensity
Copy link
Member

I guess it's screwing with the operator precedence somehow?
FWIW, I don't see the warning on GCC 14, so it's seemingly fixed on new versions.

@brandtbucher
Copy link
Member

brandtbucher commented Mar 29, 2025

No, I don’t think this has anything to do with operator precedence. It’s just the dereference (op->ob_refcnt is equivalent to op[0].ob_refcnt) that’s triggering the bug here.

Basically, as I understand it, the C compiler tries its best to keep track of what exactly you’re pointing to. Among other things, it can use this info to tell you if you’re out of bounds of an array, or if you’re accessing invalid memory.

I think the “problem” is that when we cast the bits to a pointer (which is fine, tons of programs do it without issue), it’s sort of interpreting that as actually being a pointer to memory that doesn’t “exist” (similar to trying to access NULL[0x12345678]). It seems that it models this nonexistent memory an array of size zero, so our PyObject *op is being treated sort of like PyObject op[0] (a pointer to an array of zero PyObjects). When we try to access the memory, it warns.

It’s a compiler bug, plain and simple. Looks like it’s been fixed, too. We should probably just close this as “won’t fix”.

@skirpichev skirpichev added the pending The issue will be closed if no feedback is provided label Mar 29, 2025
@skirpichev
Copy link
Member Author

Bisected to 67fbfb4. I would appreciate a workaround, but if it's not actual for gcc 14 - probably this not worth it.

It seems, there are no warnings on gcc-10: https://github.com/python/cpython/actions/runs/14139921809/job/39619432128

@skirpichev skirpichev closed this as not planned Won't fix, can't repro, duplicate, stale Mar 29, 2025
@skirpichev skirpichev removed the pending The issue will be closed if no feedback is provided label Mar 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build The build process and cross-build interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

5 participants