Skip to content

Commit

Permalink
Change hexdump_iter to not rely on the length of its input file (#850)
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 PTY or character device (e.g. stdin or /dev/null).

Supercedes: 9c2f0f4
(cherry picked from commit 14f717b)
  • Loading branch information
zachriggle authored Jan 12, 2017
1 parent 53f041a commit 16b507e
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 16b507e

Please sign in to comment.