Skip to content

fix(app): prevent OverflowError from addresses above 2^63 in memory map - #77

Merged
JeanExtreme002 merged 13 commits into
JeanExtreme002:mainfrom
cromachina:fix/memory-map-overflow-error
Aug 3, 2026
Merged

fix(app): prevent OverflowError from addresses above 2^63 in memory map#77
JeanExtreme002 merged 13 commits into
JeanExtreme002:mainfrom
cromachina:fix/memory-map-overflow-error

Conversation

@cromachina

@cromachina cromachina commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Why is this PR necessary, what does it do?

Fixes an error that appears when viewing the memory map (and also potentially the module viewer). The error prevents the lists from being fully populated. The error can also potentially segfault the program, at least when shiboken stuff runs.

Also includes a minor cosmetic change to make comparing the addresses in a list easier (monospace font for the addresses).

Checklist (complete all items):

  • [✅] Added tests as necessary.
  • [✅] There is no breaking change for existing features.

References:

Fixes #73

Notes:

No notes to be shared.

@github-actions github-actions Bot added app GUI application changes (PyMemoryEditor/app/) lib Library changes (PyMemoryEditor/) labels Jul 29, 2026
@cromachina

Copy link
Copy Markdown
Contributor Author

The "Lint PR title" check doesn't check case insensitive, even though github generates titles from branches automatically with casing.

@JeanExtreme002

JeanExtreme002 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Hi, @cromachina! Thanks for contributing.

There are some issues that must be fixed before merging this PR. I'll post the reviews here.

@JeanExtreme002 JeanExtreme002 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Good catch on the root cause. Verified locally: regular addresses (0x7ffd…) go through setData fine — only values above 2**63 overflow, which is exactly [vsyscall] at 0xffffffffff600000 on Linux x86-64. The Python-side payload is the right call, and it also covers pointer_scan_dialog.py:687, which had the same latent bug.

Three things before merge, inline. The first one is a crash, the other two are smaller.

One more: the checklist says tests were added, but there are none in the diff and _widgets.py has no test file yet. tests/app/ + QT_QPA_PLATFORM=offscreen already make this cheap to cover — a round trip with 0xffffffffff600000 and a sort over rows with a missing payload would pin both regressions.

Comment thread PyMemoryEditor/app/_widgets.py Outdated
Comment thread PyMemoryEditor/app/_widgets.py Outdated
Comment thread PyMemoryEditor/app/_widgets.py Outdated
Comment thread PyMemoryEditor/app/_widgets.py
Comment thread PyMemoryEditor/app/memory_map_dialog.py Outdated
Comment thread PyMemoryEditor/app/modules_dialog.py Outdated
@JeanExtreme002 JeanExtreme002 changed the title Fix/memory map overflow error fix(app): prevent OverflowError from addresses above 2^63 in memory map Aug 2, 2026
@github-actions github-actions Bot added the tests Test changes (tests/) label Aug 2, 2026

@JeanExtreme002 JeanExtreme002 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the quick turnaround — roles, type hints and the sort recursion are all sorted (verified: sorting a column with None payloads no longer crashes, and UserRole / UserRole + 1 stay distinct). Resolved those threads.

One new issue from the text() override, plus two smaller things, inline.

For the record on the docstring: the cap isn't really about unsigned support — a plain QStandardItem takes 0x7FFDABCD1234 fine and only breaks past 2**63, i.e. QVariant's qint64. Your 2**128 case shows the same edge. Also worth stating the constraint the workaround introduces: the payload never reaches the C++ model, so it must be read as item.data(role) and never model.data(index, role) — that path converts back to a QVariant and overflows again (confirmed locally).

Comment thread PyMemoryEditor/app/_widgets.py Outdated
Comment thread PyMemoryEditor/app/memory_map_dialog.py Outdated
Comment thread tests/app/test_app_smoke.py Outdated

@JeanExtreme002 JeanExtreme002 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Adding applicable suggestions for the two open points above. Both verified locally: with them the app suite is 83 passed and flake8 is clean; putting the text() override back makes the new assertions fail.

Comment thread PyMemoryEditor/app/_widgets.py Outdated
Comment thread tests/app/test_app_smoke.py Outdated
The override returned str(self.data()), so text() stopped matching what
the table displays (the raw payload instead of the formatted label, and
'None' for rows without one) and the __lt__ fallback compared 'None' to
'None' rather than the labels. Its except branch was unreachable too:
dict.get() returns None, it never raises KeyError. QStandardItem.text()
already returns the label the fallback wants.

The NumericItem tests were only checking that nothing crashed. Assert the
comparison results, and cover the two paths that weren't exercised: user
roles staying distinct, and the C++ sort driving comparisons over a column
that mixes payloads with None — the case that segfaulted, which comparing
two items directly doesn't reach.
@JeanExtreme002

Copy link
Copy Markdown
Owner

I went ahead and pushed the two suggestions to this branch (a82087b) since the branch allows maintainer edits — feel free to amend or revert if you'd rather do it yourself.

  • Dropped the text() override. Its except KeyError was unreachable (dict.get() returns None), so text() was returning the raw payload instead of the label, and the __lt__ fallback was comparing 'None' to 'None' instead of the labels.
  • Added assertions to the NumericItem test, plus coverage for the role collision and for model.sort() over a column mixing payloads with None — the case that actually segfaulted, which comparing two items directly doesn't reach.

Verified locally: 406 passed, 78 skipped, flake8 clean.

Still open: the model.data() note in the docstring, and _MONO living in pointer_scan_dialog rather than _widgets. Both are minor.

…ests

The address columns were reaching into pointer_scan_dialog for its private
_MONO, which points the dependency the wrong way: the memory map pulled in
the whole pointer scan module for one string. Move the family to _widgets,
next to the NumericItem those columns already import, and have all three
dialogs read it from there. The memory map's size field was hardcoding the
same stack, so it reads the constant now too.

Move the NumericItem tests out of the smoke file into test_app_widgets.py.
They were gated behind a pytest-qt skip they never needed — none of them
uses qtbot, a QApplication is enough — so they now run wherever PySide6 is
installed.
@JeanExtreme002

Copy link
Copy Markdown
Owner

Pushed the last two as well (57bb6ad):

  • MONOSPACE_FAMILY now lives in _widgets.py next to NumericItem, and all three dialogs read it from there instead of importing _MONO across dialog modules. The memory map's size field was hardcoding the same string, so it uses the constant too.
  • The NumericItem tests moved to tests/app/test_app_widgets.py. They were behind a pytest-qt skip they never needed (no qtbot, just a QApplication), so they run wherever PySide6 is installed.

406 passed, 78 skipped, flake8 clean. All review threads are resolved now — the only thing I left alone is the docstring wording, which is fine as is.

The cap isn't about unsigned support — a plain QStandardItem takes
0x7FFDABCD1234 without complaint and only breaks past 2**63, which is
QVariant's qint64 limit. Name the actual trigger ([vsyscall] at
0xffffffffff600000) and the constraint the workaround creates: the payload
never reaches the C++ model, so reading it back through model.data() hits
the same OverflowError.
@JeanExtreme002

Copy link
Copy Markdown
Owner

Last one from me (9fcfc0a) — reworded the docstring rationale. A plain QStandardItem takes 0x7FFDABCD1234 fine and only breaks past 2**63, so the cap is QVariant's qint64 rather than unsigned support (your 2**128 case is the same edge). Also noted the constraint the workaround creates: the payload never reaches the C++ model, so reading it back via model.data(index, role) hits the same OverflowError — worth having written down before someone adds a delegate or a sort role over these columns.

From my side this is ready to merge.

@JeanExtreme002 JeanExtreme002 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

LGTM 🚀

@JeanExtreme002
JeanExtreme002 merged commit a2c583b into JeanExtreme002:main Aug 3, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app GUI application changes (PyMemoryEditor/app/) lib Library changes (PyMemoryEditor/) tests Test changes (tests/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory map dialog Qt overflow error

2 participants