Closed Bug 332389 Opened 20 years ago Closed 19 years ago

nsLocalFile::GetParent() doesn't return nsnull at top of volume

Categories

(Core :: XPCOM, defect)

PowerPC
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: jwkbugzilla, Assigned: jwkbugzilla)

Details

(Keywords: regression)

Attachments

(2 files, 3 obsolete files)

I was investigating why my extension would hang when traversing upwards through the directory tree. It came out that on Mac OS X nsIFile.parent always returns a value, even on top of the volume (I was testing with Firefox 1.5 on Mac OS X 10.3, but this code hasn't been touched in a while, so the problem should occur on trunk as well). This is a regression, bug 133617 refers to this issue as fixed. Execute the following code on Mac OS X: var file = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); file.initWithPath("/"); alert(file.parent.path) This will show: /.. That's clearly not what it should be, see also comment in nsLocalFile::GetParent (http://lxr.mozilla.org/mozilla/source/xpcom/io/nsLocalFileOSX.cpp#1058). There should be an exception because file.parent should be null in this case. It seems that CFURLCreateCopyDeletingLastPathComponent doesn't return null on top of volume after all (I couldn't find any documentation stating what the return value of this function should be in such a case). My hack to work around this problem was to break out of the loop when path is "/". But I think this should somehow be fixed in Gecko as well...
Summary: nsLocalFile::GetParent() doen't return nsnull at top of volume → nsLocalFile::GetParent() doesn't return nsnull at top of volume
http://darwinsource.opendarwin.org/10.4.2/CF-368.11/URL.subproj/CFURL.c looks like CFURLCreateCopyDeletingLastPathComponent only returns NULL if the CFURL is a network URL with no path component.
Robert, thanks for pointing me into the right direction. The way I read this code it will almost always do what we need (remove the last path component). The exceptions are the paths "", ".", ".." and "/" where it adds two dots. Since nsLocalFile cannot have relative paths, only the last case is problematic. We could add a special check for this case and return nsnull if mBaseRef is "/". A more general solution might be comparing the length of parentURLRef with the length of mBaseRef - we should only return a value if the former is smaller. I am tending towards the second solution, the first one might be broken by changes in the Darwin code. The problem is - I cannot compile Firefox on a Mac. If I write a patch, will you be able to test/review it?
(In reply to comment #2) > > If I write a patch, will you be able to test/review it? I touched this file last, so it should be kosher to do r=sayrer? / sr=bsmedberg?, so we get module owner approval.
Attached patch Proposed patch (obsolete) — Splinter Review
This will make the method only accept the result of CFURLCreateCopyDeletingLastPathComponent if it is shorter than what we had before - an increase in length indicates that there is no parent. I will also attach a diff with -w to make reviewing easier.
Assignee: nobody → trev
Status: NEW → ASSIGNED
Attachment #256466 - Flags: superreview?
Attachment #256466 - Flags: review?(sayrer)
Attachment #256466 - Flags: superreview? → superreview?(benjamin)
Attached patch Same patch with -w (obsolete) — Splinter Review
Comment on attachment 256467 [details] [diff] [review] Same patch with -w >Index: nsLocalFileOSX.cpp > > } >+ } Indent the nested block, please.
Attachment #256467 - Flags: review+
Comment on attachment 256467 [details] [diff] [review] Same patch with -w oops, wrong patch.
Attachment #256467 - Flags: review+
Attachment #256466 - Flags: review?(sayrer) → review+
Comment on attachment 256466 [details] [diff] [review] Proposed patch I'm increasingly thinking that we should replace most of the guts of nsLocalFileOSX with nsLocalFileUnix. In any case, I defer to Josh as mac guru.
Attachment #256466 - Flags: superreview?(benjamin) → review?(joshmoz)
Comment on attachment 256466 [details] [diff] [review] Proposed patch Symlinks aren't getting resolved, but if they were then parent paths could potentially be longer than their children. To be safe, let's check for "/" as in addition to the path length check.
Attachment #256466 - Flags: review?(joshmoz) → review-
I don't see a point in checking for "/" *in addition* - we know that this path cannot have a parent, right? So if you are sure that this will always be the only problematic case then we can simply check for "/" and return nsnull here.
Attached patch Patch v2, Comparing path with / (obsolete) — Splinter Review
This is untested again - I cannot compile on a Mac.
Attachment #256466 - Attachment is obsolete: true
Attachment #256467 - Attachment is obsolete: true
Attachment #257643 - Flags: review?(joshmoz)
This is the same as the first patch, plus a warning fix. I like the first patch better afterall.
Attachment #257643 - Attachment is obsolete: true
Attachment #257711 - Flags: review+
Attachment #257643 - Flags: review?(joshmoz)
There were also trailing CRs in the first patch, mine gets rid of that.
Patch v1 w/warning fix landed on trunk.
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
Flags: in-testsuite?
Attached file xpcshell testcase
Proposed /mozilla/xpcom/tests/unit/test_bug332389.js file - tests whether following the .parent chain terminates.
Attachment #257957 - Flags: review?(joshmoz)
Wladimir - how do you run that test?
Same way you run all xpcshell tests -- drop it in the location mentioned, do a |make| in xpcom/tests so that it gets propagated to the right locations in the objdir, and then run |make check| in xpcom/tests in your objdir.
That doesn't seem to be working in this case. I don't see any results.
Odd -- works for me. However, when looking at the test I see: for (var i = 0; i < 100; i++) { if (f == null) { terminated = true; break; } try { f = f.parent } catch (e) { // Exception means we reached the top of a volume, terminate f = null; } } f.parent throwing an exception is not expected behavior. When f is the top directory, f.parent should be null and not throw, and on relooping the null will be detected and the test will pass. The try/catch is unnecessary -- just do |f = f.parent;| directly (and do include the semicolon).
Comment on attachment 257957 [details] xpcshell testcase I got it working now. Thanks!
Attachment #257957 - Flags: review?(joshmoz) → review+
test checked in
Flags: in-testsuite? → in-testsuite+
Could you remove the try/catch and add the semicolon, please, per comment 19?
try/catch removed, semicolon added, checked in
Jeff, exception is the expected behavior on Windows. This test isn't Mac only. Now if you think that GetParent on Windows shouldn't throw an exception feel free to file a bug. Josh, please check in the original patch, with the try/catch.
I've reverted the test to the original version, per comment 24.
(In reply to comment #24) > Jeff, exception is the expected behavior on Windows. The IDL documentation for nsIFile flatly contradict this, mentioning nothing about accessing the attribute throwing any exceptions and explicitly stating that |f.parent == null| when |f| represents the topmost directory: http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/xpcom/io/nsIFile.idl&rev=1.63&mark=324-327#320 I filed bug 373640 to fix this issue.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: