Skip to content

fix: correctly detect flow-list/single-flow command results in the console - #8375

Open
citizen204 wants to merge 1 commit into
mitmproxy:mainfrom
citizen204:fix-4916-flow-list-dead-type-check
Open

fix: correctly detect flow-list/single-flow command results in the console#8375
citizen204 wants to merge 1 commit into
mitmproxy:mainfrom
citizen204:fix-4916-flow-list-dead-type-check

Conversation

@citizen204

Copy link
Copy Markdown

Summary

CommandExecutor decides whether a command's return value should be shown as a
short status message using type(ret) == Sequence[flow.Flow] and
type(ret) is flow.Flow. Neither check can ever be true at runtime: Python
erases generic parameters, so no concrete type ever equals the subscripted
Sequence[flow.Flow], and type(x) is flow.Flow only matches the exact base
class, never a concrete subclass like HTTPFlow/TCPFlow/UDPFlow/DNSFlow
— which is what every real command actually returns.

As a result, any command returning a list of flows (e.g.
view.flows.resolve @focus) or a single flow always fell through to the
DataViewerOverlay branch instead of the intended status message. That
overlay's grid editor deepcopies its input, which is how the original report
crashed with TypeError: cannot pickle 'Context' object. I could no longer
reproduce the exact pickling crash with current flow/connection objects (it
may have been incidentally fixed by unrelated refactors), but the dead
type-check itself is still very much present and still routes flow-list
results to the wrong UI — confirmed with a regression test that fails against
current main (the overlay mock is called when it shouldn't be) and passes
after this fix.

Fixes #4916

Changes

  • mitmproxy/tools/console/commandexecutor.py: replace the dead type() ==/
    type() is checks with isinstance()-based checks that actually match at
    runtime, plus an explicit non-empty/non-str guard for the sequence case.
  • test/mitmproxy/tools/console/test_commandexecutor.py: new regression
    tests covering flow-list, single-flow, and non-flow command results
    (verified fail-before / pass-after via git stash).

🤖 Generated with Claude Code

…nsole

CommandExecutor used `type(ret) == Sequence[flow.Flow]` and
`type(ret) is flow.Flow` to decide whether a command's return value should
be shown as a short status message. Neither check can ever be true at
runtime: Python erases generic type parameters, so no concrete type is
ever equal to the subscripted `Sequence[flow.Flow]`, and `type(x) is`
only matches the exact base class, never a concrete subclass like
HTTPFlow/TCPFlow/UDPFlow/DNSFlow.

As a result, any command returning a list of flows (e.g.
`view.flows.resolve @focus`) or a single flow always fell through to
the DataViewerOverlay branch instead, which is at best the wrong UI
and at worst crashes when the overlay's grid editor tries to
deepcopy flows carrying connection state that isn't picklable.

Fixes mitmproxy#4916

## Changes

- `mitmproxy/tools/console/commandexecutor.py`: replace the dead
  `type() ==`/`type() is` checks with `isinstance()`-based checks
  that actually match at runtime.
- `test/mitmproxy/tools/console/test_commandexecutor.py`: add
  regression tests covering flow-list, single-flow, and
  non-flow command results.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Commands that return a list of flows crash when a flow has been loaded from a file

1 participant