author | Jonathan Kew <jkew@mozilla.com> |
Wed, 28 Nov 2012 09:04:14 +0000 | |
changeset 114350 | 72e123c2602da3920a17c3983f572f4c5524dd2d |
parent 114349 | 9d18ded603301309aaebc9261db21dd941e16762 |
child 114351 | 8ab6b738b68647d41c6409ac963a691c50b120c5 |
push id | 23913 |
push user | emorley@mozilla.com |
push date | Wed, 28 Nov 2012 17:11:31 +0000 |
treeherder | mozilla-central@17c267a881cf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | joe |
bugs | 815512 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/image/decoders/icon/mac/nsIconChannelCocoa.mm +++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm @@ -213,22 +213,22 @@ nsresult nsIconChannel::MakeInputStream( bool fileExists = false; if (fileloc) { // ensure that we DO NOT resolve aliases, very important for file views fileloc->SetFollowLinks(false); fileloc->Exists(&fileExists); } NSImage* iconImage = nil; - + // first try to get the icon from the file if it exists if (fileExists) { nsCOMPtr<nsILocalFileMac> localFileMac(do_QueryInterface(fileloc, &rv)); NS_ENSURE_SUCCESS(rv, rv); - + CFURLRef macURL; if (NS_SUCCEEDED(localFileMac->GetCFURL(&macURL))) { iconImage = [[NSWorkspace sharedWorkspace] iconForFile:[(NSURL*)macURL path]]; ::CFRelease(macURL); } } // if we don't have an icon yet try to get one by extension @@ -238,49 +238,58 @@ nsresult nsIconChannel::MakeInputStream( } // If we still don't have an icon, get the generic document icon. if (!iconImage) iconImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeUnknown]; if (!iconImage) return NS_ERROR_FAILURE; - + // we have an icon now, size it NSRect desiredSizeRect = NSMakeRect(0, 0, desiredImageSize, desiredImageSize); [iconImage setSize:desiredSizeRect.size]; - + [iconImage lockFocus]; NSBitmapImageRep* bitmapRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:desiredSizeRect] autorelease]; [iconImage unlockFocus]; - + // we expect the following things to be true about our bitmapRep NS_ENSURE_TRUE(![bitmapRep isPlanar] && - (unsigned int)[bitmapRep bytesPerPlane] == desiredImageSize * desiredImageSize * 4 && + // Not necessarily: on a HiDPI-capable system, we'll get a 2x bitmap + // (unsigned int)[bitmapRep bytesPerPlane] == desiredImageSize * desiredImageSize * 4 && [bitmapRep bitsPerPixel] == 32 && [bitmapRep samplesPerPixel] == 4 && [bitmapRep hasAlpha] == YES, NS_ERROR_UNEXPECTED); - + + // check what size we actually got, and ensure it isn't too big to return + uint32_t actualImageSize = [bitmapRep bytesPerRow] / 4; + NS_ENSURE_TRUE(actualImageSize < 256, NS_ERROR_UNEXPECTED); + + // now we can validate the amount of data + NS_ENSURE_TRUE((unsigned int)[bitmapRep bytesPerPlane] == actualImageSize * actualImageSize * 4, + NS_ERROR_UNEXPECTED); + // rgba, pre-multiplied data uint8_t* bitmapRepData = (uint8_t*)[bitmapRep bitmapData]; - + // create our buffer - int32_t bufferCapacity = 2 + desiredImageSize * desiredImageSize * 4; + int32_t bufferCapacity = 2 + [bitmapRep bytesPerPlane]; nsAutoTArray<uint8_t, 3 + 16 * 16 * 5> iconBuffer; // initial size is for 16x16 if (!iconBuffer.SetLength(bufferCapacity)) return NS_ERROR_OUT_OF_MEMORY; - + uint8_t* iconBufferPtr = iconBuffer.Elements(); - + // write header data into buffer - *iconBufferPtr++ = desiredImageSize; - *iconBufferPtr++ = desiredImageSize; + *iconBufferPtr++ = actualImageSize; + *iconBufferPtr++ = actualImageSize; - uint32_t dataCount = (desiredImageSize * desiredImageSize) * 4; + uint32_t dataCount = [bitmapRep bytesPerPlane]; uint32_t index = 0; while (index < dataCount) { // get data from the bitmap uint8_t r = bitmapRepData[index++]; uint8_t g = bitmapRepData[index++]; uint8_t b = bitmapRepData[index++]; uint8_t a = bitmapRepData[index++]; @@ -297,21 +306,22 @@ nsresult nsIconChannel::MakeInputStream( *iconBufferPtr++ = r; *iconBufferPtr++ = g; *iconBufferPtr++ = b; #endif } NS_ASSERTION(iconBufferPtr == iconBuffer.Elements() + bufferCapacity, "buffer size miscalculation"); - + // Now, create a pipe and stuff our data into it nsCOMPtr<nsIInputStream> inStream; nsCOMPtr<nsIOutputStream> outStream; - rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream), bufferCapacity, bufferCapacity, nonBlocking); + rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream), + bufferCapacity, bufferCapacity, nonBlocking); if (NS_SUCCEEDED(rv)) { uint32_t written; rv = outStream->Write((char*)iconBuffer.Elements(), bufferCapacity, &written); if (NS_SUCCEEDED(rv)) NS_IF_ADDREF(*_retval = inStream); }