Changeset 206244 in webkit
- Timestamp:
- Sep 21, 2016 6:23:26 PM (8 years ago)
- Location:
- trunk/Source
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r206236 r206244 1 2016-09-20 Brent Fulgham <bfulgham@apple.com> 2 3 Correct uses of 'safeCast' 4 https://bugs.webkit.org/show_bug.cgi?id=162301 5 <rdar://problem/28343658> 6 7 Reviewed by Antti Koivisto. 8 9 * wtf/StdLibExtras.h: 10 (WTF::safeCast): RELEASE_ASSERT on overflow. 11 1 12 2016-09-21 Commit Queue <commit-queue@webkit.org> 2 13 -
trunk/Source/WTF/wtf/StdLibExtras.h
r205794 r206244 160 160 inline ToType safeCast(FromType value) 161 161 { 162 ASSERT(isInBounds<ToType>(value));162 RELEASE_ASSERT(isInBounds<ToType>(value)); 163 163 return static_cast<ToType>(value); 164 164 } -
trunk/Source/WebCore/ChangeLog
r206243 r206244 1 2016-09-20 Brent Fulgham <bfulgham@apple.com> 2 3 Correct uses of 'safeCast' 4 https://bugs.webkit.org/show_bug.cgi?id=162301 5 <rdar://problem/28343658> 6 7 Reviewed by Antti Koivisto. 8 9 A number of integer calculations in BitmapImage and PDFDocumentImage 10 are not properly checked for overflow. Correct this. 11 12 Tested by fast/images/large-size-image-crash.html 13 14 * loader/cache/MemoryCache.cpp: 15 (WebCore::MemoryCache::adjustSize): RELEASE_ASSERT on overflow. 16 * platform/graphics/BitmapImage.cpp: 17 (WebCore::BitmapImage::destroyMetadataAndNotify): 18 (WebCore::BitmapImage::cacheFrame): 19 (WebCore::BitmapImage::didDecodeProperties): 20 (WebCore::BitmapImage::dataChanged): 21 (WebCore::BitmapImage::ensureFrameAtIndexIsCached): 22 (WebCore::BitmapImage::frameImageAtIndex): 23 * platform/graphics/BitmapImage.h: 24 * platform/graphics/cg/PDFDocumentImage.cpp: 25 (WebCore::PDFDocumentImage::decodedSizeChanged): 26 (WebCore::PDFDocumentImage::updateCachedImageIfNeeded): 27 1 28 2016-09-21 Chris Dumez <cdumez@apple.com> 2 29 -
trunk/Source/WebCore/loader/cache/MemoryCache.cpp
r201603 r206244 645 645 { 646 646 if (live) { 647 ASSERT(delta >= 0 || ((int)m_liveSize + delta >= 0));647 RELEASE_ASSERT(delta >= 0 || ((int)m_liveSize + delta >= 0)); 648 648 m_liveSize += delta; 649 649 } else { 650 ASSERT(delta >= 0 || ((int)m_deadSize + delta >= 0));650 RELEASE_ASSERT(delta >= 0 || ((int)m_deadSize + delta >= 0)); 651 651 m_deadSize += delta; 652 652 } -
trunk/Source/WebCore/platform/graphics/BitmapImage.cpp
r206156 r206244 1 1 /* 2 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 3 * Copyright (C) 2004 , 2005, 2006, 2008, 2015Apple Inc. All rights reserved.3 * Copyright (C) 2004-2006, 2008, 2015-2016 Apple Inc. All rights reserved. 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without … … 37 37 #include "TextStream.h" 38 38 #include "Timer.h" 39 #include <wtf/CheckedArithmetic.h> 39 40 #include <wtf/CurrentTime.h> 40 41 #include <wtf/Vector.h> … … 143 144 invalidatePlatformData(); 144 145 145 ASSERT(m_decodedSize >= frameBytesCleared);146 m_decodedSize -= frameBytesCleared;146 if (!WTF::safeSub(m_decodedSize, frameBytesCleared, m_decodedSize)) 147 CRASH_WITH_SECURITY_IMPLICATION(); 147 148 148 149 // Clearing the ImageSource destroys the extra decoded data used for determining image properties. 150 long long adjustedFrameBytesCleared = frameBytesCleared; 149 151 if (clearedSource == ClearedSource::Yes) { 150 frameBytesCleared += m_decodedPropertiesSize;152 adjustedFrameBytesCleared += m_decodedPropertiesSize; 151 153 m_decodedPropertiesSize = 0; 152 154 } 153 155 154 if (frameBytesCleared && imageObserver()) 155 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared)); 156 if (adjustedFrameBytesCleared && imageObserver()) { 157 Checked<int> checkedDelta = adjustedFrameBytesCleared; 158 imageObserver()->decodedSizeChanged(this, -checkedDelta.unsafeGet()); 159 } 156 160 } 157 161 … … 173 177 174 178 if (m_frames[index].hasNativeImage()) { 175 int deltaBytes = safeCast<int>(m_frames[index].frameBytes()); 176 m_decodedSize += deltaBytes; 179 if (!WTF::safeAdd(m_decodedSize, m_frames[index].frameBytes(), m_decodedSize)) { 180 LOG(Images, "BitmapImage %p cacheFrame m_decodedSize overflowed unsigned.", this); 181 destroyDecodedData(false); 182 return; 183 } 184 177 185 // The fully-decoded frame will subsume the partially decoded data used 178 186 // to determine image properties. 179 deltaBytes -=m_decodedPropertiesSize;187 long long deltaBytes = m_frames[index].frameBytes() - m_decodedPropertiesSize; 180 188 m_decodedPropertiesSize = 0; 189 190 Checked<int, RecordOverflow> checkedDeltaBytes = deltaBytes; 191 if (checkedDeltaBytes.hasOverflowed()) { 192 LOG(Images, "BitmapImage %p cacheFrame deltaBytes=%lld overflowed integer.", this, deltaBytes); 193 destroyDecodedData(false); 194 return; 195 } 196 181 197 if (imageObserver()) 182 imageObserver()->decodedSizeChanged(this, deltaBytes);198 imageObserver()->decodedSizeChanged(this, checkedDeltaBytes.unsafeGet()); 183 199 } 184 200 } … … 193 209 return; 194 210 195 intdeltaBytes = updatedSize - m_decodedPropertiesSize;211 long long deltaBytes = updatedSize - m_decodedPropertiesSize; 196 212 #if !ASSERT_DISABLED 197 213 bool overflow = updatedSize > m_decodedPropertiesSize && deltaBytes < 0; … … 200 216 #endif 201 217 m_decodedPropertiesSize = updatedSize; 202 if (imageObserver()) 203 imageObserver()->decodedSizeChanged(this, deltaBytes); 218 if (imageObserver()) { 219 Checked<int> checkedDeltaBytes = deltaBytes; 220 imageObserver()->decodedSizeChanged(this, checkedDeltaBytes.unsafeGet()); 221 } 204 222 } 205 223 … … 257 275 // frame affected by appending new data here. Thus we have to clear all the 258 276 // incomplete frames to be safe. 259 unsignedframeBytesCleared = 0;277 Checked<unsigned> frameBytesCleared = 0; 260 278 for (auto& frame : m_frames) { 261 279 // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to … … 265 283 frameBytesCleared += frame.clear(); 266 284 } 267 destroyMetadataAndNotify(frameBytesCleared , ClearedSource::No);285 destroyMetadataAndNotify(frameBytesCleared.unsafeGet(), ClearedSource::No); 268 286 #else 269 287 // FIXME: why is this different for iOS? 270 intdeltaBytes = 0;288 Checked<int> deltaBytes = 0; 271 289 if (!m_frames.isEmpty()) { 272 290 if (int bytes = m_frames[m_frames.size() - 1].clear()) { … … 276 294 } 277 295 } 278 destroyMetadataAndNotify(deltaBytes , ClearedSource::No);296 destroyMetadataAndNotify(deltaBytes.unsafeGet(), ClearedSource::No); 279 297 #endif 280 298 … … 357 375 358 376 // If the image is already cached, but at too small a size, re-decode a larger version. 359 int sizeChange = -m_frames[index].clear();377 unsigned sizeChange = m_frames[index].clear(); 360 378 invalidatePlatformData(); 361 m_decodedSize += sizeChange; 379 380 if (WTF::safeSub(m_decodedSize, sizeChange, m_decodedSize)) { 381 LOG(Images, "BitmapImage %p frameImageAtIndex m_decodedSize overflowed unsigned.", this); 382 destroyDecodedData(false); 383 return nullptr; 384 } 385 386 Checked<int, RecordOverflow> checkedSizeChange = -sizeChange; 387 if (checkedSizeChange.hasOverflowed()) { 388 LOG(Images, "BitmapImage %p frameImageAtIndex sizeChange=%u overflowed integer.", this, -sizeChange); 389 destroyDecodedData(false); 390 return nullptr; 391 } 392 362 393 if (imageObserver()) 363 imageObserver()->decodedSizeChanged(this, sizeChange);394 imageObserver()->decodedSizeChanged(this, checkedSizeChange.unsafeGet()); 364 395 } 365 396 -
trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
r204983 r206244 1 1 /* 2 * Copyright (C) 2004 , 2005, 2006, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2004-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 39 39 #include "IntRect.h" 40 40 #include "Length.h" 41 #include "Logging.h" 41 42 #include "SharedBuffer.h" 42 43 #include "TextStream.h" 43 44 #include <CoreGraphics/CGContext.h> 44 45 #include <CoreGraphics/CGPDFDocument.h> 46 #include <wtf/CheckedArithmetic.h> 45 47 #include <wtf/MathExtras.h> 46 48 #include <wtf/RAMSize.h> … … 182 184 return; 183 185 186 long long deltaBytes = m_cachedBytes - newCachedBytes; 187 188 Checked<int> checkedDeltaBytes = deltaBytes; 184 189 if (imageObserver()) 185 imageObserver()->decodedSizeChanged(this, - safeCast<int>(m_cachedBytes) + newCachedBytes);190 imageObserver()->decodedSizeChanged(this, -checkedDeltaBytes.unsafeGet()); 186 191 187 192 ASSERT(s_allDecodedDataSize >= m_cachedBytes); 188 193 // Update with the difference in two steps to avoid unsigned underflow subtraction. 189 s_allDecodedDataSize -= m_cachedBytes; 190 s_allDecodedDataSize += newCachedBytes; 194 if (!WTF::safeSub(s_allDecodedDataSize, m_cachedBytes, s_allDecodedDataSize)) 195 CRASH_WITH_SECURITY_IMPLICATION(); 196 197 if (!WTF::safeAdd(s_allDecodedDataSize, newCachedBytes, s_allDecodedDataSize)) 198 CRASH_WITH_SECURITY_IMPLICATION(); 191 199 192 200 m_cachedBytes = newCachedBytes; … … 236 244 if (m_pdfImageCachingPolicy == PDFImageCachingBelowMemoryLimit) { 237 245 IntSize scaledSize = ImageBuffer::compatibleBufferSize(cachedImageSize, context); 238 if (s_allDecodedDataSize + safeCast<size_t>(scaledSize.width()) * scaledSize.height() * 4 - m_cachedBytes > s_maxDecodedDataSize) { 246 Checked<size_t, RecordOverflow> scaledBytes = scaledSize.area() * 4; 247 248 if (scaledBytes.hasOverflowed()) { 249 LOG(Images, "PDFDocumentImage %p updateCachedImageIfNeeded scaledBytes overflowed size_t.", this); 250 destroyDecodedData(); 251 return; 252 } 253 254 Checked<size_t, RecordOverflow> potentialDecodedDataSize = s_allDecodedDataSize + scaledBytes - m_cachedBytes; 255 if (potentialDecodedDataSize.hasOverflowed() || potentialDecodedDataSize.unsafeGet() > s_maxDecodedDataSize) { 256 LOG(Images, "PDFDocumentImage %p updateCachedImageIfNeeded potentialDecodedDataSize overflowed size_t.", this); 239 257 destroyDecodedData(); 240 258 return; … … 260 278 261 279 IntSize internalSize = m_cachedImageBuffer->internalSize(); 262 decodedSizeChanged(safeCast<size_t>(internalSize.width()) * internalSize.height() * 4); 280 Checked<size_t, RecordOverflow> scaledBytes = internalSize.area() * 4; 281 if (scaledBytes.hasOverflowed()) { 282 LOG(Images, "PDFDocumentImage %p updateCachedImageIfNeeded scaledBytes overflowed size_t.", this); 283 destroyDecodedData(); 284 return; 285 } 286 287 decodedSizeChanged(scaledBytes.unsafeGet()); 263 288 } 264 289
Note: See TracChangeset
for help on using the changeset viewer.