Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

int() from a buffer reads past the buffer boundaries #69864

Closed
svenberkvens mannequin opened this issue Nov 20, 2015 · 11 comments
Closed

int() from a buffer reads past the buffer boundaries #69864

svenberkvens mannequin opened this issue Nov 20, 2015 · 11 comments
Assignees
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@svenberkvens
Copy link
Mannequin

svenberkvens mannequin commented Nov 20, 2015

BPO 25678
Nosy @vadmium, @serhiy-storchaka, @eryksun
Files
  • issue25678.patch
  • issue25678_2.patch
  • issue25678_3.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/serhiy-storchaka'
    closed_at = <Date 2015-11-20.19:58:57.453>
    created_at = <Date 2015-11-20.08:40:39.982>
    labels = ['interpreter-core', 'type-bug']
    title = 'int() from a buffer reads past the buffer boundaries'
    updated_at = <Date 2015-11-20.19:58:57.451>
    user = 'https://bugs.python.org/svenberkvens'

    bugs.python.org fields:

    activity = <Date 2015-11-20.19:58:57.451>
    actor = 'serhiy.storchaka'
    assignee = 'serhiy.storchaka'
    closed = True
    closed_date = <Date 2015-11-20.19:58:57.453>
    closer = 'serhiy.storchaka'
    components = ['Interpreter Core']
    creation = <Date 2015-11-20.08:40:39.982>
    creator = 'svenberkvens'
    dependencies = []
    files = ['41095', '41101', '41102']
    hgrepos = []
    issue_num = 25678
    keywords = ['patch']
    message_count = 11.0
    messages = ['254958', '254964', '254967', '254968', '254969', '254970', '255006', '255008', '255009', '255014', '255016']
    nosy_count = 5.0
    nosy_names = ['svenberkvens', 'python-dev', 'martin.panter', 'serhiy.storchaka', 'eryksun']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue25678'
    versions = ['Python 2.7']

    @svenberkvens
    Copy link
    Mannequin Author

    svenberkvens mannequin commented Nov 20, 2015

    Calling int() or long() on a buffer() object in Python 2.7 does not do the right thing. The following code snippet:

    buf = buffer("123test", 1, 2)
    print buf
    print int(buf)

    does not do what I would expect (that it print "23" twice). Instead, it prints "23" once and then throws an exception:

    ValueError: invalid literal for int() with base 10: '23test'

    This is caused by Objects/abstract.c function int_from_string(), which gets passed the length of the string but does not actually use that information to limit what part is parsed from the string. It only uses it to check for embedded NUL bytes. The real culprit is probably PyInt_FromString() which does not take a length indicator.

    @svenberkvens svenberkvens mannequin added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels Nov 20, 2015
    @serhiy-storchaka
    Copy link
    Member

    This is similar to bpo-24802. The patch for bpo-24802 was not backported to 2.7 because affected functions don't accept memoryview in Python 2. Now we have an example, and can backport that patch.

    @eryksun
    Copy link
    Contributor

    eryksun commented Nov 20, 2015

    Now we have an example, and can backport that patch.

    More seriously it's possible to get a buffer over-read using NumPy:

        >>> import numpy
        >>> int(buffer(numpy.array('123', dtype='c')))
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
         ValueError: invalid literal for int() with base 10: '123\xe1\x18\x7f'

    I backported the modification to PyNumber_Int and PyNumber_Long, using PyString_FromStringAndSize and PyString_AS_STRING. It works as expected:

        Python 2.7.10+ (2.7:5d88c1d413b9+, Nov 20 2015, 04:58:55) 
        [GCC 4.8.4] on linux2
        Type "help", "copyright", "credits" or "license" for more 
        information.
        >>> int(buffer('123test', 1, 2))
        23
        [41951 refs]
        >>> long(buffer('123test', 1, 2))
        23L
        [41952 refs]

    @serhiy-storchaka
    Copy link
    Member

    Do you forgot to add a patch?

    @eryksun
    Copy link
    Contributor

    eryksun commented Nov 20, 2015

    I just made a quick modification to check that it works. I'm sure you could do the same. But here it is anyway.

    @serhiy-storchaka
    Copy link
    Member

    Could you backport full patch, with tests? And compile() is affected too:

    >>> compile(buffer("123\0test", 1, 2), '', 'exec')
    <code object <module> at 0xb70c5800, file "", line 1>
    >>> compile(buffer("123test", 1, 2), '', 'exec')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: compile() expected string without null bytes

    @svenberkvens
    Copy link
    Mannequin Author

    svenberkvens mannequin commented Nov 20, 2015

    Eryk, could the tests in the path file that you posted regarding int() and float() be incorrect in the sense that buffer(...)[a:b] returns a str() and not another buffer() (and will thus always be NUL terminated and not exhibit the problem, whether or not the C source have been patch)? I think the tests should be using buffer(..., a, b) instead.

    May I say that I am very, very impressed by the speed with which this has been picked up? Thank you all for your impressive work!

    @svenberkvens
    Copy link
    Mannequin Author

    svenberkvens mannequin commented Nov 20, 2015

    (Please excuse my horrible spelling in my last message, I'm apparently more tired than I care to admit)

    @eryksun
    Copy link
    Contributor

    eryksun commented Nov 20, 2015

    I think the tests should be using buffer(..., a, b) instead.

    Thanks, you're right. :)

    @serhiy-storchaka serhiy-storchaka self-assigned this Nov 20, 2015
    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Nov 20, 2015

    New changeset 3ef7d1af5195 by Serhiy Storchaka in branch '2.7':
    Issue bpo-25678: Copy buffer objects to null-terminated strings.
    https://hg.python.org/cpython/rev/3ef7d1af5195

    @serhiy-storchaka
    Copy link
    Member

    Committed after fixing some details. Thank you Eryk Sun.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants