Skip to content

Commit b866ef3

Browse files
authored
Merge branch 'dev' into drop_py2
2 parents 1dfb08a + cff58e1 commit b866ef3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+348
-96
lines changed

.github/workflows/ci.yml

+15
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,25 @@ jobs:
256256
pip install --upgrade pip
257257
pip install --upgrade --editable .
258258
259+
- name: Install documentation dependencies
260+
run: pip install -r docs/requirements.txt
261+
259262
- name: Sanity checks
260263
run: |
261264
python -bb -c 'from pwn import *'
262265
python -bb examples/text.py
266+
267+
- name: Coverage doctests
268+
run: |
269+
python -bb -m coverage run -m sphinx -b doctest docs/source docs/build/doctest
270+
271+
# FIXME: Paths are broken when uploading coverage on ubuntu
272+
# coverage.exceptions.NoSource: No source for code: '/home/runner/work/pwntools/pwntools/D:\a\pwntools\pwntools\pwn\__init__.py'.
273+
# - uses: actions/upload-artifact@v4
274+
# with:
275+
# name: coverage-windows
276+
# path: .coverage*
277+
# include-hidden-files: true
263278

264279
upload-coverage:
265280
runs-on: ubuntu-latest

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,21 @@ The table below shows which release corresponds to each branch, and what date th
7575
## 5.0.0 (`dev`)
7676

7777
- [#2519][2519] Drop Python 2.7 support / Require Python 3.10
78+
- [#2507][2507] Add `+LINUX` and `+WINDOWS` doctest options and start proper testing on Windows
79+
- [#2522][2522] Support starting a kitty debugging window with the 'kitten' command
80+
- [#2524][2524] Raise EOFError during `process.recv` when stdout closes on Windows
81+
- [#2526][2526] Properly make use of extra arguments in `packing` utilities. `sign` parameter requires keyword syntax to specify it.
82+
- [#2517][2517] Allow to passthru kwargs on `ssh.__getattr__` convenience function to fix SSH motd problems
7883

7984
[2519]: https://github.com/Gallopsled/pwntools/pull/2519
85+
[2507]: https://github.com/Gallopsled/pwntools/pull/2507
86+
[2522]: https://github.com/Gallopsled/pwntools/pull/2522
87+
[2524]: https://github.com/Gallopsled/pwntools/pull/2524
88+
[2526]: https://github.com/Gallopsled/pwntools/pull/2526
89+
[2517]: https://github.com/Gallopsled/pwntools/pull/2517
8090

8191
## 4.15.0 (`beta`)
92+
8293
- [#2508][2508] Ignore a warning when compiling with asm on nix
8394
- [#2471][2471] Properly close spawned kitty window
8495
- [#2358][2358] Cache output of `asm()`

docs/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ pysocks
1616
psutil
1717
requests>=2.5.1
1818
ropgadget>=5.3
19-
sphinx>=7.0.0
19+
sphinx>=8.1.3, <9
2020
sphinx_rtd_theme
2121
sphinxcontrib-autoprogram<=0.1.5

docs/source/adb.rst

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from pwn import *
55
adb = pwnlib.adb
66

7+
import doctest
8+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
9+
710
:mod:`pwnlib.adb` --- Android Debug Bridge
811
=====================================================
912

docs/source/asm.rst

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
import subprocess
55
from pwn import *
66

7+
# TODO: Remove global POSIX flag
8+
import doctest
9+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
10+
711
:mod:`pwnlib.asm` --- Assembler functions
812
=========================================
913

docs/source/conf.py

+75-7
Original file line numberDiff line numberDiff line change
@@ -394,19 +394,87 @@ def dont_skip_any_doctests(app, what, name, obj, skip, options):
394394

395395
autodoc_default_options = {'special-members': None, 'private-members': None}
396396

397+
# doctest optionflags for platform-specific tests
398+
# they are skipped on other platforms
399+
WINDOWS = doctest.register_optionflag('WINDOWS')
400+
LINUX = doctest.register_optionflag('LINUX')
401+
POSIX = doctest.register_optionflag('POSIX')
402+
403+
# doctest optionflag for tests that haven't been looked at yet
404+
TODO = doctest.register_optionflag('TODO')
405+
406+
import sphinx.ext.doctest
407+
408+
class PlatformDocTestRunner(sphinx.ext.doctest.SphinxDocTestRunner):
409+
def run(self, test, compileflags=None, out=None, clear_globs=True):
410+
original_optionflags = self.optionflags | test.globs.get('doctest_additional_flags', 0)
411+
def filter_platform(example):
412+
optionflags = original_optionflags
413+
if example.options:
414+
for (optionflag, val) in example.options.items():
415+
if val:
416+
optionflags |= optionflag
417+
else:
418+
optionflags &= ~optionflag
419+
420+
if (optionflags & WINDOWS) == WINDOWS and sys.platform != 'win32':
421+
return False
422+
if (optionflags & LINUX) == LINUX and sys.platform != 'linux':
423+
return False
424+
if (optionflags & POSIX) == POSIX and os.name != 'posix':
425+
return False
426+
return True
427+
428+
test.examples[:] = [example for example in test.examples if filter_platform(example)]
429+
430+
return super(PlatformDocTestRunner, self).run(test, compileflags, out, clear_globs)
431+
432+
class PlatformDocTestBuilder(sphinx.ext.doctest.DocTestBuilder):
433+
_test_runner = None
434+
435+
@property
436+
def test_runner(self):
437+
return self._test_runner
438+
439+
@test_runner.setter
440+
def test_runner(self, value):
441+
self._test_runner = PlatformDocTestRunner(value._checker, value._verbose, value.optionflags)
442+
397443
if 'doctest' in sys.argv:
398444
def setup(app):
399-
pass # app.connect('autodoc-skip-member', dont_skip_any_doctests)
400-
445+
app.add_builder(PlatformDocTestBuilder, override=True)
446+
# app.connect('autodoc-skip-member', dont_skip_any_doctests)
401447
# monkey patching paramiko due to https://github.com/paramiko/paramiko/pull/1661
402448
import paramiko.client
403449
import binascii
404450
paramiko.client.hexlify = lambda x: binascii.hexlify(x).decode()
405451
paramiko.util.safe_string = lambda x: '' # function result never *actually used*
406452

407453
class EndlessLoop(Exception): pass
408-
def alrm_handler(sig, frame):
409-
signal.alarm(180) # three minutes
410-
raise EndlessLoop()
411-
signal.signal(signal.SIGALRM, alrm_handler)
412-
signal.alarm(600) # ten minutes
454+
if hasattr(signal, 'alarm'):
455+
def alrm_handler(sig, frame):
456+
signal.alarm(180) # three minutes
457+
raise EndlessLoop()
458+
signal.signal(signal.SIGALRM, alrm_handler)
459+
signal.alarm(600) # ten minutes
460+
else:
461+
def sigabrt_handler(signum, frame):
462+
raise EndlessLoop()
463+
# thread.interrupt_main received the signum parameter in Python 3.10
464+
if sys.version_info >= (3, 10):
465+
signal.signal(signal.SIGABRT, sigabrt_handler)
466+
def alrm_handler():
467+
try:
468+
import thread
469+
except ImportError:
470+
import _thread as thread
471+
# pre Python 3.10 this raises a KeyboardInterrupt in the main thread.
472+
# it might not show a traceback in that case, but it will stop the endless loop.
473+
thread.interrupt_main(signal.SIGABRT)
474+
timer = threading.Timer(interval=180, function=alrm_handler) # three minutes
475+
timer.daemon = True
476+
timer.start()
477+
import threading
478+
timer = threading.Timer(interval=600, function=alrm_handler) # ten minutes
479+
timer.daemon = True
480+
timer.start()

docs/source/elf/corefile.rst

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
# Set the environment here so it's not in the middle of our tests.
1919
os.environ.setdefault('SHELL', '/bin/sh')
2020

21+
import doctest
22+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
23+
2124

2225
:mod:`pwnlib.elf.corefile` --- Core Files
2326
===========================================================

docs/source/elf/elf.rst

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
from pwnlib.elf.maps import CAT_PROC_MAPS_EXIT
66
import shutil
77

8+
# TODO: Remove global POSIX flag
9+
import doctest
10+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
11+
812
:mod:`pwnlib.elf.elf` --- ELF Files
913
===========================================================
1014

docs/source/encoders.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
.. testsetup:: *
22

33
from pwn import *
4+
5+
# TODO: Remove global POSIX flag
6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
48

59
:mod:`pwnlib.encoders` --- Encoding Shellcode
610
===============================================

docs/source/filesystem.rst

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
from pwnlib.tubes.ssh import ssh
77
from pwnlib.filesystem import *
88

9+
# TODO: Remove global POSIX flag
10+
import doctest
11+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
12+
913
:mod:`pwnlib.filesystem` --- Manipulating Files Locally and Over SSH
1014
====================================================================
1115

docs/source/gdb.rst

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
context.arch = 'amd64'
55
context.terminal = [os.path.join(os.path.dirname(pwnlib.__file__), 'gdb_faketerminal.py')]
66

7+
# TODO: Test on cygwin too
8+
import doctest
9+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
10+
711
:mod:`pwnlib.gdb` --- Working with GDB
812
======================================
913

docs/source/intro.rst

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
from pwn import *
44

5+
import doctest
6+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
7+
58
Getting Started
69
========================
710

docs/source/libcdb.rst

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from pwn import *
44
from pwnlib.libcdb import *
55

6+
# TODO: Remove global POSIX flag
7+
import doctest
8+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
9+
610
:mod:`pwnlib.libcdb` --- Libc Database
711
===========================================
812

docs/source/qemu.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
from pwn import *
44

5+
# TODO: Remove global POSIX flag
6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
8+
59

610
:mod:`pwnlib.qemu` --- QEMU Utilities
711
==========================================

docs/source/rop/rop.rst

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
context.clear()
2121

22+
# TODO: Remove global LINUX flag
23+
import doctest
24+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
25+
2226

2327
:mod:`pwnlib.rop.rop` --- Return Oriented Programming
2428
==========================================================

docs/source/rop/srop.rst

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from pwnlib.elf import ELF
88
from pwnlib.tubes.process import process
99

10+
import doctest
11+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
12+
1013
:mod:`pwnlib.rop.srop` --- Sigreturn Oriented Programming
1114
==========================================================
1215

docs/source/runner.rst

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from pwnlib.runner import *
44
from pwnlib.asm import asm
55

6+
# TODO: Remove global POSIX flag
7+
import doctest
8+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
9+
610
:mod:`pwnlib.runner` --- Running Shellcode
711
===========================================
812

docs/source/shellcraft.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
from pwnlib import shellcraft
44

5+
# TODO: Remove global POSIX flag
6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
8+
59
:mod:`pwnlib.shellcraft` --- Shellcode generation
610
=================================================
711

docs/source/shellcraft/aarch64.rst

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from pwn import *
44
context.clear(arch='aarch64')
55

6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
8+
69
:mod:`pwnlib.shellcraft.aarch64` --- Shellcode for AArch64
710
===========================================================
811

docs/source/shellcraft/amd64.rst

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from pwn import *
44
context.clear(arch='amd64')
55

6+
# TODO: POSIX/WINDOWS shellcode test
7+
import doctest
8+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
9+
610
:mod:`pwnlib.shellcraft.amd64` --- Shellcode for AMD64
711
===========================================================
812

docs/source/shellcraft/arm.rst

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from pwn import *
44
context.clear(arch='arm')
55

6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
8+
69
:mod:`pwnlib.shellcraft.arm` --- Shellcode for ARM
710
===========================================================
811

docs/source/shellcraft/i386.rst

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from pwn import *
44
context.clear(arch='i386')
55

6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
8+
69
:mod:`pwnlib.shellcraft.i386` --- Shellcode for Intel 80386
710
===========================================================
811

docs/source/shellcraft/mips.rst

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
context.clear(arch='mips')
1414

15+
import doctest
16+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
17+
1518
:mod:`pwnlib.shellcraft.mips` --- Shellcode for MIPS
1619
===========================================================
1720

docs/source/shellcraft/riscv64.rst

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from pwn import *
44
context.clear(arch='riscv64')
55

6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
8+
69
:mod:`pwnlib.shellcraft.riscv64` --- Shellcode for RISCV64
710
==========================================================
811

docs/source/shellcraft/thumb.rst

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from pwn import *
44
context.clear(arch='thumb')
55

6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['LINUX']
8+
69
:mod:`pwnlib.shellcraft.thumb` --- Shellcode for Thumb Mode
710
===========================================================
811

docs/source/tubes/processes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
from pwn import *
44

5+
# TODO: Remove global POSIX flag
6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
8+
59
:mod:`pwnlib.tubes.process` --- Processes
610
===========================================================
711

docs/source/tubes/serial.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
from pwn import *
44

5+
# TODO: Remove global POSIX flag
6+
import doctest
7+
doctest_additional_flags = doctest.OPTIONFLAGS_BY_NAME['POSIX']
8+
59
:mod:`pwnlib.tubes.serialtube` --- Serial Ports
610
===========================================================
711

0 commit comments

Comments
 (0)