Skip to content

Commit

Permalink
Change hexdump_iter to not rely on the length of its input file
Browse files Browse the repository at this point in the history
We cannot determine the length of the file if passed e.g. a tube or a pipe or
or PTY or character device (e.g. stdin or /dev/null).

Supercedes: 9c2f0f4
(cherry picked from commit 14f717b)
  • Loading branch information
zachriggle committed Jan 12, 2017
1 parent 9c2f0f4 commit aa385c2
Showing 1 changed file with 20 additions and 23 deletions.
43 changes: 20 additions & 23 deletions pwnlib/util/fiddling.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ..context import context
from ..log import getLogger
from ..term import text
from .cyclic import cyclic
from .cyclic import de_bruijn
from .cyclic import cyclic_find

log = getLogger(__name__)
Expand Down Expand Up @@ -560,13 +560,15 @@ def _hexiichar(c):
}

cyclic_pregen = ''
de_bruijn_gen = de_bruijn()

def sequential_lines(a,b):
return (a+b) in cyclic_pregen

def update_cyclic_pregenerated(size):
global cyclic_pregen
cyclic_pregen = cyclic(size)
while size > len(cyclic_pregen):
cyclic_pregen += de_bruijn_gen.next()

def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
highlight=None, cyclic=False):
Expand Down Expand Up @@ -609,23 +611,6 @@ def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
spacer = ' '
marker = (style.get('marker') or (lambda s:s))('│')

# Total length of the input stream
total = 0

if hasattr(fd, 'len'):
total = fd.len
else:
# Save the current file offset
cur = fd.tell()

# Determine the total size of the file
fd.seek(0, os.SEEK_END)
total = fd.tell() - cur

# Restore the file offset, and
fd.seek(cur or 0, os.SEEK_SET)


if hexii:
column_sep = ''
line_fmt = '%%(offset)08x %%(hexbytes)-%is│' % (len(column_sep)+(width*byte_width))
Expand All @@ -645,17 +630,29 @@ def style_byte(b):
return hbyte, abyte
cache = [style_byte(chr(b)) for b in range(256)]

if cyclic:
update_cyclic_pregenerated(total)

numb = 0
while True:
offset = begin + numb
chunk = fd.read(width)

# If a tube is passed in as fd, it will raise EOFError when it runs
# out of data, unlike a file or StringIO object, which return an empty
# string.
try:
chunk = fd.read(width)
except EOFError:
chunk = ''

# We have run out of data, exit the loop
if chunk == '':
break

# Advance the cursor by the number of bytes we actually read
numb += len(chunk)

# Update the cyclic pattern in case
if cyclic:
update_cyclic_pregenerated(numb)

# If this chunk is the same as the last unique chunk,
# use a '*' instead.
if skip and last_unique:
Expand Down

0 comments on commit aa385c2

Please sign in to comment.