Closed
Bug 235307
Opened 21 years ago
Closed 21 years ago
nsSupportsArray::Read() allocates wrong memory size
Categories
(Core :: XPCOM, defect, P1)
Core
XPCOM
Tracking
()
RESOLVED
FIXED
mozilla1.7beta
People
(Reporter: jwkbugzilla, Assigned: brendan)
Details
(Keywords: fixed1.4.2)
Attachments
(1 file, 1 obsolete file)
6.67 KB,
patch
|
dougt
:
review+
darin.moz
:
superreview+
|
Details | Diff | Splinter Review |
User-Agent:
Build Identifier:
There is a bug in line 261 (allocation of a new buffer):
http://lxr.mozilla.org/mozilla/source/xpcom/ds/nsSupportsArray.cpp#261
The size of the new array is mArraySize instead of newArraySize which means that
the array doesn't grow at all - the new value for mArraySize is set some lines
later. I don't know where nsSupportsArray::Read() is used, but it will crash
when reading some large array.
Reproducible: Didn't try
Steps to Reproduce:
Reporter | ||
Comment 1•21 years ago
|
||
There is one more bug in the same method (not critical): line 252 should be
placed outside the inner if block, otherwise it is possible to reduce array size
to less then the size of mAutoArray.
Reporter | ||
Comment 2•21 years ago
|
||
And one more in line 610 in nsSupportsArray::SizeTo() when determining whether
to use mAutoArray - it switches to mAutoArray when it is too small instead of
doing so when it is big enough. It should be if (kAutoArraySize >= aSize). This
one isn't critical either but it wastes resources.
Reporter | ||
Comment 3•21 years ago
|
||
And while this file has to be patched anyway - how about replacing this horrible
code in nsSupportsArray::GrowArrayBy()? I understand it's a problem deciding
whether the grow algorithm has to be changed but even with the current algorithm
finding the next power-of-two size can be a lot less complicated (I first
thought this code was a bug). Here is a replacement for lines 167-185 as an example:
if (newSize & (newSize-1)) { // count bits and stuff
PRUint32 bits = 0;
while (newSize >>= 1) {
bits++;
}
bits++; // bump to the next power of two
newSize = 1 << bits;
}
Reporter | ||
Comment 4•21 years ago
|
||
Correction: the bug in nsSupportsArray::SizeTo() _is_ critical because the old
data is copied into the new buffer which is too small for it.
![]() |
||
Comment 5•21 years ago
|
||
I bet this is used in fastload....
Assignee | ||
Comment 6•21 years ago
|
||
Who wrote that bad code, anyway? I can take blame for the brain fart reported
in comment 0, but not the rest. Taking.
/be
Assignee: dougt → brendan
Status: UNCONFIRMED → NEW
Ever confirmed: true
Assignee | ||
Comment 7•21 years ago
|
||
I used prbit.h instead of open-coding a log2 loop.
/be
Assignee | ||
Updated•21 years ago
|
Attachment #142073 -
Flags: superreview?(darin)
Attachment #142073 -
Flags: review?(dougt)
Reporter | ||
Comment 8•21 years ago
|
||
Bug 235217 is probably depending on this one, could someone please check if this
patch fixes it?
Reporter | ||
Comment 9•21 years ago
|
||
One more problem I just saw in Read() - it's better to check if mCount is really
less or equal mArraySize/sizeof(nsISupports*) after reading it from the stream:
271 rv = aStream->Read32(&mCount);
272 if (NS_FAILED(rv)) return rv;
273
274 for (PRUint32 i = 0; i < mCount; i++) {
...
I'm not trusting any streams usually...
Reporter | ||
Comment 10•21 years ago
|
||
It's hard to believe and I looked at least 10 times over it, but it seems that
nsSupportsArray::Equals() compares the array to itself instead of using the
other array:
325 if (NS_FAILED( GetElementAt( aIndex, getter_AddRefs( other ) ) ))
326 return PR_FALSE;
327 if (mArray[aIndex] != other) {
I suppose it should be aOther->GetElementAt(...) instead...
Reporter | ||
Comment 11•21 years ago
|
||
And another bug: nsSupportsArray::RemoveElementsAt() doesn't check the value of
parameter aCount, it will crash if aIndex+aCount is greater than mCount.
Somehow, this reminds me of bug 91362
Reporter | ||
Comment 12•21 years ago
|
||
Please ignore the sizeof() in comment 9, it's nonsense.
There might be a problem with the patch of SizeTo(): I'm not sure if casting
aSize into PRUint32 is a good idea. The original version catches negative values
with the check for aSize < mCount at the beginning of the method, it will just
return PR_TRUE without doing anything. The patched version will pass the
negative value to the new operator instead.
Assignee | ||
Comment 13•21 years ago
|
||
Agreed on comment 9.
Comment 10 and comment 11 belong in other bugs. If you want me to patch it all
here, I can, but I'm not going to take assignment of other bugs, or worry about
closing them.
> There might be a problem with the patch of SizeTo(): I'm not sure if casting
> aSize into PRUint32 is a good idea. The original version catches negative
> values with the check for aSize < mCount at the beginning of the method, it
> will just return PR_TRUE without doing anything.
Not so: mCount is unsigned and C and C++ promote from signed to unsigned.
> The patched version will pass the negative value to the new operator instead.
new takes size_t, which is an unsigned integral type. It will fail for very
large arguments.
If you really want me to defend against negative inputs, I would rather do so
using an assertion.
/be
Status: NEW → ASSIGNED
Priority: -- → P1
Target Milestone: --- → mozilla1.7beta
Assignee | ||
Comment 14•21 years ago
|
||
I fixed things reported here; this code needs a high colonic!
/be
Attachment #142073 -
Attachment is obsolete: true
Assignee | ||
Updated•21 years ago
|
Attachment #142099 -
Flags: superreview?(darin)
Attachment #142099 -
Flags: review?(dougt)
Assignee | ||
Updated•21 years ago
|
Attachment #142073 -
Flags: superreview?(darin)
Attachment #142073 -
Flags: review?(dougt)
Reporter | ||
Comment 15•21 years ago
|
||
Sorry, I wasn't suggesting for you to take care of the bug, I was only assuming
it would be easy for you to check whether the patched Mozilla version still has
the problem (I have to keep looking for the reason if so). I don't really know
how things are done here (and I don't know how problems are usually solved in
Mozilla's C++ code, I was only making suggestions).
Updated•21 years ago
|
Attachment #142099 -
Flags: superreview?(darin) → superreview+
Comment 16•21 years ago
|
||
Comment on attachment 142099 [details] [diff] [review]
patch, v2
i would have added a comment above some of the more terse statements. It took
me a while to figure out what:
if (newSize & (newSize - 1))
was doing. (i cheated and looked at the comment below).
It would be nice to ask who this blames to for a review as well. When they
wrote this, they may have been taking things into consideration that we are all
missing.
get it in soon; needs all the loving testing mozilla can provide.
Attachment #142099 -
Flags: review?(dougt) → review+
Assignee | ||
Comment 17•21 years ago
|
||
dougt, the blame is easy to track, but not very interesting. Some goes to me
(Read), some to waterson, some to kandrot. But there's nothing deep here, just
bugs and suboptimal power-of-two rounding code.
Fix is in, thanks to all, esp. to Wladimir for reporting this! Please test and
close any bugs that might also be fixed; I'm sorry I don't have time to do that
myself.
/be
Status: ASSIGNED → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Assignee | ||
Updated•21 years ago
|
Flags: blocking1.4.2?
Comment 18•21 years ago
|
||
For 1.4, is there any way we could get a very simple fix that just fixes the
problem?
Reporter | ||
Comment 19•21 years ago
|
||
This file hasn't been changed since January 2003, you can use the same patch for
1.4 as well.
Comment 20•21 years ago
|
||
I want a "less risky" patch for 1.4.2.
For an older release, I'd prefer to just fix the bug rather than change the
implementation.
Updated•21 years ago
|
Flags: blocking1.4.2?
Keywords: fixed1.4.2
You need to log in
before you can comment on or make changes to this bug.
Description
•