Bug 3871 - non-syscall getcwd() often fails with minimum buffer
Summary: non-syscall getcwd() often fails with minimum buffer
Status: NEW
Alias: None
Product: uClibc
Classification: Unclassified
Component: Other (show other bugs)
Version: 0.9.32
Hardware: PC Linux
: P5 minor
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-17 13:15 UTC by Michael Deutschmann
Modified: 2011-06-17 13:16 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments
Patch to fix non-syscall getcwd (2.01 KB, patch)
2011-06-17 13:16 UTC, Michael Deutschmann
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Deutschmann 2011-06-17 13:15:00 UTC
uClibc's non-syscall getcwd() implementation uses the buffer provided by the application as working space.  However, there are two cases where the algorithm needs more working space to determine a directory name, than to store the result.

The more common case is when the directory being searched-for has a sibling file with a longer name.  uClibc will try to stat the sibling file, and will give up if that file's full filename will not fit in the buffer.

Another case, rarely seen in practice, is if the filename has many components that are single characters (eg: "/a/a/a/a/a/a").  In this case, the "./../../.." strings used during the first part of the search can run out of space.

This causes test failures in coreutils/gnulib -- which demands that getcwd() always work if there is enough buffer for the result.

Attached is a patch that addresses these two issues.  

The sibling file problem is addressed by assuming that any too-long file isn't the searched-for directory, and then returning ERANGE if the desired inode hasn't been found after reaching the end of the parent directory.

The a/a/a/a problem is resolved by a second search using a temporary buffer that is just large enough.
Comment 1 Michael Deutschmann 2011-06-17 13:16:04 UTC
Created attachment 3403 [details]
Patch to fix non-syscall getcwd