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

Buffer overflow when listing deeply nested directory #45320

Closed
sonderblade mannequin opened this issue Aug 17, 2007 · 15 comments
Closed

Buffer overflow when listing deeply nested directory #45320

sonderblade mannequin opened this issue Aug 17, 2007 · 15 comments
Labels
OS-windows type-bug An unexpected behavior, bug, or error

Comments

@sonderblade
Copy link
Mannequin

sonderblade mannequin commented Aug 17, 2007

BPO 1776160
Nosy @benjaminp, @serhiy-storchaka, @eryksun, @ZackerySpytz

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 = None
closed_at = <Date 2020-05-14.21:21:04.585>
created_at = <Date 2007-08-17.11:24:22.000>
labels = ['type-bug', 'OS-windows']
title = 'Buffer overflow when listing deeply nested directory'
updated_at = <Date 2020-05-14.21:21:04.584>
user = 'https://bugs.python.org/sonderblade'

bugs.python.org fields:

activity = <Date 2020-05-14.21:21:04.584>
actor = 'benjamin.peterson'
assignee = 'none'
closed = True
closed_date = <Date 2020-05-14.21:21:04.585>
closer = 'benjamin.peterson'
components = ['Windows']
creation = <Date 2007-08-17.11:24:22.000>
creator = 'sonderblade'
dependencies = []
files = []
hgrepos = []
issue_num = 1776160
keywords = []
message_count = 15.0
messages = ['32647', '32648', '32649', '32650', '32651', '32652', '175102', '175104', '175105', '175108', '175114', '224324', '340965', '340998', '368868']
nosy_count = 6.0
nosy_names = ['sonderblade', 'benjamin.peterson', 'serhiy.storchaka', 'eryksun', 'arno-cs', 'ZackerySpytz']
pr_nums = []
priority = 'low'
resolution = 'wont fix'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue1776160'
versions = ['Python 2.7']

@sonderblade
Copy link
Mannequin Author

sonderblade mannequin commented Aug 17, 2007

This code:

import os
import os.path
TARGET='C:/code/python/foo'
base = TARGET
for x in range(200):
    subdirs = os.listdir(base)
    base = os.path.join(base, subdirs[0])
    print base

Produces a TypeError (buffer overflow) when run on a to deeply nested directory for windows to handle:

.. more output here..
C:code/python/foo\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.p
ng\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png\foo bar.png
Traceback (most recent call last):
  File "killdir.py", line 6, in <module>
    subdirs = os.listdir(base)
TypeError: listdir() argument 1 must be (buffer overflow), not str

@sonderblade sonderblade mannequin added OS-windows labels Aug 17, 2007
@smontanaro
Copy link
Contributor

Worked as expected for me on Mac OS X 10.4.10 running from
the trunk (you didn't mention what version you were using).
In ~/tmp/deep I created a maximally nested directory tree from the shell like so:

cd /Users/skip/tmp/deep
for i in `range 1000` ; do
    x=`printf %04d $i`
    echo $x
    mkdir $x
    cd $x
done

where the range command is analogous to Python's range
builtin:

% range 20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

The for loop barfed after making directory 0205.

In Python I then executed these statements:

    import os.path
    base = "/Users/skip/tmp/deep"
    for x in range(210):
        subdirs = os.listdir(base)
        base = os.path.join(base, subdirs[0])
        print base

This went until it got to dir 0200 where it raised an
OSError:

[Errno 63] File name too long: '/Users/skip/tmp/deep/0000/0001/.../0199/0200'

which stands to reason since base was 1025 characters long
at that point. MAXPATHLEN is defined to be 1024 on my
system, so the OSError is to be expected.

Skip

@loewis
Copy link
Mannequin

loewis mannequin commented Aug 21, 2007

To rephrase Skip's comment: Can you please report what operating system and Python version you are using?

@sonderblade
Copy link
Mannequin Author

sonderblade mannequin commented Aug 21, 2007

Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32
MS Windows XP, Version 5.1, SP2

@loewis
Copy link
Mannequin

loewis mannequin commented Aug 22, 2007

Can you please explain what specifically you consider a bug here?

I can see that the error message is confusing, so it could be improved. However, there is nothing we can do to make the error go away. The Microsoft C library simply does not support file names longer than MAX_PATH; you have to use Unicode file names to go beyond this limit.

@sonderblade
Copy link
Mannequin Author

sonderblade mannequin commented Aug 22, 2007

Yes, it is the error message and the exception that is the problem. First, it shouldn't raise TypeError (which indicates a programming error), it should raise either IOError, OSError or WindowsError. Second, the exception message is whacky: "listdir() argument 1 must be (buffer overflow), not str" I realize that it is probably impossible to detect this specific error condition but I still want something more explanatory than what it currently is.

@devdanzin devdanzin mannequin added type-bug An unexpected behavior, bug, or error labels Apr 7, 2009
@arno-cs
Copy link
Mannequin

arno-cs mannequin commented Nov 7, 2012

Can somebody please look at this bug? It still appears in SCons 2.2.0 on Windows 7 when it tries to do a os.listdir on

C:\Program Files\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;\build\libevent-2.0.20-stable-debug\include;\build\libevent-2.0.20-stable-debug\WIN32-Code;\build\gtest-1.4.0\include;

@serhiy-storchaka
Copy link
Member

Can you please report what Python version you are using?

@arno-cs
Copy link
Mannequin

arno-cs mannequin commented Nov 7, 2012

This is on Python 2.7.3 on Win7 32-bit, sorry.

@serhiy-storchaka
Copy link
Member

This issue is related to parsing of "et#" format which is used only in listdir() and _getfullpathname() under Windows. PyArg_ParseTuple() throws TypeError exception for multiple conversion errors (in this case it is an overflow of a static buffer). There are several ways to solve this issue:

  1. Do nothing, close the issue as "wont fix". This is just the wrong exception in a very rare case only on 2.7 and only under Windows. The issue will go away with 2.7.

  2. Use under Windows dynamic buffer as under other platforms. This will require not only dynamic memory allocation, but also reallocation for "\*.*" appending.

  3. Do not use PyArg_ParseTuple(). Parse the singular argument manually.

  4. If PyArg_ParseTuple() fails then check if the raised exception is TypeError and the error message matches "(buffer overflow)". In this case raise the right exception.

  5. Rewrite PyArg_ParseTuple() so that it will raise an appropriate type of exception (this will have to do anyway, but maybe later, in other issue). In this case it will be OverflowError. Then we can catch this error and raise the right exception.

Martin, what is your decision?

@serhiy-storchaka
Copy link
Member

See also bpo-4071.

@BreamoreBoy
Copy link
Mannequin

BreamoreBoy mannequin commented Jul 30, 2014

I suggest we close this as "won't fix" since I don't see how we can justify spending time working around a known limitation of Windows.

@serhiy-storchaka
Copy link
Member

Benjamin, what of the proposed options do you prefer?

@eryksun
Copy link
Contributor

eryksun commented Apr 27, 2019

In Windows 7, FindFirstFileA uses a per-thread static buffer to decode the input bytes path to Unicode. This buffer limits the length to 259 characters (MAX_PATH - 1), even if a "\\?\" device path is used. Windows 8+ uses a dynamic buffer, but I don't see the point of switching to a dynamic buffer on our side given Windows 7 is still so widely used and the documentation still requires Unicode for long "\\?\" paths.

Ideally, I think 2.7 should raise the same exception as 3.5 does in this case 1. For example:

    >>> os.listdir(long_bytes_path)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: listdir: path too long for Windows

@ZackerySpytz
Copy link
Mannequin

ZackerySpytz mannequin commented May 14, 2020

Python 2 is EOL.

@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
OS-windows type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants