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
os.getcwd causes infinite loop on solaris #53431
Comments
os.getcwd() causes infinite loop on solaris10 when the length of the current directory is greater than 1024 (them limit of the maximum absolute path). os.getcwd is implemented by a while loop in python, see the function posix_getcwd in posixmodule.c. That while loop loops forever because on solaris it sets errno to ERANGE and res to NULL - even if there will be no positive results from getcwd due to the extra long path. I think the solution would be implementing a hard limit for this while loop. It could be either fixed (16k for example), or dymanic: comparing the MAXPATHLEN macro to the size of the allocated buffer and if the size of the buffer is greater than MAXLPATHLEN then raise an OSError exception with the current errno. That bug was triggered by test_posix unittest. |
There would be also a solution to allocate a fix buffer with MAXLPATHLEN size and call the getcwd function only one time - if MAXLPATHLEN is available. |
I've encountered this a while ago on OpenSolaris. According to the man http://docs.sun.com/app/docs/doc/816-5168/getcwd-3c?a=view this would be a bug in getcwd(): ERANGE The size argument is greater than 0 and less than the length of the |
You are right, but this bug could be easily avoided by using one of the suggested solutions. In my experience a fix sized buffer (whose size is MAXLPATHLEN - or 1024 if not defined) is usually passed to getcwd and the errno is propagated back to the caller if the result is NULL. While getcwd() is buggy on solaris I think it's not the correct behavior from python to get to an infinite loop and eat up the memory. |
I agree that there should be a workaround. In py3k the function is |
Here's a patch. If PATH_MAX is defined, a static buffer is used. I left In case anyone is mystified how to reproduce the original problem on # This worked fine: # This showed the bug: The bug could also be reproduced by creating a path name longer than Antoine, could I ask you to comment on the patch? |
I'm not sure I understand the cause of the problem. Does getcwd() fail on Solaris when the path length is higher than PATH_MAX, even if you pass a big enough buffer? First, your patch makes getcwd() return an error when the path length is longer than PATH_MAX, which it doesn't today. This is a regression and shouldn't probably go in. Second, the test_posix change is a bit too tolerant. IMO it should check that the error is ERANGE, and that we are under Solaris. Otherwise the error shouldn't happen, should it? Also, I wonder why py3k uses a simple hard-coded buffer of 1026 bytes (not even PATH_MAX+2). This is even worse than what you are proposing. I'll open a separate issue for it. |
Thanks for having a look at the patch! Antoine Pitrou <report@bugs.python.org> wrote:
If the path length exceeds PATH_MAX, getcwd() keeps returning NULL and setting ERANGE,
Hm, on Linux I can't use os.getcwd() with paths longer than PATH_MAX as things are now: $ cd /tmp/
$ for i in `seq 1 410`; do mkdir "123456789"; cd "123456789"; done
cd: error retrieving current directory: getcwd: cannot access parent directories: File name too long
$ python2.6
Python 2.6.5+ (release26-maint:81682M, Jun 6 2010, 11:22:46)
[GCC 4.1.3 20080623 (prerelease) (Ubuntu 4.1.2-23ubuntu3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getcwd()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 36] File name too long
If you change 1027 to 4098, the test currently fails on Linux, too. I think the only OSError: [Errno 36] File name too long
Good question. posix_getcwdu() also uses a buffer of 1026 in 2.7. |
Oh, right. I was assuming 1024 for PATH_MAX when doing my tests, but it
Ok, then perhaps the test should be fixed? |
Antoine Pitrou <report@bugs.python.org> wrote:
I wasn't really precise. The test fails on Linux, but for a different reason. Solaris, on the other hand, does not even raise, since it keeps setting If you prefer, of course it's possible to be conservative and make the new |
Ok. Still, silencing all OSErrors in test_posix is much too broad. The
I think this would be the most reasonable solution for 2.7, indeed. |
OpenBSD has the same getcwd() bug. It was uncovered by raising current_path_length Here is a new patch that enables the changed posix_getcwd() function So far, there are three categories of behavior if PATH_MAX is exceeded:
So FreeBSD is one of the systems that benefits from principally I think the changes in the unit test handle all categories well, |
Nice! The patch looks good to me. |
Antoine, thanks! Committed in release27-maint (r82853). Zsolt, could you confirm that bpo-9185-2.patch (or r82853) works for you? |
I confirm that test_posix passes after applying the patch bpo-9185-2.patch on solaris 8. |
Thanks for testing! - Fix also backported to release26-maint in r82975. |
New changeset bfa5d0ddfbeb by Trent Nelson in branch '2.7': |
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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: