-
-
Notifications
You must be signed in to change notification settings - Fork 29
fix(app): prevent OverflowError from addresses above 2^63 in memory map #77
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
Merged
JeanExtreme002
merged 13 commits into
JeanExtreme002:main
from
cromachina:fix/memory-map-overflow-error
Aug 3, 2026
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
9e4b5c8
Fix overflow error that occurs with NumericItem by holding the data o…
cromachina 467f56d
Make addresses in memory map display as monospace so they are easier …
cromachina f78ce09
Make addresses in module viewer display as monospace so they are easi…
cromachina 9386f0b
Use dict for NumericItem role storage. Update types and docstring
cromachina 53fc977
Update monospace font assignment for memory map and modules widgets
cromachina 00b9fa0
Linter fixes
cromachina 9a8adc0
Add tests for _widgets, starting with NumericItem
cromachina 4e01f7a
Make UserRole the default role key instead of UserRole+1, since this …
cromachina b5d070e
Add text override to NumericItem to try to pull from the stored dict …
cromachina 08ea8c5
Add more coverage to NumericItem tests
cromachina a82087b
fix(app): drop NumericItem.text() override and assert the regressions
JeanExtreme002 57bb6ad
refactor(app): centralise the monospace family and split the widget t…
JeanExtreme002 9fcfc0a
docs(app): correct the NumericItem overflow rationale
JeanExtreme002 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| """ | ||
| Tests for the shared item widgets in ``PyMemoryEditor/app/_widgets.py``. | ||
| Only ``NumericItem`` so far, whose sort payload can't live in a ``QVariant``: | ||
| Qt caps those integers at ``qint64``, but Linux x86-64 maps ``[vsyscall]`` at | ||
| 0xffffffffff600000 (above 2**63), so pushing that address through | ||
| ``QStandardItem.setData`` raises "OverflowError: int too big to convert" and | ||
| leaves the memory map half-populated. | ||
| Unlike the dialog tests these need no ``qtbot`` — a ``QApplication`` is enough, | ||
| so they keep running when ``pytest-qt`` isn't installed. | ||
| Skipped when ``PySide6`` isn't installed (the runtime dependency is opt-in via | ||
| the ``app`` extra). | ||
| """ | ||
|
|
||
| import os | ||
|
|
||
| import pytest | ||
|
|
||
|
|
||
| pytest.importorskip("PySide6", reason="App tests require PySide6 (install with [app] extra).") | ||
|
|
||
| # Offscreen platform plugin: no display server needed, runs on CI. | ||
| os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") | ||
|
|
||
|
|
||
| @pytest.fixture(scope="module") | ||
| def qapp(): | ||
| """A single QApplication for the module (Qt allows only one per process).""" | ||
| from PySide6.QtWidgets import QApplication | ||
|
|
||
| return QApplication.instance() or QApplication([]) | ||
|
|
||
|
|
||
| def test_pyside_widget_regressions(qapp): | ||
| """ | ||
| Test for Pyside related regressions, like potential overflow and comparison in NumericItem. | ||
| """ | ||
|
|
||
| from PySide6.QtCore import Qt | ||
| from PySide6.QtGui import QStandardItemModel | ||
|
|
||
| from PyMemoryEditor.app import _widgets | ||
|
|
||
| unsigned_64bit_max = 0xffff_ffff_ffff_ffff | ||
| big_number = 2 ** 128 | ||
|
|
||
| # Overflow regressions. | ||
| item = _widgets.NumericItem() | ||
| item.setData(unsigned_64bit_max) | ||
| assert item.data() == unsigned_64bit_max | ||
|
|
||
| item2 = _widgets.NumericItem() | ||
| item2.setData(big_number) | ||
| assert item2.data() == big_number | ||
|
|
||
| # Non-numeric payloads must fall back to the labels instead of recursing | ||
| # into QStandardItem::operator< (that recursion segfaulted mid-sort). | ||
| assert item < item2 | ||
|
|
||
| item3 = _widgets.NumericItem('aaa') | ||
| item3.setData('hello world') | ||
| item4 = _widgets.NumericItem('bbb') | ||
| item4.setData('hello world') | ||
| assert item3 < item4 | ||
| assert not (item4 < item3) | ||
|
|
||
| # Distinct user roles must not share a slot. | ||
| item5 = _widgets.NumericItem() | ||
| item5.setData(111, Qt.UserRole) | ||
| item5.setData(222, Qt.UserRole + 1) | ||
| assert item5.data(Qt.UserRole) == 111 | ||
| assert item5.data(Qt.UserRole + 1) == 222 | ||
|
|
||
| # The path that actually crashed: the C++ sort driving the comparisons over | ||
| # a column mixing payloads and None (the process picker's memory column). | ||
| model = QStandardItemModel() | ||
| for label, payload in (('120 MB', 120), ('-', None), ('8 MB', 8), ('-', None)): | ||
| row_item = _widgets.NumericItem(label) | ||
| row_item.setData(payload, Qt.UserRole) | ||
| model.appendRow([row_item]) | ||
| model.sort(0, Qt.AscendingOrder) | ||
| order = [model.item(row, 0).data(Qt.DisplayRole) for row in range(model.rowCount())] | ||
| assert order.index('8 MB') < order.index('120 MB') |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.