Skip to content

Commit e882c9b

Browse files
authored
Enable basic tubes/process test on Windows (#2616)
* Enable basic tubes/process test on Windows Many tests are Linux specific using qemu or /proc etc. So only test the basic process interaction for now. * Cleanup docs without using ellipsis for Windows output * Set newline to b'\r\n' for local Windows processes But only change it automatically if `context.newline` wasn't set manually. * Disable process.terminate() test on Windows Windows doesn't support sending SIGTERM to other processes. https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal * libcdb CI cache: add another dns server [emerg] 1#1: host not found in upstream "debuginfod.elfutils.org" in /etc/nginx/nginx.conf:26 The cache should still start despite not being able to resolve some domain.
1 parent 195d7d5 commit e882c9b

5 files changed

Lines changed: 78 additions & 27 deletions

File tree

docs/source/tubes/processes.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
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-
95
:mod:`pwnlib.tubes.process` --- Processes
106
===========================================================
117

docs/source/tubes/serial.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
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-
95
:mod:`pwnlib.tubes.serialtube` --- Serial Ports
106
===========================================================
117

pwnlib/tubes/process.py

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,22 @@ class process(tube):
133133
True
134134
>>> p.connected('send')
135135
False
136-
>>> p.recvline()
137-
b'Hello world\n'
136+
>>> p.recvline(drop=True)
137+
b'Hello world'
138138
>>> p.recvuntil(b',')
139139
b'Wow,'
140140
>>> p.recvregex(b'.*data')
141141
b' such data'
142-
>>> p.recv()
143-
b'\n'
142+
>>> p.recv()[-1:] == b'\n'
143+
True
144144
>>> p.recv() # doctest: +ELLIPSIS
145145
Traceback (most recent call last):
146146
...
147147
EOFError
148148
149+
.. doctest::
150+
:options: +POSIX
151+
149152
>>> p = process('cat')
150153
>>> d = open('/dev/urandom', 'rb').read(4096)
151154
>>> p.recv(timeout=0.1)
@@ -289,6 +292,10 @@ def __init__(self, argv = None,
289292
self.suid = self.uid = None
290293
self.sgid = self.gid = None
291294
internal_preexec_fn = None
295+
# Expect Windows to use CRLF newlines, but if the user explicitly
296+
# set it to something else, don't mess with it.
297+
if 'newline' not in context._tls and context.newline == b'\n':
298+
self.newline = b'\r\n'
292299
else:
293300
# Avoid the need to have to deal with the STDOUT magic value.
294301
if stderr is STDOUT:
@@ -524,6 +531,9 @@ def program(self):
524531
525532
Example:
526533
534+
.. doctest::
535+
:options: +POSIX +TODO
536+
527537
>>> p = process('/bin/true')
528538
>>> p.executable == '/bin/true'
529539
True
@@ -539,6 +549,9 @@ def cwd(self):
539549
540550
Example:
541551
552+
.. doctest::
553+
:options: +POSIX +TODO
554+
542555
>>> p = process('sh')
543556
>>> p.sendline(b'cd /tmp; echo AAA')
544557
>>> _ = p.recvuntil(b'AAA')
@@ -687,8 +700,14 @@ def terminate(self):
687700
688701
The process can choose to ignore this signal, so proper cleanup
689702
is only done in :meth:`kill`/:meth:`close`.
703+
704+
Note: On Windows, there is no SIGTERM signal, so the Win32 API function ``TerminateProcess()`` is called
705+
instead, leading to :meth:`terminate()` and :meth:`kill()` being effectively the same.
690706
691707
Examples:
708+
709+
.. doctest::
710+
:options: +POSIX
692711
693712
>>> p = process(['python', '-u', '-c', 'import signal;signal.signal(signal.SIGTERM, lambda signum,frame: (print("sigterm"),exit(0)));print("ready");import time;time.sleep(10)'])
694713
>>> p.recvline_contains(b'ready')
@@ -945,7 +964,10 @@ def maps(self):
945964
read, write, execute, private, shared, string
946965
947966
Example:
948-
967+
968+
.. doctest::
969+
:options: +POSIX +TODO
970+
949971
>>> p = process(['cat'])
950972
>>> p.sendline(b"meow")
951973
>>> p.recvline()
@@ -1028,7 +1050,10 @@ def get_mapping(self, path_value, single=True):
10281050
path_value.
10291051
10301052
Example:
1031-
1053+
1054+
.. doctest::
1055+
:options: +POSIX
1056+
10321057
>>> p = process(['cat'])
10331058
>>> mapping = p.get_mapping('[stack]')
10341059
>>> mapping.path == '[stack]'
@@ -1071,6 +1096,9 @@ def stack_mapping(self, single=True):
10711096
10721097
Example:
10731098
1099+
.. doctest::
1100+
:options: +POSIX
1101+
10741102
>>> p = process(['cat'])
10751103
>>> mapping = p.stack_mapping()
10761104
>>> mapping.path
@@ -1100,6 +1128,9 @@ def heap_mapping(self, single=True):
11001128
11011129
Example:
11021130
1131+
.. doctest::
1132+
:options: +POSIX
1133+
11031134
>>> p = process(['cat'])
11041135
>>> p.sendline(b'meow')
11051136
>>> p.recvline()
@@ -1132,6 +1163,9 @@ def vdso_mapping(self, single=True):
11321163
11331164
Example:
11341165
1166+
.. doctest::
1167+
:options: +LINUX
1168+
11351169
>>> p = process(['cat'])
11361170
>>> mapping = p.vdso_mapping()
11371171
>>> mapping.path
@@ -1161,6 +1195,9 @@ def vvar_mapping(self, single=True):
11611195
11621196
Example:
11631197
1198+
.. doctest::
1199+
:options: +LINUX
1200+
11641201
>>> p = process(['cat'])
11651202
>>> mapping = p.vvar_mapping()
11661203
>>> mapping.path
@@ -1191,6 +1228,9 @@ def libc_mapping(self, single=True):
11911228
11921229
Example:
11931230
1231+
.. doctest::
1232+
:options: +POSIX
1233+
11941234
>>> p = process(['cat'])
11951235
>>> p.sendline(b'meow')
11961236
>>> p.recvline()
@@ -1271,6 +1311,9 @@ def elf_mapping(self, single=True):
12711311
12721312
Example:
12731313
1314+
.. doctest::
1315+
:options: +POSIX
1316+
12741317
>>> p = process(['cat'])
12751318
>>> p.sendline(b'meow')
12761319
>>> p.recvline()
@@ -1309,7 +1352,9 @@ def lib_size(self, path_value):
13091352
13101353
Example:
13111354
1312-
>>> from pwn import *
1355+
.. doctest::
1356+
:options: +POSIX
1357+
13131358
>>> p = process(['cat'])
13141359
>>> p.send(b'meow')
13151360
>>> p.recvuntil(b'meow')
@@ -1349,6 +1394,9 @@ def address_mapping(self, address):
13491394
13501395
Example:
13511396
1397+
.. doctest::
1398+
:options: +POSIX
1399+
13521400
>>> p = process(['cat'])
13531401
>>> p.sendline(b'meow')
13541402
>>> p.recvline()
@@ -1403,16 +1451,19 @@ def libc(self):
14031451
14041452
Example:
14051453
1406-
>>> p = process("/bin/cat")
1407-
>>> p.send(b"meow")
1408-
>>> p.recvuntil(b"meow")
1409-
b'meow'
1410-
>>> libc = p.libc
1411-
>>> libc is not None
1412-
True
1413-
>>> libc # doctest: +SKIP
1414-
ELF('/lib64/libc-...so')
1415-
>>> p.close()
1454+
.. doctest::
1455+
:options: +POSIX
1456+
1457+
>>> p = process("/bin/cat")
1458+
>>> p.send(b"meow")
1459+
>>> p.recvuntil(b"meow")
1460+
b'meow'
1461+
>>> libc = p.libc
1462+
>>> libc is not None
1463+
True
1464+
>>> libc # doctest: +SKIP
1465+
ELF('/lib64/libc-...so')
1466+
>>> p.close()
14161467
"""
14171468
from pwnlib.elf import ELF
14181469

@@ -1490,6 +1541,9 @@ def leak(self, address, count=1):
14901541
14911542
Example:
14921543
1544+
.. doctest::
1545+
:options: +POSIX +TODO
1546+
14931547
>>> e = ELF(which('bash-static'))
14941548
>>> p = process(e.path)
14951549
@@ -1526,6 +1580,9 @@ def writemem(self, address, data):
15261580
15271581
Let's write data to the beginning of the mapped memory of the ELF.
15281582
1583+
.. doctest::
1584+
:options: +POSIX +TODO
1585+
15291586
>>> context.clear(arch='i386')
15301587
>>> address = 0x100000
15311588
>>> data = cyclic(32)

pwnlib/util/misc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,10 @@ def which(name, all = False, path=None):
161161
162162
Example:
163163
164-
>>> which('sh') # doctest: +ELLIPSIS +POSIX +TODO
164+
>>> which('sh') # doctest: +ELLIPSIS +POSIX
165165
'.../bin/sh'
166+
>>> which('cmd') # doctest: +ELLIPSIS +WINDOWS
167+
'...\\cmd.EXE'
166168
"""
167169
# If name is a path, do not attempt to resolve it.
168170
if os.path.sep in name:

travis/libcdb_nginx_cache.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ http {
1010
access_log /dev/stdout cache_st;
1111
# Use Docker's embedded DNS server to resolve hostnames at runtime
1212
# instead of at startup.
13-
resolver 127.0.0.11;
13+
resolver 127.0.0.11 8.8.8.8 ipv6=off;
1414

1515
server {
1616
listen 3000;

0 commit comments

Comments
 (0)