classification
Title: Pdb crashes when code is executed in a mapping that does not define `__contains__`
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: ppperry, scotchka, serhiy.storchaka, xtreak
Priority: normal Keywords: patch, patch

Created on 2018-09-23 21:38 by ppperry, last changed 2019-01-18 16:31 by scotchka.

Pull Requests
URL Status Linked Edit
PR 11571 closed BTaskaya, 2019-01-15 17:46
PR 11571 closed BTaskaya, 2019-01-15 17:46
Messages (8)
msg326186 - (view) Author: (ppperry) Date: 2018-09-23 21:38
class FakeContainer:
	def __getitem__(self, key)
		raise KeyError(key)
pdb.run("pass",{},FakeContainer())

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    pdb.run("pass",{},FakeContainer())
  File "C:\Program Files\Python37\lib\pdb.py", line 1590, in run
    Pdb().run(statement, globals, locals)
  File "C:\Program Files\Python37\lib\bdb.py", line 585, in run
    exec(cmd, globals, locals)
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <module>
  File "C:\Program Files\Python37\lib\bdb.py", line 88, in trace_dispatch
    return self.dispatch_line(frame)
  File "C:\Program Files\Python37\lib\bdb.py", line 112, in dispatch_line
    self.user_line(frame)
  File "C:\Program Files\Python37\lib\pdb.py", line 261, in user_line
    self.interaction(frame, None)
  File "C:\Program Files\Python37\lib\pdb.py", line 351, in interaction
    self.print_stack_entry(self.stack[self.curindex])
  File "C:\Program Files\Python37\lib\pdb.py", line 1453, in print_stack_entry
    self.format_stack_entry(frame_lineno, prompt_prefix))
  File "C:\Program Files\Python37\lib\bdb.py", line 549, in format_stack_entry
    if '__args__' in frame.f_locals:
  File "<pyshell#3>", line 3, in __getitem__
    raise KeyError
KeyError: 0

Obviously, the debugger shouldn't crash in this case (running code outside of the debugger works as expected, producing a NameError on variable reads and a TypeError whenever a name is assigned).
msg333763 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-01-16 12:14
There is no a crash. There is just an exception raised when you pass an inappropriate object as locals. This is an expected behavior, and I do not think that anything need to be changed.
msg333781 - (view) Author: Henry Chen (scotchka) * Date: 2019-01-16 17:48
I agree that this behavior is normal, unless there is a use case for passing a partially implemented mapping object to pdb.run. However I cannot think of such a use case.
msg333785 - (view) Author: (ppperry) Date: 2019-01-16 20:05
The thing is, though, that the same error occurs if a larger code being debugged calls `exec` or `eval` with such a mapping (`pdb.run("eval('1+1',{},FakeContainer())" also crashes with the same error), and the test suite contains code that evals other code in an incomplete mapping (test_var_annot_custom_maps in test_grammar)
msg333812 - (view) Author: Henry Chen (scotchka) * Date: 2019-01-17 01:37
Hmm, the example works for me (Python 3.6.5):

>>> import pdb
>>> class FakeContainer:
...     def __getitem__(self, key):
...             raise KeyError(key)
...
>>> pdb.run("eval('1+1',{},FakeContainer())")
> <string>(1)<module>()
(Pdb) c
>>>

As for exec/eval accepting an incomplete mapping, that strikes me as a less than thorough checking on the part of exec/eval, perhaps for performance reasons(?)
msg333813 - (view) Author: (ppperry) Date: 2019-01-17 01:40
You have to step into the eval for the error to be raised.
msg333833 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-01-17 09:26
This looks to me like an error in the user code. What is the use case of passing an object that does not implement the mapping interface as locals to pdb.run()?
msg333988 - (view) Author: Henry Chen (scotchka) * Date: 2019-01-18 16:31
An attempt to clarify the issue in my own mind:

def foo():
    # import pdb; pdb.set_trace()
    exec('pass', {}, FakeContainer())

This function runs successfully. But if you uncomment the pdb line and then step thru in the pdb console, there is an Exception.

I *think* the underlying principle is that code that runs normally should also run under pdb, which this example violates. However, to adhere to the principle 100% could be a very steep technical cost.

Alternatively, I'd argue that the function should NOT run even without pdb, since exec requires a (complete) mapping type according to the documentation. Perhaps the thing to do is to add more stringent type checking to exec and eval?
History
Date User Action Args
2019-01-18 16:31:42scotchkasetmessages: + msg333988
2019-01-17 09:26:12serhiy.storchakasetkeywords: patch, patch

messages: + msg333833
2019-01-17 01:40:03ppperrysetmessages: + msg333813
2019-01-17 01:38:00scotchkasetmessages: + msg333812
2019-01-16 20:05:51ppperrysetmessages: + msg333785
2019-01-16 17:48:36scotchkasetmessages: + msg333781
2019-01-16 12:14:36serhiy.storchakasetkeywords: patch, patch
nosy: + serhiy.storchaka
messages: + msg333763

2019-01-16 03:59:59scotchkasetnosy: + scotchka
2019-01-15 17:46:47BTaskayasetkeywords: + patch
stage: patch review
pull_requests: + pull_request11240
2019-01-15 17:46:43BTaskayasetkeywords: + patch
stage: (no value)
pull_requests: + pull_request11239
2018-09-24 02:43:40xtreaksetnosy: + xtreak
2018-09-23 21:39:57ppperrysettype: behavior
2018-09-23 21:38:01ppperrycreate