Closed Bug 1240013 Opened 9 years ago Closed 9 years ago

Crash in nsNavBookmarks::OnVisit by setting long location.hash

Categories

(Toolkit :: Places, defect)

39 Branch
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla47
Tracking Status
firefox44 --- wontfix
firefox45 + fixed
firefox46 + fixed
firefox47 + fixed

People

(Reporter: pvtolkien, Assigned: mak)

References

Details

(Keywords: crash, regression, reproducible)

Crash Data

Attachments

(1 file, 1 obsolete file)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0 Build ID: 20160105164030 Steps to reproduce: location.hash=new Array(10000000).join("A") Actual results: Firefox crashed Expected results: Give an error for invalid URL.
CR FF46: https://crash-stats.mozilla.com/report/index/e2256adf-0acd-4982-8f81-0903e2160115 It didn't crash in the past, even if the browser was hanging during generating the array but the console was able to display the result. reg range: https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=fd8e079d6335&tochange=58c9d079f318 Reporter, do you have a crash report ID in about:crashes?
Crash Signature: [@ nsNavBookmarks::OnVisit ]
Flags: needinfo?(pvtolkien)
Summary: Crash by setting loooong location.hash → Crash in nsNavBookmarks::OnVisit by setting long location.hash
Severity: normal → critical
Keywords: crash, reproducible
Version: 43 Branch → 39 Branch
Sorry for the delay, I was AFK. (In reply to Loic from comment #1) > CR FF46: > https://crash-stats.mozilla.com/report/index/e2256adf-0acd-4982-8f81- > 0903e2160115 > > It didn't crash in the past, even if the browser was hanging during > generating the array but the console was able to display the result. > You can avoid the output from console adding a ",1": location.hash=new Array(10000000).join("A"),1 > reg range: > https://hg.mozilla.org/mozilla-central/ > pushloghtml?fromchange=fd8e079d6335&tochange=58c9d079f318 > > Reporter, do you have a crash report ID in about:crashes? Sure: https://crash-stats.mozilla.com/report/index/076adbe3-6ae3-4396-904e-516952160118 I could test for Firefox and Firefox Nightly on Linux 64bits and OSX, and all of them seem to crash.
Flags: needinfo?(pvtolkien)
Seems the crash reports related to nsNavBookmarks::OnVisit are in a solid number in the last few days. Based on crash report details, assigning issue to
Status: UNCONFIRMED → NEW
Component: Untriaged → XUL
Ever confirmed: true
Product: Firefox → Core
Component: XUL → Places
Product: Core → Toolkit
I'll see if I can figure out something
Assignee: nobody → mak77
So, it's sort-of a regression caused by Bug 1135354. That bug is doing the right thing, but some consumers are not properly checking the return value of NS_NewURI, that now returns an error if a spec is longer than 1MB. So we can have a dereference crash if the nsIURI is used without the rv being checked.
Blocks: 1135354
Status: NEW → ASSIGNED
Keywords: regression
Ok, after a tedious debugging session I think I figured out something. What I noticed was that some nsIURI was larger than the limit set by Bug 1135354. I also noticed that often I had other nsIURI with the same content (host#AAAA...) but length 65536. Looks like in some cases "something" is already limiting uri size to 65536. I don't know what yet, could be xpidl or something else. That may explain why we didn't notice many crashes due to large uris even before Bug 1135354? Btw, this is uninteresting for this bug since these cropped nsIURIs won't crash. I had no luck figuring where the cut happens. But, the most interesting thing, is when instead we end up with an nsIURI that is larger than the limit set by Bug 1135354. In all those cases the stack had IPC in the middle. So what I found is that when we serialize and deserialize URIs through IPC we call nsStandardURL::Deserialize. nsStandardURL::Deserialize does this: mSpec = params.spec(); No length check! So, I guess we have our culprit, we deserialize an uri that is too long, we build a good nsIURI, but if later we extract the spec and rebuild an nsIURI, it will fail. So, 2 things: 1. We always assumed we could trust that if we got a spec from nsIURI we could rebuild an nsIURI from it. Looks like it's fragile to assume that, so here I will add checks to Places around NS_NewURI wherever we avoided them in the past. 2. nsStandardURL::Deserialize should check length! This is worrisome, I wonder if other methods can bypass the SetSpec check, like if something changes just the ref or the schema with a very long string, looks like we can again end up into this situation? Patrick, you reviewed the change in bug 1135354, what do you think we should do, just add a length check to Deserialize? How can we test that?
Flags: needinfo?(mcmanus)
the length check makes sense to me, but valentin is the defacto owner of the url code..
Flags: needinfo?(mcmanus) → needinfo?(valentin.gosu)
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric https://reviewboard.mozilla.org/r/31951/#review28697 Works for me, but I'd appreciate a little more documentation, since there are new silent semi-failures. ::: toolkit/components/places/History.cpp:757 (Diff revision 1) > - (void)NS_NewURI(getter_AddRefs(referrerURI), mPlace.referrerSpec); > + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_NewURI(getter_AddRefs(referrerURI), mPlace.referrerSpec))); If `referrerURI == nullptr`, shouldn't we also call `HandleError`? Otherwise, could you document why we can just drop it? ::: toolkit/components/places/History.cpp:1637 (Diff revision 1) > + if (uri) { So what's the semantics if `uri` is `nullptr`? Could you document it? ::: toolkit/components/places/nsNavBookmarks.cpp:2577 (Diff revision 1) > + if (!uri) { Here, too, since it fails silently in release, could you document this behavior somewhere? ::: toolkit/components/places/nsNavHistory.cpp:569 (Diff revision 1) > + if (uri) { Here, too.
Attachment #8711038 - Flags: review?(dteller) → review+
So, while I think this fix kinda works, it doesn't fix the underlying problem and could lead to this assertion in debug code because we expect deserialization to always work: https://dxr.mozilla.org/mozilla-central/source/ipc/glue/URIUtils.cpp#119 It would be much better if we could address the cause of the problem, which is that nsIURI setters cause the URL to exceed its max length. There's less than a dozen setters which need to be addressed. The ones that call into :SetSpec are already OK. We need to do something like > if (mSpec.Length() + input.Length() - Ref().Length() > net_GetURLMaxLength()) return error
Flags: needinfo?(valentin.gosu)
(In reply to Valentin Gosu [:valentin] from comment #11) > It would be much better if we could address the cause of the problem, which > is that nsIURI setters cause the URL to exceed its max length. There's less > than a dozen setters which need to be addressed. The ones that call into > :SetSpec are already OK. I suppose there's no case where we explicitly create an URIParams and Deserialize it, but we always go through SerializeURI. Cause otherwise we'd still need to add a check to Deserialize. Regardless an adding an assertion there will be nice. I think I will split the netwerk part to its own bug and start by landing the crash prevention in Places. Based on Try I may have broken something in Places, so for now I will fix that, then move to the StandardURL part later, unless you wish to attack that in parallel.
(In reply to Marco Bonardo [::mak] from comment #12) > (In reply to Valentin Gosu [:valentin] from comment #11) > > It would be much better if we could address the cause of the problem, which > > is that nsIURI setters cause the URL to exceed its max length. There's less > > than a dozen setters which need to be addressed. The ones that call into > > :SetSpec are already OK. > > I suppose there's no case where we explicitly create an URIParams and > Deserialize it, but we always go through SerializeURI. Cause otherwise we'd > still need to add a check to Deserialize. Regardless an adding an assertion > there will be nice. > > I think I will split the netwerk part to its own bug and start by landing > the crash prevention in Places. Sounds good.
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Review request updated; see interdiff: https://reviewboard.mozilla.org/r/31951/diff/1-2/
Attachment #8711039 - Attachment is obsolete: true
Attachment #8711039 - Flags: review?(valentin.gosu)
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Review request updated; see interdiff: https://reviewboard.mozilla.org/r/31951/diff/2-3/
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Review request updated; see interdiff: https://reviewboard.mozilla.org/r/31951/diff/3-4/
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Review request updated; see interdiff: https://reviewboard.mozilla.org/r/31951/diff/4-5/
Blocks: 1242961
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Review request updated; see interdiff: https://reviewboard.mozilla.org/r/31951/diff/5-6/
Ok, so the Places breakage was due to me using an nsCOMPtr after a .forget() call. Glad we have tests :) Apart that, I had to convert a couple assertions to warnings, cause some automated tests like to test for invalid URIs that "somehow" entered the Places database, and they were clearly hitting the assertions. the nsStandardURL fixed will happen in bug 1242961.
As it's a regression since FF39 and FF45 is the next ESR, requesting tracking.
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla47
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Approval Request Comment [Feature/regressing bug #]: bug 1135354 [User impact if declined]: Crash in rare cases, but with a properly built page it could be used for a DOS [Describe test coverage new/current, TreeHerder]: the touched code is tested in various automated tests [Risks and why]: low risk, mostly null checks [String/UUID change made/needed]: none
Attachment #8711038 - Flags: approval-mozilla-beta?
Attachment #8711038 - Flags: approval-mozilla-aurora?
Comment on attachment 8711038 [details] MozReview Request: Bug 1240013 - Crash in nsNavBookmarks::OnVisit by setting long location.hash. r=Yoric Fix a crash taking it. Should be in 45 beta 2.
Attachment #8711038 - Flags: approval-mozilla-beta?
Attachment #8711038 - Flags: approval-mozilla-beta+
Attachment #8711038 - Flags: approval-mozilla-aurora?
Attachment #8711038 - Flags: approval-mozilla-aurora+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: