Skip to content

gh-138890: Add clearer message when deleting builtins with del#139078

Open
Tapeline wants to merge 5 commits intopython:mainfrom
Tapeline:fix-gh-138890
Open

gh-138890: Add clearer message when deleting builtins with del#139078
Tapeline wants to merge 5 commits intopython:mainfrom
Tapeline:fix-gh-138890

Conversation

@Tapeline
Copy link
Copy Markdown
Contributor

@Tapeline Tapeline commented Sep 17, 2025

@Tapeline Tapeline marked this pull request as ready for review September 17, 2025 21:02
Comment thread Python/generated_cases.c.h Outdated
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
);
name = PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better no to break the declaration and the assignment?

Comment thread Python/generated_cases.c.h Outdated
Comment thread Python/bytecodes.c Outdated
Comment thread Python/bytecodes.c Outdated
Comment thread Python/bytecodes.c Outdated
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
);
PyObject *name;
name = PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyTuple_GetItem can fail. We should be able to expect that it can't, so let's use PyTuple_GET_ITEM.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we leave this as is? This seems like an unrelated change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the new usage of PyTuple_GetItem is potentially dangerous. Initially, it was used alongside _PyEval_FormatExcCheckArg, which would safely check for NULL to propagate exceptions during the lookup. Now, we're calling PyMapping_HasKeyWithError with a potentially NULL argument, which isn't safe. There are two solutions:

  1. Use PyTuple_GET_ITEM, which prevents failure entirely. This can possibly crash if someone messed with the code object, but that's possible already.
  2. Check the result of PyTuple_GetItem before calling PyMapping_HasKeyWithError.

My suggestion was choosing the former, but I missed that we were using PyTuple_GetItem initially. I think you're right that we should continue using that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the new usage of PyTuple_GetItem is potentially dangerous

I missed that we were using PyTuple_GetItem initially. I think you're right that we should continue using that.

So what should we do? Do we leave this as is?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do this:

Check the result of PyTuple_GetItem before calling PyMapping_HasKeyWithError.

Comment thread Python/bytecodes.c Outdated
Comment thread Misc/NEWS.d/next/Core_and_Builtins/2025-09-18-01-13-22.gh-issue-138890.x2QKfy.rst Outdated
Comment thread Lib/test/test_scope.py Outdated
Try to fit C code in reasonable width
Comment thread Lib/test/test_scope.py
Copy link
Copy Markdown
Member

@terryjreedy terryjreedy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other two tests also assume that the user correctly typed the intended name and meant to delete a builtin rather than a masking use. I think this will be true less than half the time.

Comment thread Lib/test/test_scope.py
Comment on lines +842 to +846
def f():
del all

with self.assertRaisesRegex(UnboundLocalError, "cannot delete builtin 'all'"):
f()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within a function it does not matter whether a name not in a global statement is or is not in globals or builtins. It only matters that it is an unbound local. Leave this case alone.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do so, should we also revert changes in DELETE_FAST implementation?

@github-actions
Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting core review stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants