internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: Gallopsled/pwntools

Issue:
Raise AttributeError when closing a socket
I want pwnlib to listen on a port, but when I close the socket it raise AssertionError.

Here's my code:
```python
from pwnlib import tubes
import os

p = tubes.listen.listen(1337, "127.0.0.1")

os.system("nohup curl 127.0.0.1:1337/start123end >/dev/null 2>/dev/null &")

print(p.recvregex(b"start([\s\S]+)end"))

p.close()
```

And here's the error message: 
```
Exception in thread Thread-1 (accepter):
Traceback (most recent call last):
  File "/usr/lib64/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/lib64/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/listen.py", line 129, in accepter
    self.settimeout(self.timeout)
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py", line 1186, in settimeout
    self.timeout = timeout
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/timeout.py", line 146, in timeout
    assert not self._stop
AssertionError
b'GET /start123end'
Traceback (most recent call last):
  File "THE PYTHON SCRIPT ABOVE", line 10, in <module>
    p.close()
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/listen.py", line 177, in close
    super(listen, self).close()
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/sock.py", line 173, in close
    self._close_msg()
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/sock.py", line 176, in _close_msg
    self.info('Closed connection to %s port %d', self.rhost, self.rport)
  File "MYHOME/.local/lib/python3.10/site-packages/pwnlib/tubes/listen.py", line 170, in __getattr__
    return getattr(super(listen, self), key)
AttributeError: 'super' object has no attribute 'rhost'. Did you mean: 'lhost'?

```


Discussion:
You need to call `listen.wait_for_connection()` before using the listen socket, otherwise the accepter thread isn't joined. I guess the docs could use some improving, if you're down.

```python
from pwnlib import tubes
import os

p = tubes.listen.listen(1337, "127.0.0.1")

os.system("nohup curl 127.0.0.1:1337/start123end >/dev/null 2>/dev/null &")

p.wait_for_connection()
print(p.recvregex(b"start([\s\S]+)end"))

p.close()
```

Resolving patch:
diff --git a/pwnlib/tubes/listen.py b/pwnlib/tubes/listen.py
--- a/pwnlib/tubes/listen.py
+++ b/pwnlib/tubes/listen.py
@@ -13,7 +13,8 @@
 
 class listen(sock):
     r"""Creates an TCP or UDP-socket to receive data on. It supports
-    both IPv4 and IPv6.
+    both IPv4 and IPv6. You need to call :meth:`wait_for_connection`
+    before using the listen socket.
 
     The returned object supports all the methods from
     :class:`pwnlib.tubes.sock` and :class:`pwnlib.tubes.tube`.
@@ -46,6 +47,7 @@ class listen(sock):
         >>> # and it works with ipv6 by defaut, too!
         >>> l = listen()
         >>> r = remote('::1', l.lport)
+        >>> _ = l.wait_for_connection()
         >>> r.sendline(b'Bye-bye')
         >>> l.recvline()
         b'Bye-bye\n'


Test patch:
Repository: Gallopsled/pwntools

Issue:
`_need_text` not working for none str types
When logging, `_need_text` is called.
If the param is a bytes instance, it will be decoded twice, thus throwing an Exception (and a warning as well).
For other types eg int, calling its `decode` method will also throw Exceptions.

IMHO this method should either check the param type explicitly, or use `repr` on the param 



Discussion:

Resolving patch:
diff --git a/pwnlib/util/packing.py b/pwnlib/util/packing.py
--- a/pwnlib/util/packing.py
+++ b/pwnlib/util/packing.py
@@ -441,7 +441,7 @@ def make_packer(word_size = None, sign = None, **kwargs):
 def make_unpacker(word_size = None, endianness = None, sign = None, **kwargs):
     """make_unpacker(word_size = None, endianness = None, sign = None,  **kwargs) -> str → number
 
-    Creates a unpacker by "freezing" the given arguments.
+    Creates an unpacker by "freezing" the given arguments.
 
     Semantically calling ``make_unpacker(w, e, s)(data)`` is equivalent to calling
     ``unpack(data, w, e, s)``. If word_size is one of 8, 16, 32 or 64, it is however
@@ -836,7 +836,7 @@ def dd(dst, src, count = 0, skip = 0, seek = 0, truncate = False):
     values from offset `seek` in `src` to offset `skip` in `dst`.  If `count` is
     0, all of ``src[seek:]`` is copied.
 
-    If `dst` is a mutable type it will be updated.  Otherwise a new instance of
+    If `dst` is a mutable type it will be updated.  Otherwise, a new instance of
     the same type will be created.  In either case the result is returned.
 
     `src` can be an iterable of characters or integers, a unicode string or a
@@ -1035,6 +1035,9 @@ def _need_text(s, level=1):
     if isinstance(s, (str, six.text_type)):
         return s   # already text
 
+    if not isinstance(s, (bytes, bytearray)):
+        return repr(s)
+
     encoding = context.encoding
     errors = 'strict'
     if encoding == 'auto':


Test patch:
Repository: Gallopsled/pwntools

Issue:
Dumpable raw array
Currently, when I add to a `ROP` object an array with `rop.raw([a1,a2])`, I can't run `rop.dump()` on the object and just get the error `Don't know how to dump [a1, a2]`. However, it's able to dump objects individually added with `raw()` just fine.

```python
# this can be dumped with lookups
rop.raw(gadget)
rop.raw(a1)
rop.raw(a2)
rop.raw(a3)

# this can't be dumped at all
rop.raw([gadget,a1,a2,a3])
```

I believe it should be easy to make array entries dumpable by adding them in a manner similar to adding individual raw objects. I want arrays added with `raw()` to be dumpable.


Discussion:

Resolving patch:
diff --git a/pwnlib/rop/rop.py b/pwnlib/rop/rop.py
--- a/pwnlib/rop/rop.py
+++ b/pwnlib/rop/rop.py
@@ -1167,6 +1167,15 @@ def find_gadget(self, instructions):
             if tuple(gadget.insns)[:n] == tuple(instructions):
                 return gadget
 
+    def _flatten(self, initial_list):
+        # Flatten out any nested lists.
+        flattened_list = []
+        for data in initial_list:
+            if isinstance(data, (list, tuple)):
+                flattened_list.extend(self._flatten(data))
+            else:
+                flattened_list.append(data)
+        return flattened_list
 
     def raw(self, value):
         """Adds a raw integer or string to the ROP chain.
@@ -1174,14 +1183,18 @@ def raw(self, value):
         If your architecture requires aligned values, then make
         sure that any given string is aligned!
 
+        When given a list or a tuple of values, the list is
+        flattened before adding every item to the chain.
+
         Arguments:
-            data(int/bytes): The raw value to put onto the rop chain.
+            data(int/bytes/list): The raw value to put onto the rop chain.
 
         >>> context.clear(arch='i386')
         >>> rop = ROP([])
         >>> rop.raw('AAAAAAAA')
         >>> rop.raw('BBBBBBBB')
         >>> rop.raw('CCCCCCCC')
+        >>> rop.raw(['DDDD', 'DDDD'])
         >>> print(rop.dump())
         0x0000:          b'AAAA' 'AAAAAAAA'
         0x0004:          b'AAAA'
@@ -1189,10 +1202,16 @@ def raw(self, value):
         0x000c:          b'BBBB'
         0x0010:          b'CCCC' 'CCCCCCCC'
         0x0014:          b'CCCC'
+        0x0018:          b'DDDD' 'DDDD'
+        0x001c:          b'DDDD' 'DDDD'
         """
         if self.migrated:
             log.error('Cannot append to a migrated chain')
-        self._chain.append(value)
+
+        if isinstance(value, (list, tuple)):
+            self._chain.extend(self._flatten(value))
+        else:
+            self._chain.append(value)
 
     def migrate(self, next_base):
         """Explicitly set $sp, by using a ``leave; ret`` gadget"""


Test patch:
Repository: Gallopsled/pwntools

Issue:
readthedocs.org builds are broken
The docs fail to build for a while, but differently since https://github.com/Gallopsled/pwntools/pull/2179. They're still built using Python 2.7, which had problems installing rpyc and is now missing the toml package before running the setup.py.

https://readthedocs.org/projects/pwntools/builds/

You could switch to Python 3 or try adding the `toml; python_version<'3.4'` package to the `docs/requirements.txt` file for a starter? I think only a maintainer with access to the configs can fix this.


Discussion:

Resolving patch:
diff --git a/pwn/toplevel.py b/pwn/toplevel.py
--- a/pwn/toplevel.py
+++ b/pwn/toplevel.py
@@ -16,7 +16,6 @@
 import threading
 import time
 
-import colored_traceback
 from pprint import pprint
 
 import pwnlib
@@ -85,7 +84,12 @@
 debug   = log.debug
 success = log.success
 
-colored_traceback.add_hook()
+try:
+    import colored_traceback
+except ImportError:
+    pass
+else:
+    colored_traceback.add_hook()
 
 # Equivalence with the default behavior of "from import *"
 # __all__ = [x for x in tuple(globals()) if not x.startswith('_')]


Test patch:
Repository: Gallopsled/pwntools

Issue:
CI: Python 2 runner image removed
Python 2 tests are broken atm. Switch tests to a container?

https://github.com/actions/setup-python/issues/672#issuecomment-1589120020


Discussion:
+1 for a container ([should be quite easy](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-a-docker-hub-action) / [method 2](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-running-a-job-within-a-container))

Resolving patch:
diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py
--- a/pwnlib/libcdb.py
+++ b/pwnlib/libcdb.py
@@ -217,7 +217,7 @@ def unstrip_libc(filename):
         >>> libc = ELF(filename)
         >>> hex(libc.symbols.main_arena)
         '0x219c80'
-        >>> unstrip_libc(which('python'))
+        >>> unstrip_libc(which('python3'))
         False
         >>> filename = search_by_build_id('d1704d25fbbb72fa95d517b883131828c0883fe9', unstrip=True)
         >>> 'main_arena' in ELF(filename).symbols
diff --git a/pwnlib/tubes/ssh.py b/pwnlib/tubes/ssh.py
--- a/pwnlib/tubes/ssh.py
+++ b/pwnlib/tubes/ssh.py
@@ -1151,10 +1151,10 @@ def system(self, process, tty = True, wd = None, env = None, timeout = None, raw
 
         Examples:
             >>> s =  ssh(host='example.pwnme')
-            >>> py = s.run('python -i')
+            >>> py = s.run('python3 -i')
             >>> _ = py.recvuntil(b'>>> ')
             >>> py.sendline(b'print(2+2)')
-            >>> py.sendline(b'exit')
+            >>> py.sendline(b'exit()')
             >>> print(repr(py.recvline()))
             b'4\n'
             >>> s.system('env | grep -a AAAA', env={'AAAA': b'\x90'}).recvall()


Test patch:
Repository: Gallopsled/pwntools

Issue:
context.log_level = 100 still shows corefile parsing errors
Pwntools Version: 4.2.1

If `context.log_level = 100;` is set, one would expect all output to be hidden.

When `core = io.corefile;` is run and the corefile fails to parse, a message is still output, even though you set the output level to 100

`[!] Error parsing corefile stack: Found bad environment at 0x7ffcef1fffb7`

From the debug log

```
2020-08-24T20:16:07:DEBUG:pwnlib.elf.corefile:Trying corefile_path: '/home/reelix/thm/anonymousplayground/core'
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:Parsing corefile...
2020-08-24T20:16:07:WARNING:pwnlib.elf.corefile:Error parsing corefile stack: Found bad environment at 0x7fff2f902fb7
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:'/tmp/tmp19mma2o3'
Arch:      amd64-64-little
RIP:       0x40070f
RSP:       0x7fff2f901a88
Exe:       '/home/reelix/thm/anonymousplayground/file.elf' (0x400000)
Fault:     0x6161617461616173
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:Parsing corefile...: Done
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:Parsing corefile...
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:'/home/reelix/thm/anonymousplayground/core.634721'
Arch:      amd64-64-little
RIP:       0x40070f
RSP:       0x7fff2f901a88
Exe:       '/home/reelix/thm/anonymousplayground/file.elf' (0x400000)
Fault:     0x6161617461616173
2020-08-24T20:16:07:INFO:pwnlib.elf.corefile:Parsing corefile...: Done
```


Discussion:

Resolving patch:
diff --git a/pwnlib/elf/corefile.py b/pwnlib/elf/corefile.py
--- a/pwnlib/elf/corefile.py
+++ b/pwnlib/elf/corefile.py
@@ -530,7 +530,6 @@ class Corefile(ELF):
         >>> io = elf.process()
         >>> io.wait(2)
         >>> core = io.corefile
-        [!] End of the stack is corrupted, skipping stack parsing (got: 41414141)
         >>> core.argc, core.argv, core.env
         (0, [], {})
         >>> core.stack.data.endswith(b'AAAA')
@@ -666,7 +665,7 @@ def __init__(self, *a, **kw):
                     log.warn('Could not find the stack!')
                     self.stack = None
 
-            with context.local(bytes=self.bytes, log_level='warn'):
+            with context.local(bytes=self.bytes):
                 try:
                     self._parse_stack()
                 except ValueError:


Test patch:
Repository: Gallopsled/pwntools

Issue:
Cannot get output of pwnlib.adb.packages()
Sorry if this question is a bit daft, but I'm having some issues trying to work out how to read the output of `pwnlib.adb.packages()`.

Looking at the code it should be returning an array of values, however no matter how I handle it I get the error:

`a bytes-like object is required, not 'str'`

Is anybody able to assist?



Discussion:
That function appears to have been missed while updating for Python 3 compatiblilty. Would you be willing to fix this in a PR?

Resolving patch:
diff --git a/pwnlib/adb/adb.py b/pwnlib/adb/adb.py
--- a/pwnlib/adb/adb.py
+++ b/pwnlib/adb/adb.py
@@ -1591,7 +1591,10 @@ def uninstall(package, *arguments):
 @context.quietfunc
 def packages():
     """Returns a list of packages installed on the system"""
-    packages = process(['pm', 'list', 'packages']).recvall()
+    # Decodes the received bytes as UTF-8 per:
+    # https://developer.android.com/reference/java/nio/charset/Charset#defaultCharset()
+    # where it is specified that UTF-8 is the default charset for Android.
+    packages = process(['pm', 'list', 'packages']).recvall().decode('utf-8')
     return [line.split('package:', 1)[-1] for line in packages.splitlines()]
 
 @context.quietfunc


Test patch:
Repository: Gallopsled/pwntools

Issue:
Do not overwrite global `bytes` in code or examples
It looks like there's a few places we overwrite `bytes` (the type identifier) with a local variable.

```
$ git grep -E -e '^ +bytes *=' -- '*.py'
pwnlib/commandline/disasm.py:81:        bytes   = disasm(dat, vma=safeeval.const(args.address), instructions=False, offset=False)
pwnlib/commandline/elfpatch.py:29:    bytes  = unhex(a.bytes)
pwnlib/elf/elf.py:195:    bytes = 4
```

And a few cases we do it in tests, which could have cross-test impact if the global state isn't reset (hint: it isn't).

```
~/pwntools $ git grep -E -e '^ +>>> bytes *=' -- '*.py'
pwnlib/runner.py:42:        >>> bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
pwnlib/runner.py:48:        >>> bytes = asm('mov r0, #12; mov r7, #1; svc #0', arch='arm')
pwnlib/runner.py:87:        >>> bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
```


Discussion:

Resolving patch:
diff --git a/pwnlib/runner.py b/pwnlib/runner.py
--- a/pwnlib/runner.py
+++ b/pwnlib/runner.py
@@ -39,14 +39,14 @@ def run_shellcode(bytes, **kw):
 
     Example:
 
-        >>> bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
-        >>> p = run_shellcode(bytes)
+        >>> insn_bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
+        >>> p = run_shellcode(insn_bytes)
         >>> p.wait_for_close()
         >>> p.poll()
         3
 
-        >>> bytes = asm('mov r0, #12; mov r7, #1; svc #0', arch='arm')
-        >>> p = run_shellcode(bytes, arch='arm')
+        >>> insn_bytes = asm('mov r0, #12; mov r7, #1; svc #0', arch='arm')
+        >>> p = run_shellcode(insn_bytes, arch='arm')
         >>> p.wait_for_close()
         >>> p.poll()
         12
@@ -84,8 +84,8 @@ def run_shellcode_exitcode(bytes):
 
     Example:
 
-        >>> bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
-        >>> run_shellcode_exitcode(bytes)
+        >>> insn_bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;')
+        >>> run_shellcode_exitcode(insn_bytes)
         3
     """
     p = run_shellcode(bytes)


Test patch:
Repository: Gallopsled/pwntools

Issue:
ROP.find_stack_adjustment() is missing a return value
```python
def find_stack_adjustment(self, slots):
    self.search(move=slots * context.bytes)
```

`self.search()` just returns a `Gadget` and does not modify the ROP `self`. So the function `find_stack_adjustment()` actually does nothing.

Perhaps a `return` needs to be added.


Discussion:

Resolving patch:
diff --git a/pwnlib/rop/rop.py b/pwnlib/rop/rop.py
--- a/pwnlib/rop/rop.py
+++ b/pwnlib/rop/rop.py
@@ -1037,10 +1037,6 @@ def build(self, base = None, description = None):
 
         return stack
 
-
-    def find_stack_adjustment(self, slots):
-        self.search(move=slots * context.bytes)
-
     def chain(self, base=None):
         """Build the ROP chain
         


Test patch:
Repository: Gallopsled/pwntools

Issue:
Incorrect parsing of the mips plt section
$ uname -a
Linux debian 5.10.0-11-amd64 # 1 SMP Debian 5.10.92-1 (2022-01-18) x86_64 GNU/Linux
Pwntools version: 4.7.0
Target binary: https://ropemporium.com/challenge/ret2csu.html  (ret2csu_mipsel)

Here's the problems:
1) e.plt contains only two functions
```
>>> for key in e.plt:
...     print(f"{key} : {hex(e.plt[key])}")
... 
ret2win : 0x400a5c
__libc_start_main : 0x400a6c
```
But it missing `pwnme` plt entry. Also, docker image with pwntools 4.6.0 has emtpy plt dictionary 

2) Addresses of plt entries are invalid. They all lower for 4bytes than needed (Should be `0x00400a60`, but pwntools show `0x400a5c`)

3) Maybe symbols interpreted as functions because e.symbols[<plt_entry>] points to the location to that e.symbols[plt.<plt_entry>] should be pointing


Discussion:

Resolving patch:
diff --git a/pwnlib/elf/plt.py b/pwnlib/elf/plt.py
--- a/pwnlib/elf/plt.py
+++ b/pwnlib/elf/plt.py
@@ -119,18 +119,6 @@ def prepare_unicorn_and_context(elf, got, address, data):
 
         uc.mem_write(got, p_magic)
 
-        # Separately, Unicorn is apparently unable to hook unmapped memory
-        # accesses on MIPS.  So we also have to map the page that contains
-        # the magic address.
-        start = magic_addr & (~0xfff)
-        try:
-            uc.mem_map(start, 0x1000)
-        except Exception:
-            # Ignore double-mapping
-            pass
-        trap = packing.p32(0x34000000, endian=elf.endian)
-        uc.mem_write(magic_addr, trap)
-
     return uc, uc.context_save()
 
 
diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py
--- a/pwnlib/libcdb.py
+++ b/pwnlib/libcdb.py
@@ -217,7 +217,7 @@ def unstrip_libc(filename):
         >>> libc = ELF(filename)
         >>> hex(libc.symbols.main_arena)
         '0x219c80'
-        >>> unstrip_libc(which('python3'))
+        >>> unstrip_libc(pwnlib.data.elf.get('test-x86'))
         False
         >>> filename = search_by_build_id('d1704d25fbbb72fa95d517b883131828c0883fe9', unstrip=True)
         >>> 'main_arena' in ELF(filename).symbols


Test patch:
Repository: Gallopsled/pwntools

Issue:
Some binary files cause `context.quiet` to affect the global scope.
The tested libc is download from https://github.com/niklasb/libc-database

## Update Pwntools First

using latest commit

<img width="690" alt="image" src="https://github.com/Gallopsled/pwntools/assets/46804083/7dce65f8-5ae0-446d-8e9c-3c574ea65d0a">

## Debug Output

DEBUG output:
<img width="1029" alt="image" src="https://github.com/Gallopsled/pwntools/assets/46804083/a1ff1be6-bf69-4a88-9b61-e1784e7cdecb">

But when not using DEBUG, use ELF() load the target libc causes `context.quiet` to affect the global scope.
<img width="1037" alt="image" src="https://github.com/Gallopsled/pwntools/assets/46804083/76f7153b-099e-4ad3-9455-8379b2608bcf">

## Test Code

testing on the following code

```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import ipdb

safe = "./libc6_2.13-20ubuntu5.2_i386.so"
target = "./libc6-x32_2.30-0ubuntu2_i386.so"

# load target libc
print("[test0] context.log_level: ", context.log_level)
ELF(target, checksec=False)
print("[test0] context.log_level: ", context.log_level)

# load safe libc in context.quiet
print("[test1] context.log_level: ", context.log_level)
with context.quiet:
    ELF(safe, checksec=False)
print("[test1] context.log_level: ", context.log_level)

# load target libc in context.quiet
print("[test2] context.log_level: ", context.log_level)
with context.quiet:
    ELF(target, checksec=False)
print("[test2] context.log_level: ", context.log_level)
```

## Example File


[attachment.zip](https://github.com/Gallopsled/pwntools/files/13455763/attachment.zip)




Discussion:

Resolving patch:
diff --git a/pwnlib/context/__init__.py b/pwnlib/context/__init__.py
--- a/pwnlib/context/__init__.py
+++ b/pwnlib/context/__init__.py
@@ -787,7 +787,7 @@ def arch(self, arch):
         try:
             defaults = self.architectures[arch]
         except KeyError:
-            raise AttributeError('AttributeError: arch must be one of %r' % sorted(self.architectures))
+            raise AttributeError('AttributeError: arch (%r) must be one of %r' % (arch, sorted(self.architectures)))
 
         for k,v in defaults.items():
             if k not in self._tls:
diff --git a/pwnlib/elf/elf.py b/pwnlib/elf/elf.py
--- a/pwnlib/elf/elf.py
+++ b/pwnlib/elf/elf.py
@@ -460,6 +460,7 @@ def _describe(self, *a, **kw):
     def get_machine_arch(self):
         return {
             ('EM_X86_64', 64): 'amd64',
+            ('EM_X86_64', 32): 'amd64', # x32 ABI
             ('EM_386', 32): 'i386',
             ('EM_486', 32): 'i386',
             ('EM_ARM', 32): 'arm',


Test patch: