Repository navigation
fix(packing): dd() raises TypeError on a bytearray destination - #2772
Conversation
dd() documents bytearray as a supported destination type, but
dd(bytearray(b'Hello!'), b'?', skip=5) raises
"TypeError: 'bytes' object cannot be interpreted as an integer".
pwnlib/util/packing.py:1108 handled list and bytearray destinations in a
single branch and filled both with list(map(p8, bytearray(src))). p8()
returns a length-1 bytes object, which is what a list destination is
documented to hold (see the existing dd(list('Hello!'), (63,), skip=5)
doctest), but a bytearray slice assignment needs an iterable of int, so
every bytearray destination crashed.
Assign the byte string src directly when the destination is a bytearray.
Every src branch above the destination dispatch (packing.py:1039-1089)
has already reduced src to a byte string, so the slice assignment is
always valid. This also makes a bytearray destination agree with the
bytes and str destinations, which already copy src verbatim.
Add a doctest covering the returned value and the in-place update of the
caller's bytearray.
|
The three failing test jobs fail in The Python 2.7 job is the one that ran the doctest suite to completion. In it, Those three examples are the exact ones 86cafce marked |
dd()listsbytearrayamong its supported destination types, and has an explicitisinstance(dst, ..., bytearray)branch for it, but everybytearraydestination raisesTypeErroron 4.15.0.The cause is the shared
list/bytearraybranch atpwntools/pwnlib/util/packing.py
Lines 1107 to 1108 in 7e5e79d
list(map(p8, bytearray(src))).p8()returns a length-1bytesobject, which is exactly what alistdestination is documented to hold, as the neighbouringdd(list('Hello!'), (63,), skip = 5)doctest shows. Abytearrayslice assignment needs an iterable ofint, so it rejects thosebytesobjects. The other four destination types all work:list,tuple,bytesandstrreturn['H', 'e', 'l', 'l', 'o', b'?'],('H', 'e', 'l', 'l', 'o', b'?'),b'Hello?'and'Hello?'respectively.The fix assigns the byte string
srcdirectly when the destination is abytearray. Everysrcbranch above the destination dispatch, at packing.py:1039-1089, has already reducedsrcto a byte string, so the slice assignment is always valid, and this makes abytearraydestination agree with thebytesandstrdestinations, which already copysrcverbatim.dd(bytearray(b'Hello!'), b'?', skip=5)now returnsbytearray(b'Hello?')and updates the caller's buffer in place, which is what the "Ifdstis a mutable type it will be updated" contract in the docstring promises.Testing
The new doctest in the
dd()docstring covers both the returned value and the in-place update. Run the way CI runs it, on the touched module only:Reverting only the one-line code change and keeping the new doctest gives
69 passed and 2 failed, withTypeError: 'bytes' object cannot be interpreted as an integerondd(buf, b'?', skip = 5)andbytearray(b'Hello!')instead ofbytearray(b'Hello?')on the follow-up check, so the doctest is a real regression test rather than a restatement of the new behaviour.flake8 . --count --select=E9,F63,F7,E71 --show-source --statistics --exclude=android-?dkreports0, andpylint --exit-zero --errors-only pwnlib/util/packing.py -f parseableproduces output identical tostableat 7e5e79d, so the PyLint job sees no new errors. Ran on macOS 15 with Python 3.11.9 and Sphinx 8.2.3.Target Branch
This targets
stablebecause the crash is present in the released 4.15.0 and inbetaanddevas well, which the PR template maps to astablebug fix.