Skip to content

fix(foundation): treat only a regular file's seekable() as trustworthy (#2097) - #2104

Merged
JarryShaw merged 1 commit into
mainfrom
fix/2097-windows-pipe-seekable
Oct 23, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/2097-windows-pipe-seekable

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix — bug fixes

Description of your pull request and other information

Closes #2097. On Windows a pipe's file object reports seekable() as True while seek does nothing (the agent cites CPython gh-86768 / bpo-42602; not re-verified here). Extractor.__init__ therefore wrapped the raw pipe in PeekableStream, whose peek-then-seek-back lost the 4 magic octets. A buffered stdin got no wrapper at all, so its seek(0, SEEK_END) answers were wrong. That is why 25 pipe cases, pcapkit - included, failed on the Windows leg (job 120605026883).

  • Fix: the new _can_seek() in pcapkit/foundation/extraction.py trusts seekable() only when os.fstat(fileno) reports a regular file. A stream without a descriptor (e.g. BytesIO) is taken at its word as before. Anything else is wrapped in SeekableReader.
  • Test: test_extraction_windows_pipe_seekable_2097_unit uses a real os.pipe that claims to be seekable and has a no-op seek. Without the fix the raw case raises ProtocolError: invalid magic number, as in the CI log, and the buffered case returns 0 frames instead of 50. The non-seekable stream tests pass.

#2097)

On Windows before CPython 3.16 a pipe reports seekable() and its seek does
nothing (CPython gh-86768), so Extractor skipped SeekableReader and lost the
octets its magic-number peek read. A stream whose descriptor is not a
regular file is now wrapped; one without a descriptor is taken at its word.
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 23, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO at 61aa9f979 (Sonnet review).

  • Test: the new test fails with extraction.py reverted to 862a6e679 and passes with the fix. The non-seekable, no-EOF, ownership, extraction, io and CLI tests pass.
  • CPython reference: confirmed through the API. gh-86768 is "seekable() returns True on pipe objects in Windows". PR 133137, which makes os.lseek check seekability on Windows, merged to main on 2026-08-11. That it ships in 3.16 is the reviewer's inference.
  • Linux probes of _can_seek: regular files, gzip.GzipFile, BytesIO and stdin redirected from a file stay unwrapped. A pipe, a socket makefile and /dev/null get wrapped. io.UnsupportedOperation from fileno() is caught. Wrapping a seekable device such as /dev/null is harmless, only slower.
  • UNVERIFIED: that Windows os.fstat reports S_IFIFO for a pipe.
  • Follow-up: PeekableStream in pcapkit/corekit/io.py has its own seekable() check without the fstat guard. Tracked separately.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 23, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage: 91.54% (unit tier, Python 3.15, 61aa9f979, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 19599 880 2618 866 92.12%
pcapkit/corekit 2565 71 812 37 96.56%
pcapkit/dumpkit 282 3 102 3 98.44%
pcapkit/foundation 2939 23 1024 25 98.79%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 17414 219 4574 185 98.14%
pcapkit/toolkit 869 36 298 10 95.20%
pcapkit/utilities 473 7 136 5 98.03%
pcapkit/vendor 4432 1988 1018 167 51.87%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Ready to merge at 61aa9f979.

  • Review: the Sonnet review is GOOD TO GO.
  • CI: every blocking check passed (Required checks passed SUCCESS). The 3.8–3.10 KTLO legs carry no warnings.
  • Ordering: the tests/foundation plain-unittest ordering leg passed on a scratch merge into main: 712 tests, 0 failures.
  • Base: the head is behind main only by test-only and workflow commits that don't touch extraction.py, and the scratch merge was clean.

This closes #2097. #2108 (the record-skip helper) follows once it merges.

@JarryShaw
JarryShaw merged commit c7229b4 into main Oct 23, 2026
65 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 23, 2026
@JarryShaw
JarryShaw deleted the fix/2097-windows-pipe-seekable branch October 23, 2026 21:44
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 23, 2026
@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issues reporting a defect (set by the bug report template; a default, not an assessment)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(foundation): a Windows pipe passes seekable(), so its peeked octets are lost

1 participant