-
Notifications
You must be signed in to change notification settings - Fork 19
mmap: bound find/rfind by the needle rather than clamping the subtraction #1184
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
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c925796
jit-trace: preserve semantic maps at non-live jitcode PCs
youknowone 842be03
mmap: bound find/rfind by the needle rather than clamping the subtrac…
youknowone 0b885e3
mmap: implement the module on Windows
youknowone f674b2a
jit: split the dead-op removal test off the CSE purity predicate
youknowone ebc7c58
jit-trace: drop pcdep at non-decodable resume positions
youknowone 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
77 changes: 77 additions & 0 deletions
77
pyre/extra_tests/parity_tests/mmap_find_span_shorter_than_needle.py
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,77 @@ | ||
| # CPython-suite gap: test_mmap's exhaustive find/rfind sweep (test_find_end, | ||
| # test_rfind) never uses an empty pattern — its list is | ||
| # [b"o", b"on", b"two", b"ones", b"s"] — so the near-end answer an empty needle | ||
| # owes is untested there. The oversized-needle cases below are covered by that | ||
| # sweep, and are kept only to hold the two halves of one bound together. | ||
| # parity-tests reason: test_mmap is not in the suite gate (still 3 failures and | ||
| # 21 errors), so nothing in the vendored suite protects either half today. | ||
|
|
||
| """`mmap.find`/`rfind` over a span that cannot hold the needle report -1. | ||
|
|
||
| The scan's upper bound is `span - len(needle)`. Clamping that subtraction at | ||
| zero still leaves one index to try, and reading a needle-sized window there | ||
| runs off the end of a shorter span, so the interpreter aborts instead of | ||
| answering. | ||
|
|
||
| The empty needle is the boundary in the other direction, and it is the half | ||
| with no oracle in the vendored suite: it matches at the near end of the span — | ||
| `start` for `find`, `end` for `rfind` — where a shared "empty or inverted" | ||
| guard would fold it into -1 along with the spans that really have no room. | ||
|
|
||
| Every case pins the value rather than the absence of a panic, so the fixture | ||
| keeps its meaning once the abort is gone. | ||
| """ | ||
|
|
||
| import mmap | ||
|
|
||
| m = mmap.mmap(-1, 4) | ||
| m[:] = b"abca" | ||
|
|
||
| # The empty needle matches at the near end of the span. | ||
| assert m.find(b"") == 0, m.find(b"") | ||
| assert m.rfind(b"") == 4, m.rfind(b"") | ||
| assert m.find(b"", 2) == 2, m.find(b"", 2) | ||
| assert m.rfind(b"", 0, 2) == 2, m.rfind(b"", 0, 2) | ||
| assert m.find(b"", 4) == 4, m.find(b"", 4) | ||
| assert m.rfind(b"", 4) == 4, m.rfind(b"", 4) | ||
| assert m.find(b"", -2) == 2, m.find(b"", -2) | ||
| assert m.rfind(b"", -2) == 4, m.rfind(b"", -2) | ||
|
|
||
| # An inverted span holds nothing at all, not even the empty needle. | ||
| assert m.find(b"", 3, 1) == -1, m.find(b"", 3, 1) | ||
| assert m.rfind(b"", 3, 1) == -1, m.rfind(b"", 3, 1) | ||
|
|
||
| # The needle is longer than the whole map. | ||
| assert m.find(b"abcab") == -1, m.find(b"abcab") | ||
| assert m.rfind(b"abcab") == -1, m.rfind(b"abcab") | ||
|
|
||
| # The needle fits the map but not the requested span. | ||
| assert m.find(b"abc", 2) == -1, m.find(b"abc", 2) | ||
| assert m.rfind(b"abc", 2) == -1, m.rfind(b"abc", 2) | ||
| assert m.find(b"abc", 0, 2) == -1, m.find(b"abc", 0, 2) | ||
| assert m.rfind(b"abc", 0, 2) == -1, m.rfind(b"abc", 0, 2) | ||
|
|
||
| # A span exactly the needle's length still has one candidate. | ||
| assert m.find(b"bc", 1, 3) == 1, m.find(b"bc", 1, 3) | ||
| assert m.rfind(b"bc", 1, 3) == 1, m.rfind(b"bc", 1, 3) | ||
|
|
||
| # The ordinary answers, so a bound that returns -1 too eagerly is caught too. | ||
| assert m.find(b"a") == 0, m.find(b"a") | ||
| assert m.rfind(b"a") == 3, m.rfind(b"a") | ||
| assert m.find(b"ca") == 2, m.find(b"ca") | ||
| assert m.find(b"a", -1) == 3, m.find(b"a", -1) | ||
| assert m.find(b"abca", -10) == 0, m.find(b"abca", -10) | ||
|
|
||
| m.close() | ||
|
|
||
| # A one-byte map is the smallest span an oversized needle can overrun. | ||
| one = mmap.mmap(-1, 1) | ||
| one[:] = b"a" | ||
| assert one.find(b"ab") == -1, one.find(b"ab") | ||
| assert one.rfind(b"ab") == -1, one.rfind(b"ab") | ||
| assert one.find(b"") == 0, one.find(b"") | ||
| assert one.rfind(b"") == 1, one.rfind(b"") | ||
| assert one.find(b"a") == 0, one.find(b"a") | ||
| one.close() | ||
|
|
||
| print("OK") |
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Keep
NewListout ofis_pure_op.NewListallocates a fresh mutable object. Classifying it as pure permits CSE to merge separate list allocations and changes identity and mutation behavior. The comment already states thatNewListis notPureOperation, butcan_remove_opcurrently has no separateNewListcase.Return
falsefromis_pure_opforNewList. Returntruefor it fromcan_remove_op. Add assertions for both predicates.Proposed fix
As per coding guidelines, port RPython/PyPy code with strict line-by-line structural parity; do not take shortcuts.
Also applies to: 1290-1303, 1564-1598
🤖 Prompt for AI Agents
Source: Coding guidelines