Skip to content

tell() is incorrect after read_bytes() #426

Closed

Description

@eddyashton

Using the default ._cmsgpack implementation of an Unpacker, you will get the wrong answer if you call tell() after read_bytes(). Here's a simple repro:

import msgpack
from io import BytesIO
buf = BytesIO(b'my data')
u = msgpack.Unpacker(buf)
print(u.tell())
u.read_bytes(5)
print(u.tell())

After calling u.read_bytes(5), u.tell() will still return 0. It looks like the stream_offset in _unpacker.pyx should be advanced in read_bytes(), but is currently only advanced by _unpack().

Note that this works correctly in the .fallback implementation, so a quick workaround is to use import msgpack.fallback as msgpack, but I assume this is much slower than the C implementation.

Activity

  1. jfolz commented on Jun 4, 2020

    @jfolz
    Contributor

    Kinda embarrassing, since I implemented tell, but never explicitly documented what it was actually supposed to do. Intuitively it's meant to work like tell on a file-like to give the position of the object that the Unpacker returns next.

    import msgpack
    from io import BytesIO
    b = msgpack.packb([2,3])
    u = msgpack.Unpacker(BytesIO(b))
    u.read_bytes(1)
    print(next(u), u.tell())
    b = msgpack.packb(4) + msgpack.packb(5)
    u = msgpack.Unpacker(BytesIO(b))
    print(next(u), u.tell())
    print(next(u), u.tell())
    

    This prints 2 1, so we skipped the array header (1 byte) and unpack the first item instead (1 byte). We should now be at position 2.
    Then it prints 4 1 and 5 2, so tell is behaving as expected as long as read_bytes is not used.

    AFAIK adding stream_offset += len(ret) here should fix this. read_bytes reads directly from the buffer (and the file-like if needed), but doesn't advance the stream_offset.

  2. added 2 commits that reference this issue on Jun 4, 2020
    a2a8e76
    e4d75e2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions