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

imp.find_module crashes Python if there exists a directory named "__init__.py" #51981

Closed
Trundle mannequin opened this issue Jan 18, 2010 · 29 comments
Closed

imp.find_module crashes Python if there exists a directory named "__init__.py" #51981

Trundle mannequin opened this issue Jan 18, 2010 · 29 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@Trundle
Copy link
Mannequin

Trundle mannequin commented Jan 18, 2010

BPO 7732
Nosy @warsaw, @brettcannon, @doko42, @amauryfa, @ncoghlan, @orsenthil, @pitrou, @vstinner, @bitdancer, @Trundle, @florentx
Files
  • issue7732_find_module_v2.diff: Patch, apply to trunk
  • import_directory-py3k.patch
  • pyfile_fromfile_close.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/vstinner'
    closed_at = <Date 2013-08-23.19:20:34.694>
    created_at = <Date 2010-01-18.12:07:04.800>
    labels = ['library', 'type-crash']
    title = 'imp.find_module crashes Python if there exists a directory named "__init__.py"'
    updated_at = <Date 2013-08-23.19:20:34.693>
    user = 'https://github.com/Trundle'

    bugs.python.org fields:

    activity = <Date 2013-08-23.19:20:34.693>
    actor = 'pitrou'
    assignee = 'vstinner'
    closed = True
    closed_date = <Date 2013-08-23.19:20:34.694>
    closer = 'pitrou'
    components = ['Library (Lib)']
    creation = <Date 2010-01-18.12:07:04.800>
    creator = 'Trundle'
    dependencies = []
    files = ['16029', '22415', '22416']
    hgrepos = []
    issue_num = 7732
    keywords = ['patch']
    message_count = 29.0
    messages = ['98007', '98009', '98010', '98011', '98012', '98472', '98474', '98475', '98476', '98477', '102694', '102695', '102699', '102702', '110328', '113336', '138707', '138716', '144450', '144463', '144465', '144977', '147532', '147628', '190762', '191820', '195668', '195672', '196012']
    nosy_count = 14.0
    nosy_names = ['barry', 'brett.cannon', 'doko', 'amaury.forgeotdarc', 'ncoghlan', 'orsenthil', 'pitrou', 'vstinner', 'r.david.murray', 'Trundle', 'flox', 'l0nwlf', 'BreamoreBoy', 'python-dev']
    pr_nums = []
    priority = 'high'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'crash'
    url = 'https://bugs.python.org/issue7732'
    versions = ['Python 2.6', 'Python 2.7', 'Python 3.2', 'Python 3.3']

    @Trundle
    Copy link
    Mannequin Author

    Trundle mannequin commented Jan 18, 2010

    Create a directory "__init__.py" and execute

    >> import imp
    >> imp.find_module('__init__', ['.'])

    to reproduce that issue. It will crash because Python tries to double-close a file pointer: call_find_module will call PyFile_FromFile, but PyFile_FromFile closes the file pointer if it's a directory (by decrefing the created file object) and call_find_module then closes the already closed file.

    @Trundle Trundle mannequin added stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump labels Jan 18, 2010
    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Jan 18, 2010

    Confirmed on trunk.

    ~ $ mkdir foo.py
    ~ $ ./python -c 'import imp;imp.find_module("foo", ["."])'
    *** glibc detected *** ./python: double free or corruption (!prev): 0x00000000024a7390 ***
    ======= Backtrace: =========
    (...)

    @bitdancer
    Copy link
    Member

    Confirmed that this does not affect py3k.

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Jan 18, 2010

    Patch proposed.

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Jan 18, 2010

    Removed the EnvironmentVarGuard from the test. It does not make sense.

    @amauryfa
    Copy link
    Member

    This is slightly incorrect: if PyFile_FromFile fails for another reason (PyString_FromString(name) runs out of memory), the fp is not closed and the caller is right to call fclose().

    IMO PyFile_FromFile() should be changed to consistently leave the fp opened when NULL is returned. But then, many usages of this function are incorrect, e.g in posixmodule.c :-(

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Jan 28, 2010

    if PyFile_FromFile fails for another reason (PyString_FromString(name)
    runs out of memory), the fp is not closed and the caller is right to
    call fclose().

    As far as I understand, the fp is never left open, when PyFile_FromFile returns NULL. So there's no reason to call fclose on it.

    However I found a reference leak in the case you describe (PyString_FromString(name) == NULL).

    It is fixed with this last update.

    @Trundle
    Copy link
    Mannequin Author

    Trundle mannequin commented Jan 28, 2010

    Note that the fp gets set with fill_file_fields() and that is called after the error return of PyString_FromString(). Hence, the fp is left open if PyString_FromString() returns NULL.

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Jan 28, 2010

    AFAICT, in this case, if PyString_FromString gives NULL, then (o_name == NULL) and the function returns without calling "fill_file_fields".
    Hence, the fp is not opened.

    Do you suggest something else?

    @Trundle
    Copy link
    Mannequin Author

    Trundle mannequin commented Jan 28, 2010

    fill_file_fields() does not open the fp, the caller of PyFile_FromFile() opens the fp.

    I don't have a better idea, that's why I don't have provided a patch.

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Apr 9, 2010

    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Apr 9, 2010

    I can reproduce this locally. I believe it is relevant that a simple "import crash" (with crash.py as the directory) doesn't cause a problem - there must be something higher in the import machinery which avoids the issue.

    @ncoghlan ncoghlan self-assigned this Apr 9, 2010
    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Apr 9, 2010

    Ah, OK - the problem is confined solely to the wrapper for the Python imp module function. The normal import machinery doesn't go through the wrapper and hence doesn't have the problem.

    The PyFile_FromFile logic is a little convoluted, but Florent's patch looks correct. Currently, if the dircheck call in fill_file_fields fails, the function returns NULL, but leaves the file object populated (included its f_fp field). The Py_DECREF call then implicitly closes the file, resulting in a double close when call_find_module does the same thing manually.

    One other thing that is a little dubious in this code is the lack of error checking on the conversion of mode to a string object in fill_file_fields. That's fine for file_init (where mode came from a Python string object in the first place), but not valid for PyFile_FromFile (where mode is passed in as a char * instance).

    @ncoghlan ncoghlan assigned florentx and unassigned ncoghlan Apr 9, 2010
    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Apr 9, 2010

    An interesting part of this story is *why* it doesn't crash in Py3k (despite explicitly closing the file descriptor in the same way as 2.x closes the C file pointer).

    The reason is that PyFile_FromFd (the closest Py3k equivalent to PyFile_FromFile) will sometimes leave the file descriptor open, even if closefd is True. Specifically, this will happen if the raw file IO object fails to be created. Any subsequent failure while opening the file (e.g. while creating the line buffering or text wrapper) will trigger the same double close bug as occurs in 2.x.

    io_open needs to be fixed so this behaviour is consistent: if creation of the raw file IO object fails and closefd is True, io_open should close the file descriptor so that the behaviour on error is consistent.

    @BreamoreBoy
    Copy link
    Mannequin

    BreamoreBoy mannequin commented Jul 14, 2010

    Quote from ncoghlan on msg102699 "Florent's patch looks correct". Does anyone else wish to comment or can this be taken forward?

    @florentx
    Copy link
    Mannequin

    florentx mannequin commented Aug 8, 2010

    According to message http://bugs.python.org/issue7732#msg102702,
    someone should write a patch for 3.x too.

    @florentx florentx mannequin removed their assignment Aug 8, 2010
    @vstinner
    Copy link
    Member

    import_directory-py3k.patch: find_module_path_list() ignores silently directories matching requested filename pattern (like module_name + ".py"). I don't think that it is useful to emit a warning (or raise an error) here, the code checks for various file extensions, not only .pyc: .so, .pyd, ...

    @vstinner
    Copy link
    Member

    pyfile_fromfile_close.patch: patch based on issue7732_find_module_v2.diff, fixing this issue in Python 2.7

    • PyFile_FromFile() closes the file on PyString_FromString() failure (note: unlikely failure)
    • call_find_module() doesn't close the file anymore, PyFile_FromFile() closes already the file on failure (e.g. if the path is a directory)
    • update PyFile_FromFile() doc to simplify that the file is closed on error

    @warsaw
    Copy link
    Member

    warsaw commented Sep 23, 2011

    Note that Python 2.6 is also vulnerable to the crash. While we do not have an exploit, we did get a report on security@ which led to this bug. I could be convinced to allow the patch to 2.6 on grounds that if the crasher can be exploited, better to apply it now rather than wait. Certainly if it's easier to apply 2.6 and forward port, I'm fine with that.

    Victor's pyfile_fromfile_close.patch looks good to me and fixes the problem with no discernible ill effects. On IRC, he said he'll apply it to 2.7, 3.2, and 3.3. I will approve it for 2.6 if he wants to apply it there too.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Sep 23, 2011

    New changeset 125887a41a6f by Victor Stinner in branch '3.2':
    Issue bpo-7732: Don't open a directory as a file anymore while importing a
    http://hg.python.org/cpython/rev/125887a41a6f

    New changeset 8c6fea5794b2 by Victor Stinner in branch 'default':
    Merge 3.2: Issue bpo-7732: Don't open a directory as a file anymore while
    http://hg.python.org/cpython/rev/8c6fea5794b2

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Sep 23, 2011

    New changeset 0f5b64630fda by Victor Stinner in branch '2.7':
    Issue bpo-7732: Fix a crash on importing a module if a directory has the same name
    http://hg.python.org/cpython/rev/0f5b64630fda

    @pitrou
    Copy link
    Member

    pitrou commented Oct 6, 2011

    This broke the Windows buildbots in Python 2.7.

    @pitrou
    Copy link
    Member

    pitrou commented Nov 12, 2011

    Victor, can you fix the test failures on Windows and 2.7?
    Otherwise the commit should be reverted.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Nov 14, 2011

    New changeset 555871844962 by Victor Stinner in branch '2.7':
    Issue bpo-7732: Try to fix the a failing test on Windows
    http://hg.python.org/cpython/rev/555871844962

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jun 7, 2013

    New changeset bf882390713c by Brett Cannon in branch 'default':
    Issue bpo-7732: Move an imp.find_module test from test_import to
    http://hg.python.org/cpython/rev/bf882390713c

    @vstinner
    Copy link
    Member

    The test just failed on x86 Windows Server 2003 [SB] 3.x:

    http://buildbot.python.org/all/builders/x86%20Windows%20Server%202003%20%5BSB%5D%203.x/builds/1077/steps/test/logs/stdio

    ======================================================================
    FAIL: test_bug7732 (test.test_imp.ImportTests)
    ----------------------------------------------------------------------

    Traceback (most recent call last):
      File "E:\Data\buildslave\cpython\3.x.snakebite-win2k3r2sp2-x86\build\lib\test\test_imp.py", line 285, in test_bug7732
        imp.find_module, support.TESTFN, ["."])
    AssertionError: ImportError not raised by find_module

    @vstinner vstinner reopened this Jun 24, 2013
    @pitrou
    Copy link
    Member

    pitrou commented Aug 19, 2013

    The bug still fails on a regular basis on the Windows buildbots:

    ======================================================================
    FAIL: test_bug7732 (test.test_imp.ImportTests)
    ----------------------------------------------------------------------

    Traceback (most recent call last):
      File "E:\Data\buildslave\cpython\3.x.snakebite-win2k3r2sp2-x86\build\lib\test\test_imp.py", line 285, in test_bug7732
        imp.find_module, support.TESTFN, ["."])
    AssertionError: ImportError not raised by find_module

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Aug 19, 2013

    New changeset 4f7845be9e23 by Antoine Pitrou in branch 'default':
    Issue bpo-7732: try to fix test_bug7732's flakiness on Windows by executing it in a fresh temporary directory.
    http://hg.python.org/cpython/rev/4f7845be9e23

    @pitrou
    Copy link
    Member

    pitrou commented Aug 23, 2013

    Seems fixed now.

    @pitrou pitrou closed this as completed Aug 23, 2013
    @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
    stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants