Closed Bug 286702 Opened 20 years ago Closed 20 years ago

[FIXr]###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI, &loadingData) && loadingData == aLoadData', file r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486

Categories

(Core :: CSS Parsing and Computation, defect, P1)

x86
Windows XP
defect

Tracking

()

RESOLVED FIXED
mozilla1.8beta2

People

(Reporter: timeless, Assigned: bzbarsky)

References

(Blocks 1 open bug)

Details

(Keywords: assertion)

Attachments

(2 files, 3 obsolete files)

###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI,
&loadingData) && loadingData == aLoadData', file
r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486

+
{,,necko.dll}((*(nsACString*)(&(*(nsCSubstring*)(&(*(nsStandardURL*){*}(((*aLoadData).mURI).mRawPtr)).mSpec))))).mData
0x011790e0 "file:///css/homepage_import_rc.css"	char *
+	aLoadData	0x035d4d88 {mRefCnt={mValue=0x00000003 }
_mOwningThread={mThread=0x003f5198 } mLoader=0x01aaf320
{mRefCnt={mValue=0x00000003 } _mOwningThread={mThread=0x003f5198 }
gParsers=0x019caa50 ...} ...}	SheetLoadData *
	aLoadData->mIsLoading	0x01 '␁'	unsigned char
+	loadingData	0x00000000 {mRefCnt={mValue=??? } _mOwningThread={mThread=??? }
mLoader=??? ...}	SheetLoadData *
-	mLoadingDatas	{...}	nsDataHashtable<nsURIHashKey,SheetLoadData *>
\-	nsBaseHashtable<nsURIHashKey,SheetLoadData *,SheetLoadData *>	{...}
nsBaseHashtable<nsURIHashKey,SheetLoadData *,SheetLoadData *>
 \-	nsTHashtable<nsBaseHashtableET<nsURIHashKey,SheetLoadData *> >
{mTable={ops=0x0269a654 sOps data=0x00000000 hashShift=0x001c ...} }
nsTHashtable<nsBaseHashtableET<nsURIHashKey,SheetLoadData *> >
  \-	mTable	{ops=0x0269a654 sOps data=0x00000000 hashShift=0x001c ...}	PLDHashTable
   |+	ops	0x0269a654 sOps	const PLDHashTableOps *
   |	data	0x00000000	void *
   |	hashShift	0x001c	short
   |	maxAlphaFrac	0xc0 'À'	unsigned char
   |	minAlphaFrac	0x40 '@'	unsigned char
   |	entrySize	0x0000000c	unsigned int
   |	entryCount	0x00000001	unsigned int
   |	removedCount	0x00000000	unsigned int
   |	generation	0x00000000	unsigned int
   \+	entryStore	0x0356f2d8 ""	char *
	aSucceeded	0x00000000	int

	aStatus	0x80520001	unsigned int /*NS_ERROR_FILE_UNRECOGNIZED_PATH*/

 	xpcom_core.dll!nsDebugImpl::Assertion(const char * aStr=0x025ae8f0, const char
* aExpr=0x025ae8a0, const char * aFile=0x025ae878, int aLine=0x000005ce)  Line
301	C++
 	xpcom_core.dll!nsDebug::Assertion(const char * aStr=0x025ae8f0, const char *
aExpr=0x025ae8a0, const char * aFile=0x025ae878, int aLine=0x000005ce)  Line 109	C++
>	gklayout.dll!CSSLoaderImpl::SheetComplete(SheetLoadData *
aLoadData=0x035d4d88, int aSucceeded=0x00000000)  Line 1486 + 0x41	C++
 	gklayout.dll!SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader *
aLoader=0x0349ee88, nsISupports * aContext=0x00000000, unsigned int
aStatus=0x80520001, nsIUnicharInputStream * aDataStream=0x00000000)  Line 791	C++
 	xpcom_core.dll!XPTC_InvokeByIndex(nsISupports * that=0x035d4d88, unsigned int
methodIndex=0x00000004, unsigned int paramCount=0x00000004, nsXPTCVariant *
params=0x0349eef0)  Line 102	C++
 	xpcom_core.dll!EventHandler(PLEvent * self=0x034c6e70)  Line 563 + 0x29	C++
 	xpcom_core.dll!PL_HandleEvent(PLEvent * self=0x034c6e70)  Line 698 + 0xa	C
 	xpcom_core.dll!PL_ProcessPendingEvents(PLEventQueue * self=0x0114a280)  Line
633 + 0x9	C
 	xpcom_core.dll!_md_EventReceiverProc(HWND__ * hwnd=0x007d15be, unsigned int
uMsg=0x0000c1d6, unsigned int wParam=0x00000000, long lParam=0x0114a280)  Line
1435 + 0x9	C
 	user32.dll!_InternalCallWinProc@20()  + 0x28	
 	user32.dll!_UserCallWinProcCheckWow@32()  + 0xb7	
 	user32.dll!_DispatchMessageWorker@8()  + 0xdc	
 	user32.dll!_DispatchMessageA@4()  + 0xf	
 	mfc71d.dll!AfxInternalPumpMessage()  Line 188	C++
 	mfc71d.dll!CWinThread::PumpMessage()  Line 916	C++
 	mfc71d.dll!CWinThread::Run()  Line 637 + 0xb	C++
 	mfc71d.dll!CWinApp::Run()  Line 701	C++
 	mfc71d.dll!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ *
hPrevInstance=0x00000000, char * lpCmdLine=0x00142384, int nCmdShow=0x0000000a)
 Line 49 + 0xb	C++
 	mfcembed.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ *
hPrevInstance=0x00000000, char * lpCmdLine=0x00142384, int nCmdShow=0x0000000a)
 Line 25	C++
 	mfcembed.exe!WinMainCRTStartup()  Line 390 + 0x39	C
 	kernel32.dll!_BaseProcessStart@4()  + 0x23	

i was using file>open to load http://www.macromedia.com, windows automatically
downloads just the text/html file to a temporary internet files folder, but
doesn't do things like fix up paths, so something asked for
/css/homepage_import_rc.css as a stylesheet and got poorly reparented. not sure
what other special bits it took to do this.
Blocks: 286705
Please let me know if this is reproducible and what the steps to reproduce are....
Assignee: bzbarsky → nobody
Attachment #178304 - Attachment description: www.macromedia[1].com → www.macromedia[1].com bug 286704
this assert will trigger if the file is saved to disk as something like '0.xml'
or '0.html'.

i can't think of a way to trigger this testcase using bugzilla. i tried the
foopy protocol, and it didn't work :(, it triggered something which mrbkap says
is probably bug 243338 / bug 84582.
Attached patch Proposed patch (obsolete) — Splinter Review
Darin, the problem is that when trying to convert the URI "file:///foo/bar"
(note lack of drive letter) to an nsIFile on Windows, we get an exception. 
This can happen in various other ways too, for resource: and file:// URIs.

So what this patch does is to compare the strings if EnsureFile fails in an
indentical way on both URIs...
Assignee: nobody → bzbarsky
Status: UNCONFIRMED → ASSIGNED
Attachment #178323 - Flags: superreview?(darin)
Attachment #178323 - Flags: review?(darin)
Severity: minor → major
Priority: -- → P1
Summary: ###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI, &loadingData) && loadingData == aLoadData', file r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486 → [FIX]###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI, &loadingData) && loadingData == aLoadData', file r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486
Target Milestone: --- → mozilla1.8beta2
Attachment #178323 - Flags: superreview?(darin)
Attachment #178323 - Flags: review?(darin)
Attached patch Same, but compiling (obsolete) — Splinter Review
Attachment #178323 - Attachment is obsolete: true
Attachment #178325 - Flags: superreview?(darin)
Attachment #178325 - Flags: review?(darin)
Comment on attachment 178325 [details] [diff] [review]
Same, but compiling

>Index: netwerk/base/src/nsStandardURL.cpp

>+        if (rv != rv2) {
>+            if (NS_FAILED(rv))
>+                LOG(("nsStandardURL::Equals [this=%p spec=%s] failed to "
>+                     "ensure file",
>+                     this, mSpec.get()));
>+
>+            if (NS_FAILED(rv2))
>+                LOG(("nsStandardURL::Equals [other=%p spec=%s] other failed "
>+                     "to ensure file",
>                 other, other->mSpec.get()));
>+
>+            // Claim mismatch, but also propagate the error we got
>+            *result = PR_FALSE;
>+            return NS_FAILED(rv) ? rv : rv2;
>         }

The if checks and LOG statements should probably be wrapped in a #ifdef
PR_LOGGING since we don't #define FORCE_PR_LOG in this file.  Wouldn't
some sort of NS_WARNING be better than LOG in these cases?  Or, are there
legit cases where EnsureFile would fail?

Also, there's no reason to set *result if the method is going to throw
an exception.  Doing so is inconsistent with other exit points from the
method, so I think you shouldn't bother setting *result here.
Attachment #178325 - Flags: superreview?(darin)
Attachment #178325 - Flags: superreview+
Attachment #178325 - Flags: review?(darin)
Attachment #178325 - Flags: review+
I was thinking about this some more, and I really feel that returning error for
"reasonable" failures in EnsureFile (eg invalid file path, pointing to
nonexistent resource mapping, etc) seems wrong.

Darin thinks we should avoid creating such URIs at all (throw from newURI).  I'm
not sure how we can do that, exactly, unless we plan to basically duplicate all
the checks all platform nsLocalFile impls do (and this is just for file:// URIs;
resource: URIs are a separate story altogether).

So what do people think is a reasonable course of action here?
Summary: [FIX]###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI, &loadingData) && loadingData == aLoadData', file r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486 → [FIXr]###!!! ASSERTION: Bad loading table: 'mLoadingDatas.Get(aLoadData->mURI, &loadingData) && loadingData == aLoadData', file r:/mozilla/layout/style/nsCSSLoader.cpp, line 1486
If the URI is really malformed, then sure we should throw at newURI. But for a
missing resource: mapping, I think we should go as long as possible (similarly
for a missing chrome package or a non-existent file: URI drive letter): the
resource mapping could be added in the future; we shouldn't fail until
absolutely necessary.

Unless I'm misunderstanding the question.
The question is twofold:

1)  Should we allow such URIs to exist?
2)  How should Equals() should for such URIs?  Right now it just throws, which is
    highly suboptimal in all cases where URIs are used as cache keys, since such
    a URI tests unequal to itself, basically.
It is easy to check that file:///home/foo is invalid under windows, so we should
perform that check in the URL parsers that get invoked as part of NewURI.

I guess that still leaves plenty of other interesting failure cases for EnsureFile.

But, at least for resource:// and chrome://, straight up string comparisons is
probably fine in the absence of actual files to compare.

So, I think we should just make sure that we aren't doing stupid things like
comparing file:///home/FOO/ to file:///home/foo/ and so on.
file:///home/foo is a valid url and that does not depend on the OS. It just does
not translate to a local file on windows. I see no reason to not create the url.
The URLParsers should not be bothered with this OS dependend stuff (it was a big
task to clean them up years ago), for those we have the converters to local
files.   
Well, we have a lot of other XP_WIN specific code in nsURLParsers.cpp:
http://lxr.mozilla.org/seamonkey/source/netwerk/base/src/nsURLParsers.cpp#404

Hmm... I suppose I could live with constructing nsIURIs from broken file:// URLs
on windows.  Anyways, we need to be smart in Equals to handle other cases where
EnsureFile returns failure, so we might as well lump this case in with those.  Ok.
So perhaps we need two functions... EnsureFile(), and TryFile() (bad name, but
no better ideas so far).  The latter will be implemented by the same subclass
that implements EnsureFile and convert error codes that correspond to "not a
valid file" errors to NS_OK.

That said, if we do that we'll end up with file:///home/foo and file:///home/FOO
being compared as strings on Windows.  But I think that's reasonable...
I'd really like to get some agreement on this and move forward... As things
stand, it's pretty easy to trigger leaks and/or crashes in any consumer that
uses an nsIURI as a hash key (and we have plenty of those).
Flags: blocking1.8b2?
Attached patch Proposed patch (obsolete) — Splinter Review
I think this patch is money.  It does the right thing for clearly identical
URIs, and does its best for the rest.
Attachment #178325 - Attachment is obsolete: true
Attachment #181314 - Flags: superreview?(darin)
Attachment #181314 - Flags: review?(cbiesinger)
Comment on attachment 181314 [details] [diff] [review]
Proposed patch

+    // First, check whether both URIs are nsIFileURLs.

hm... that comments is confusing... what the if really checks is if one is a
file url and the other isn't. the nsIFiles are checked much later...

+ since conversion to file will
+	 // ignore the host!

maybe that should get a bug filed on?

+	 !SegmentIs(mPassword, other->mSpec.get(), other->mPassword) ||
+	 (Port() != other->Port());
+	 !SegmentIs(mParam, other->mSpec.get(), other->mParam)) {

uh... what's the semicolon in the port line doing here? (how does this
compile?)
Attachment #181314 - Flags: review?(cbiesinger) → review+
> uh... what's the semicolon in the port line doing here?

Hangin' out?  ;)  That in fact does not compile; I thought I'd checked, but I
checked in the wrong tree.
Attachment #181314 - Attachment is obsolete: true
Attachment #181324 - Flags: superreview?(darin)
Attachment #181314 - Flags: superreview?(darin) → superreview-
> 
> + since conversion to file will
> +	 // ignore the host!
> 
> maybe that should get a bug filed on?
> 

The host in a file url is somewhat redundant. It can only be localhost or the
local hostnamne, because the file protocol is by definition a local protocol.
Most of the time the hostname is already dropped from the url, but if it is
present it can savely be ignored because file://host1/path/file is the same as
file://host2/path/file on the local box. 

UNC-paths in file-urls are *paths* with network access, the host is still localhost.
So two file URLs that point to the same file but have different hosts should
test equal?  Note that that's not what the patch implements, but it'd not be
hard to fix...
It is somewhat more complex because there are certain malformed file-urls
possible, like having only two slashes but still having no host like
file://path/file. I think we handle this (or have handled this) by moving the
host into the path-component if parsed as host. Sometimes an UNC path is given
as file://host/path/file when it should have been file://///host/path/file. How
to know what is meant? There is not 100% solution I know of. I think the host
can be savely ignored comparing file urls ... unless it is a malformed UNC path
file-url mentioned above for example. We just can't be sure, so I have to
recommend against ignoring it, just to be on the save side.
So wait.  Are there cases when the Host() of the nsStandardURL would be
different and:

1)  The two URIs should be treated as different, and both resolve to the same
    file
or
2)  The two URIs should be treated as the same and one of the two doesn't resolve
    to a file (or both don't).

In other words, in that diff, should Host() be with the filename/extension/path,
or with scheme/ref/query ?
Isn't that fun? At the level of the nsStandardUrl we simply don't know in all
cases. That said, if the url is not malformed, everything is fine, the host can
be ignored. But in certain malformed cases, part of the path ends up as host.
This is only resolved (if even possible), if memory serves correctly, while
converting to a local file. 
Usually the host is empty but if not I would put it for file urls with
filename/extension/path. I think this needs some testing with all those strange
border/malformed cases. 
> But in certain malformed cases, part of the path ends up as host.

Ah, I see.  Yeah, in that case we just want to move the Host() check to the
other condition.
Flags: blocking1.8b2? → blocking1.8b2+
In(In reply to comment #21)
> It is somewhat more complex because there are certain malformed file-urls
> possible, like having only two slashes but still having no host like
> file://path/file. I think we handle this (or have handled this) by moving the
> host into the path-component if parsed as host.

No, we preserve the host in this case.  Try it for yourself ;-)

Loading file://foo/home/darin in the browser shows me my home directory!

The one special case is "file://c:/Windows", and during URL normalization, this
will get converted to "file:///c:/Windows".  By the time, EnsureFile is called,
the URL spec should already be normalized.


> Sometimes an UNC path is given
> as file://host/path/file when it should have been file://///host/path/file. 
> How
> to know what is meant? There is not 100% solution I know of. I think the host
> can be savely ignored comparing file urls ... unless it is a malformed UNC path
> file-url mentioned above for example. We just can't be sure, so I have to
> recommend against ignoring it, just to be on the save side.

This is all hypothetical.  Our implementation does very few fancy things with
malformed file URLs.  We could do a better job of guessing that the user really
meant a UNC path, but we do not.
Comment on attachment 181324 [details] [diff] [review]
Compiling and all

>Index: netwerk/base/src/nsStandardURL.cpp

>+    // At this point, the URIs are not identical, but they only differ in the
>+    // directory/filename/extension.  If these are file URLs, then get the
>+    // corresponding file objects and compare those, since two filenames that
>+    // differ, eg, only in case could still be equal.
>     if (mSupportsFileURL) {
>         // Assume not equal for failure cases... but failures in GetFile are
>+        // really failures, more or less, so propagate them to caller.
>         *result = PR_FALSE;
>         
>         rv = EnsureFile();
>         if (NS_FAILED(rv)) {
>             LOG(("nsStandardURL::Equals [this=%p spec=%s] failed to ensure file",
>                 this, mSpec.get()));
>             return rv;
>         }
>         NS_ASSERTION(mFile, "EnsureFile() lied!");
>         rv = other->EnsureFile();
>         if (NS_FAILED(rv)) {
>             LOG(("nsStandardURL::Equals [other=%p spec=%s] other failed to ensure file",
>                 other, other->mSpec.get()));
>             return rv;
>         }
>         NS_ASSERTION(other->mFile, "EnsureFile() lied!");
>         return mFile->Equals(other->mFile, result);
>     }

So, this block could be #if defined(XP_WIN) || defined(XP_OS2), right?
Afterall, for unix filesystems this is not required.


>+    // Not file URIs and not identical, so these are different.

I'm having trouble parsing this sentence.  What? ;-)
> So, this block could be #if defined(XP_WIN) || defined(XP_OS2), right?

Maybe... I'd really rather avoid building assumptions like that into this code
if I can avoid it, but it's your call.

> I'm having trouble parsing this sentence.  What? ;-)

The two URIs are not identical, and they're not file URIs.  So Equals() should
test false.  For file URIs, it can test true even if they're not identical
because of the case-folding stuff.  I suppose I could write this out in more
detail... ;)
Comment on attachment 181324 [details] [diff] [review]
Compiling and all

>+    // Not file URIs and not identical, so these are different.

I get it now.  How about this instead:

  // The URLs are not identical, and they do not correspond to the
  // same file, so they are different.


sr=darin (the #ifdef'ing of that EnsureFile block is optional, and
maybe you have a compelling reason for why we want it on UNIX and
other systems -- e.g., because of error checking?)
Attachment #181324 - Flags: superreview?(darin) → superreview+
Mostly I want it on in general because it makes us easier to port... It's not
obvious to me what should be happening even for OSX, much less other things we
may want to run on sometime so I'd really rather leave it to the system nsIFile
impl unconditionally.
Comment on attachment 181324 [details] [diff] [review]
Compiling and all

Requesting approval for this fix... Should make CSSLoader, at least, happier.
Attachment #181324 - Flags: approval1.8b2?
note that you can run linux w/ fat(16/32), osx of course is generally only case
preserving (not case sensitive), plus you could have a fun remote file system
which plays by those rules (and yes, i really do all these things, including
case sensitive ntfs, case sensitive HFSX on osx, and random file sharing among
arbitrary os's including hosting mozilla on the wrong volume or os)
Comment on attachment 181324 [details] [diff] [review]
Compiling and all

a=brendan for 1.8b2.

/be
Attachment #181324 - Flags: approval1.8b2? → approval1.8b2+
(In reply to comment #31)
> note that you can run linux w/ fat(16/32), osx of course is generally only case
> preserving (not case sensitive), plus you could have a fun remote file system
> which plays by those rules (and yes, i really do all these things, including
> case sensitive ntfs, case sensitive HFSX on osx, and random file sharing among
> arbitrary os's including hosting mozilla on the wrong volume or os)

timeless: if you wish to write code to do a 'proper' file comparison for
nsLocalFileUnix, then by all means.
Fixed (with the comment change)
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: