Closed
Bug 454298
Opened 17 years ago
Closed 17 years ago
infinite recursion in GetIsKilled
Categories
(MailNews Core :: Database, defect)
MailNews Core
Database
Tracking
(Not tracked)
RESOLVED
FIXED
People
(Reporter: Bienvenu, Assigned: Bienvenu)
Details
Attachments
(2 files, 1 obsolete file)
|
3.71 KB,
patch
|
Bienvenu
:
review+
neil
:
superreview+
|
Details | Diff | Splinter Review |
|
4.12 KB,
patch
|
neil
:
superreview+
|
Details | Diff | Splinter Review |
If the threading structure of a message is messed up, GetIsKilled can recurse until the stack overflows. In particular, if a is the parent of b, and b is the parent of a, then we will recurse forever. In general, GetIsKilled doesn't deal with bogus parenting. I will fix the cause of the broken parenting, but we need to be tolerant of it, for existing db's. The test case in bug 367896 exhibits this problem. I'll attach a patch that basically just counts how deeply we've recursed and errors out if we've gone deeper than the number of children in the thread.
| Assignee | ||
Comment 1•17 years ago
|
||
What do you think of this approach, jcranmer?
Attachment #337543 -
Flags: review?
| Assignee | ||
Updated•17 years ago
|
Attachment #337543 -
Flags: review? → review?(Pidgeot18)
Comment 2•17 years ago
|
||
Comment on attachment 337543 [details] [diff] [review]
proposed fix for crash
>diff --git a/mailnews/db/msgdb/src/nsMsgHdr.cpp b/mailnews/db/msgdb/src/nsMsgHdr.cpp
>+ PRUint32 numChildren;
>+ thread->GetNumChildren(&numChildren);
>+ if (numChildren < depth)
I think a comment explaining why the check is being made would be helpful here; it wasn't immediately obvious to me at first why numChildren and depth should be related (I read the patch before the comments on the bug).
>+NS_IMETHODIMP nsMsgHdr::GetIsKilled(PRBool *isKilled)
>+{
>+ NS_ENSURE_ARG_POINTER(isKilled);
>+ *isKilled = IsAncestorKilled(0);
> return NS_OK;
> }
It shouldn't matter, but I think 1 is the proper parameter here, since the header being queried is in fact the parent of the current header. That should cause failure if the current thread has 1 child and the header thinks it has a parent. In any case, all that happens is but a single extra call, so it's no big deal.
Attachment #337543 -
Flags: review?(Pidgeot18) → review+
| Assignee | ||
Comment 3•17 years ago
|
||
carrying forward jcranmer's review (thx, jcranmer), requesting sr.
Attachment #337543 -
Attachment is obsolete: true
Attachment #337566 -
Flags: superreview?(neil)
Attachment #337566 -
Flags: review+
Updated•17 years ago
|
OS: Windows XP → All
Hardware: PC → All
Updated•17 years ago
|
Attachment #337566 -
Flags: superreview?(neil) → superreview+
Comment 4•17 years ago
|
||
Comment on attachment 337566 [details] [diff] [review]
fix addressing comments
> (void) m_mdb->GetThreadContainingMsgHdr(this, getter_AddRefs(thread));
> if (thread)
> {
> nsCOMPtr<nsIMsgDBHdr> claimant;
> (void) thread->GetChild(threadParent, getter_AddRefs(claimant));
> if (!claimant)
> {
> NS_ASSERTION(PR_FALSE, "Borked message header, please fix!");
>- return NS_OK;
>+ return PR_FALSE;
>+ }
>+ PRUint32 numChildren;
>+ thread->GetNumChildren(&numChildren);
>+
>+ // we can't have as many ancestors as there are messages
>+ // in the thread, so if that seems to be the case, error out.
>+ if (depth >= numChildren)
>+ {
>+ NS_ASSERTION(PR_FALSE, "Borked thread, please fix!");
NS_ERROR
Rather than getting the number of children every time, why not get it once in GetIsKilled and count down to zero? (If you do this I would also suggest checking the depth earlier.)
| Assignee | ||
Comment 5•17 years ago
|
||
that's a good idea - I'll redo this.
| Assignee | ||
Comment 6•17 years ago
|
||
I didn't move the check for ancestors because it's only an error when we're about to recurse - otherwise, I'd have had to pass in numChildren instead of numChildren - 1 as the number of ancestors to check.
Attachment #337881 -
Flags: superreview?(neil)
Updated•17 years ago
|
Attachment #337881 -
Flags: superreview?(neil) → superreview+
Comment 7•17 years ago
|
||
Comment on attachment 337881 [details] [diff] [review]
get thread count only once
>+ if (!isKilled)
> {
> nsMsgKey threadParent;
> GetThreadParent(&threadParent);
My point is that we're already thinking of recursing here but it's up to you exactly where you'd like to put the check.
>+ NS_ASSERTION(PR_FALSE, "cycle in parent relationship, please fix!");
NS_ERROR
| Assignee | ||
Comment 8•17 years ago
|
||
right, we're thinking of recursing, but the case where we don't recurse is ok, so in order to prevent false assertions, I need to put the assertion right before we'll actually recurse.
I've switched it to NS_ERROR
changeset: 305:c2932fcc8375
Status: NEW → RESOLVED
Closed: 17 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•