Changeset 44553 in webkit


Ignore:
Timestamp:
Jun 9, 2009 7:23:06 PM (15 years ago)
Author:
pkasting@chromium.org
Message:

2009-06-09 Peter Kasting <pkasting@google.com>

Reviewed by Eric Seidel.

https://bugs.webkit.org/show_bug.cgi?id=25709 part four
Most of the remaining Cairo changes needed before merging Skia/Cairo
image decoders. Most of these involve plumbing more error detection and
handling (or, in some cases, merely the capability to detect errors, as
e.g. Skia detects and handles image allocation failure while Cairo
currently doesn't). There is also some general cleanup and
simplification; RGBA32Buffer::m_height and all associated functions have
been removed (set but never used) and some places now rely on superclass
implementations.

  • platform/image-decoders/ImageDecoder.h: (WebCore::RGBA32Buffer::RGBA32Buffer): Remove m_height, ensureHeight() and associated stuff (WebCore::RGBA32Buffer::copyBitmapData): Add API function so refcounted backing stores (like Skia uses) can be used with GIFs (WebCore::RGBA32Buffer::setSize): Zero-fill image to avoid garbage (WebCore::RGBA32Buffer::height): Remove (WebCore::RGBA32Buffer::ensureHeight): Remove (WebCore::ImageDecoder::ImageDecoder): Keep member initialization in order, force subclasses to go through size() instead of accessing m_size directly (WebCore::ImageDecoder::isSizeAvailable): Check that decoding hasn't failed (WebCore::ImageDecoder::size): Check that decoding hasn't failed (WebCore::ImageDecoder::setSize): Protect against integer overflow (WebCore::ImageDecoder::isOverSize): Protect against integer overflow
  • platform/image-decoders/gif/GIFImageDecoder.cpp: Remove prepEmptyFrameBuffer() (WebCore::GIFImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling (WebCore::GIFImageDecoder::sizeNowAvailable): Add return values for better failure handling, rely on superclass setSize() for overflow protection (WebCore::GIFImageDecoder::initFrameBuffer): Add return values for better failure handling, remove prepEmptyFrameBuffer(), use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), use RGBA32Buffer::copyBitmapData() so backing store can be refcounted internally (Cairo won't be, Skia is), rely on superclass size() for better failure handling (WebCore::GIFImageDecoder::haveDecodedRow): Fix style violation, remove RGBA32Buffer::ensureHeight() (WebCore::GIFImageDecoder::frameComplete): Remove RGBA32Buffer::ensureHeight()
  • platform/image-decoders/gif/GIFImageDecoder.h: Remove prepEmptyFrameBuffer(), add return values for better failure handling
  • platform/image-decoders/gif/GIFImageReader.cpp: (GIFImageReader::do_lzw): Protect against array overflow, add comments (GIFImageReader::read): Protect against array overflow, be more tolerant of bad data, better failure handling
  • platform/image-decoders/jpeg/JPEGImageDecoder.cpp: Remove MSVC-specific warning disable (bfulgham will move into build files) (WebCore::JPEGImageReader::decode): Better failure handling (WebCore::JPEGImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling (WebCore::JPEGImageDecoder::outputScanlines): Use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), rely on superclass size() for better failure handling, remove RGBA32Buffer::ensureHeight()
  • platform/image-decoders/jpeg/JPEGImageDecoder.h: Rely on superclass setSize() for overflow protection
  • platform/image-decoders/png/PNGImageDecoder.cpp: Remove MSVC-specific warning disable (bfulgham will move into build files) (WebCore::PNGImageDecoder::PNGImageDecoder): Don't allocate a slot in the framebuffer cache until it's needed (WebCore::PNGImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling (WebCore::PNGImageDecoder::frameBufferAtIndex): Don't allocate a slot in the framebuffer cache until it's needed (WebCore::PNGImageDecoder::decode): Don't allocate a slot in the framebuffer cache until it's needed (WebCore::PNGImageDecoder::decodingFailed): Fix style violation (WebCore::PNGImageDecoder::headerAvailable): Rely on superclass isSizeAvailable() and setSize() for overflow protection and better failure handling (WebCore::PNGImageDecoder::rowAvailable): Don't allocate a slot in the framebuffer cache until it's needed, use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), remove RGBA32Buffer::ensureHeight() (WebCore::PNGImageDecoder::pngComplete): Don't allocate a slot in the framebuffer cache until it's needed
Location:
trunk/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r44552 r44553  
     12009-06-09  Peter Kasting  <pkasting@google.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=25709 part four
     6        Most of the remaining Cairo changes needed before merging Skia/Cairo
     7        image decoders.  Most of these involve plumbing more error detection and
     8        handling (or, in some cases, merely the capability to detect errors, as
     9        e.g. Skia detects and handles image allocation failure while Cairo
     10        currently doesn't).  There is also some general cleanup and
     11        simplification; RGBA32Buffer::m_height and all associated functions have
     12        been removed (set but never used) and some places now rely on superclass
     13        implementations.
     14
     15        * platform/image-decoders/ImageDecoder.h:
     16        (WebCore::RGBA32Buffer::RGBA32Buffer): Remove m_height, ensureHeight() and associated stuff
     17        (WebCore::RGBA32Buffer::copyBitmapData): Add API function so refcounted backing stores (like Skia uses) can be used with GIFs
     18        (WebCore::RGBA32Buffer::setSize): Zero-fill image to avoid garbage
     19        (WebCore::RGBA32Buffer::height): Remove
     20        (WebCore::RGBA32Buffer::ensureHeight): Remove
     21        (WebCore::ImageDecoder::ImageDecoder): Keep member initialization in order, force subclasses to go through size() instead of accessing m_size directly
     22        (WebCore::ImageDecoder::isSizeAvailable): Check that decoding hasn't failed
     23        (WebCore::ImageDecoder::size): Check that decoding hasn't failed
     24        (WebCore::ImageDecoder::setSize): Protect against integer overflow
     25        (WebCore::ImageDecoder::isOverSize): Protect against integer overflow
     26        * platform/image-decoders/gif/GIFImageDecoder.cpp: Remove prepEmptyFrameBuffer()
     27        (WebCore::GIFImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling
     28        (WebCore::GIFImageDecoder::sizeNowAvailable): Add return values for better failure handling, rely on superclass setSize() for overflow protection
     29        (WebCore::GIFImageDecoder::initFrameBuffer): Add return values for better failure handling, remove prepEmptyFrameBuffer(), use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), use RGBA32Buffer::copyBitmapData() so backing store can be refcounted internally (Cairo won't be, Skia is), rely on superclass size() for better failure handling
     30        (WebCore::GIFImageDecoder::haveDecodedRow): Fix style violation, remove RGBA32Buffer::ensureHeight()
     31        (WebCore::GIFImageDecoder::frameComplete): Remove RGBA32Buffer::ensureHeight()
     32        * platform/image-decoders/gif/GIFImageDecoder.h: Remove prepEmptyFrameBuffer(), add return values for better failure handling
     33        * platform/image-decoders/gif/GIFImageReader.cpp:
     34        (GIFImageReader::do_lzw): Protect against array overflow, add comments
     35        (GIFImageReader::read): Protect against array overflow, be more tolerant of bad data, better failure handling
     36        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: Remove MSVC-specific warning disable (bfulgham will move into build files)
     37        (WebCore::JPEGImageReader::decode): Better failure handling
     38        (WebCore::JPEGImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling
     39        (WebCore::JPEGImageDecoder::outputScanlines): Use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), rely on superclass size() for better failure handling, remove RGBA32Buffer::ensureHeight()
     40        * platform/image-decoders/jpeg/JPEGImageDecoder.h: Rely on superclass setSize() for overflow protection
     41        * platform/image-decoders/png/PNGImageDecoder.cpp: Remove MSVC-specific warning disable (bfulgham will move into build files)
     42        (WebCore::PNGImageDecoder::PNGImageDecoder): Don't allocate a slot in the framebuffer cache until it's needed
     43        (WebCore::PNGImageDecoder::isSizeAvailable): Rely on superclass isSizeAvailable() for better failure handling
     44        (WebCore::PNGImageDecoder::frameBufferAtIndex): Don't allocate a slot in the framebuffer cache until it's needed
     45        (WebCore::PNGImageDecoder::decode): Don't allocate a slot in the framebuffer cache until it's needed
     46        (WebCore::PNGImageDecoder::decodingFailed): Fix style violation
     47        (WebCore::PNGImageDecoder::headerAvailable): Rely on superclass isSizeAvailable() and setSize() for overflow protection and better failure handling
     48        (WebCore::PNGImageDecoder::rowAvailable): Don't allocate a slot in the framebuffer cache until it's needed, use RGBA32Buffer::setSize() to handle potential allocation failures (won't happen with Cairo port, can in Skia), remove RGBA32Buffer::ensureHeight()
     49        (WebCore::PNGImageDecoder::pngComplete): Don't allocate a slot in the framebuffer cache until it's needed
     50
    1512009-06-09  Kevin Ollivier  <kevino@theolliviers.com>
    252
  • trunk/WebCore/platform/image-decoders/ImageDecoder.h

    r44167 r44553  
    3131#include "PlatformString.h"
    3232#include "SharedBuffer.h"
     33#include <wtf/Assertions.h>
     34#include <wtf/RefPtr.h>
    3335#include <wtf/Vector.h>
    3436
     
    5355
    5456        RGBA32Buffer()
    55             : m_height(0)
    56             , m_status(FrameEmpty)
     57            : m_status(FrameEmpty)
    5758            , m_duration(0)
    5859            , m_disposalMethod(DisposeNotSpecified)
     
    7071        }
    7172
     73        // This function creates a new copy of the image data in |other|, so the
     74        // two images can be modified independently.
     75        void copyBitmapData(const RGBA32Buffer& other)
     76        {
     77            if (this == &other)
     78                return;
     79
     80            m_bytes = other.m_bytes;
     81            m_hasAlpha = other.m_hasAlpha;
     82        }
     83
    7284        const RGBA32Array& bytes() const { return m_bytes; }
    7385        RGBA32Array& bytes() { return m_bytes; }
     86
     87        // Must be called before any pixels are written. Will return true on
     88        // success, false if the memory allocation fails.
     89        bool setSize(int width, int height)
     90        {
     91            // NOTE: This has no way to check for allocation failure if the
     92            // requested size was too big...
     93            m_bytes.resize(width * height);
     94
     95            // Clear the image.
     96            m_bytes.fill(0);
     97            m_hasAlpha = true;
     98
     99            return true;
     100        }
     101
    74102        const IntRect& rect() const { return m_rect; }
    75         unsigned height() const { return m_height; }
    76103        FrameStatus status() const { return m_status; }
    77104        unsigned duration() const { return m_duration; }
     
    80107
    81108        void setRect(const IntRect& r) { m_rect = r; }
    82         void ensureHeight(unsigned rowIndex) { if (rowIndex > m_height) m_height = rowIndex; }
    83109        void setStatus(FrameStatus s) { m_status = s; }
    84110        void setDuration(unsigned duration) { m_duration = duration; }
     
    107133                           // This will always just be the entire buffer except for GIF frames
    108134                           // whose original rect was smaller than the overall image size.
    109         unsigned m_height; // The height (the number of rows we've fully decoded).
    110135        FrameStatus m_status; // Whether or not this frame is completely finished decoding.
    111136        unsigned m_duration; // The animation delay.
     
    120145    public:
    121146        ImageDecoder()
    122             : m_sizeAvailable(false)
    123             , m_failed(false)
    124         {
    125         }
    126        
     147            : m_failed(false)
     148            , m_sizeAvailable(false)
     149        {
     150        }
     151
    127152        virtual ~ImageDecoder() {}
    128153
     
    133158        virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; }
    134159
    135         // Whether or not the size information has been decoded yet.
    136         virtual bool isSizeAvailable() const = 0;
     160        // Whether or not the size information has been decoded yet. This default
     161        // implementation just returns true if the size has been set and we have not
     162        // seen a failure. Decoders may want to override this to lazily decode
     163        // enough of the image to get the size.
     164        virtual bool isSizeAvailable() const
     165        {
     166            return !m_failed && m_sizeAvailable;
     167        }
    137168
    138169        // Requests the size.
    139         virtual IntSize size() const { return m_size; }
     170        virtual IntSize size() const
     171        {
     172            // Requesting the size of an invalid bitmap is meaningless.
     173            ASSERT(!m_failed);
     174            return m_size;
     175        }
    140176
    141177        // The total number of frames for the image.  Classes that support multiple frames
     
    167203
    168204    protected:
     205        // Called by the image decoders to set their decoded size, this also check
     206        // the size for validity. It will return true if the size was set, or false
     207        // if there is an error. On error, the m_failed flag will be set and the
     208        // caller should immediately stop decoding.
     209        bool setSize(unsigned width, unsigned height)
     210        {
     211            if (isOverSize(width, height)) {
     212                m_failed = true;
     213                return false;
     214            }
     215            m_size = IntSize(width, height);
     216            m_sizeAvailable = true;
     217            return true;
     218        }
     219
    169220        RefPtr<SharedBuffer> m_data; // The encoded data.
    170221        Vector<RGBA32Buffer> m_frameBufferCache;
     222        mutable bool m_failed;
     223
     224    private:
     225        // Some code paths compute the size of the image as "width * height * 4"
     226        // and return it as a (signed) int.  Avoid overflow.
     227        static bool isOverSize(unsigned width, unsigned height)
     228        {
     229            // width * height must not exceed (2 ^ 29) - 1, so that we don't
     230            // overflow when we multiply by 4.
     231            unsigned long long total_size = static_cast<unsigned long long>(width)
     232                                          * static_cast<unsigned long long>(height);
     233            return total_size > ((1 << 29) - 1);
     234        }
     235
     236        IntSize m_size;
    171237        bool m_sizeAvailable;
    172         mutable bool m_failed;
    173         IntSize m_size;
    174238    };
    175239
  • trunk/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp

    r44167 r44553  
    117117{
    118118    // If we have pending data to decode, send it to the GIF reader now.
    119     if (!m_sizeAvailable && m_reader) {
     119    if (!ImageDecoder::isSizeAvailable() && m_reader) {
    120120        if (m_failed)
    121121            return false;
     
    126126    }
    127127
    128     return m_sizeAvailable;
     128    return ImageDecoder::isSizeAvailable();
    129129}
    130130
     
    252252
    253253// Callbacks from the GIF reader.
    254 void GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height)
    255 {
    256     m_size = IntSize(width, height);
    257     m_sizeAvailable = true;
     254bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height)
     255{
     256    return setSize(width, height);
    258257}
    259258
     
    263262}
    264263
    265 void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
     264bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
    266265{
    267266    // Initialize the frame rect in our buffer.
     
    280279    if (frameIndex == 0) {
    281280        // This is the first frame, so we're not relying on any previous data.
    282         prepEmptyFrameBuffer(buffer);
     281        if (!buffer->setSize(size().width(), size().height())) {
     282            m_failed = true;
     283            return false;
     284        }
    283285    } else {
    284286        // The starting state for this frame depends on the previous frame's
     
    303305                (prevMethod == RGBA32Buffer::DisposeKeep)) {
    304306            // Preserve the last frame as the starting state for this frame.
    305             buffer->bytes() = prevBuffer->bytes();
    306             buffer->setHasAlpha(prevBuffer->hasAlpha());
     307            buffer->copyBitmapData(*prevBuffer);
    307308        } else {
    308309            // We want to clear the previous frame to transparent, without
     
    313314                // Clearing the first frame, or a frame the size of the whole
    314315                // image, results in a completely empty image.
    315                 prepEmptyFrameBuffer(buffer);
     316                if (!buffer->setSize(size().width(), size().height())) {
     317                    m_failed = true;
     318                    return false;
     319                }
    316320            } else {
    317321              // Copy the whole previous buffer, then clear just its frame.
    318               buffer->bytes() = prevBuffer->bytes();
    319               buffer->setHasAlpha(prevBuffer->hasAlpha());
     322              buffer->copyBitmapData(*prevBuffer);
    320323              for (int y = prevRect.y(); y < prevRect.bottom(); ++y) {
    321324                  unsigned* const currentRow =
    322                       buffer->bytes().data() + (y * m_size.width());
     325                      buffer->bytes().data() + (y * size().width());
    323326                  for (int x = prevRect.x(); x < prevRect.right(); ++x)
    324327                      buffer->setRGBA(*(currentRow + x), 0, 0, 0, 0);
     
    335338    // Reset the alpha pixel tracker for this frame.
    336339    m_currentBufferSawAlpha = false;
    337 }
    338 
    339 void GIFImageDecoder::prepEmptyFrameBuffer(RGBA32Buffer* buffer) const
    340 {
    341     buffer->bytes().resize(size().width() * size().height());
    342     buffer->bytes().fill(0);
    343     buffer->setHasAlpha(true);
     340    return true;
    344341}
    345342
     
    353350    // Initialize the frame if necessary.
    354351    RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
    355     if (buffer.status() == RGBA32Buffer::FrameEmpty)
    356         initFrameBuffer(frameIndex);
     352    if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
     353        return;
    357354
    358355    // Do nothing for bogus data.
     
    405402        // Copy the row |repeatCount|-1 times.
    406403        unsigned num = currDst - dst;
    407         unsigned data_size = num * sizeof(unsigned);
     404        unsigned dataSize = num * sizeof(unsigned);
    408405        unsigned width = size().width();
    409406        unsigned* end = buffer.bytes().data() + width * size().height();
     
    412409            if (currDst + num > end) // Protect against a buffer overrun from a bogus repeatCount.
    413410                break;
    414             memcpy(currDst, dst, data_size);
     411            memcpy(currDst, dst, dataSize);
    415412            currDst += width;
    416413        }
    417414    }
    418 
    419     // Our partial height is rowNumber + 1, e.g., row 2 is the 3rd row, so that's a height of 3.
    420     // Adding in repeatCount - 1 to rowNumber + 1 works out to just be rowNumber + repeatCount.
    421     buffer.ensureHeight(rowNumber + repeatCount);
    422415}
    423416
     
    427420    // in which case we never reach haveDecodedRow() before getting here.
    428421    RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
    429     if (buffer.status() == RGBA32Buffer::FrameEmpty)
    430         initFrameBuffer(frameIndex);
    431 
    432     buffer.ensureHeight(m_size.height());
     422    if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
     423        return;
     424
    433425    buffer.setStatus(RGBA32Buffer::FrameComplete);
    434426    buffer.setDuration(frameDuration);
  • trunk/WebCore/platform/image-decoders/gif/GIFImageDecoder.h

    r44167 r44553  
    6565
    6666        // Callbacks from the GIF reader.
    67         void sizeNowAvailable(unsigned width, unsigned height);
     67        bool sizeNowAvailable(unsigned width, unsigned height);
    6868        void decodingHalted(unsigned bytesLeft);
    6969        void haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber,
     
    7474    private:
    7575        // Called to initialize the frame buffer with the given index, based on the
    76         // previous frame's disposal method.
    77         void initFrameBuffer(unsigned frameIndex);
    78 
    79         // A helper for initFrameBuffer(), this sets the size of the buffer, and
    80         // fills it with transparent pixels.
    81         void prepEmptyFrameBuffer(RGBA32Buffer*) const;
     76        // previous frame's disposal method. Returns true on success. On failure,
     77        // this will mark the image as failed.
     78        bool initFrameBuffer(unsigned frameIndex);
    8279
    8380        bool m_frameCountValid;
  • trunk/WebCore/platform/image-decoders/gif/GIFImageReader.cpp

    r44167 r44553  
    312312      while (code >= clear_code)
    313313      {
    314         if (code == prefix[code])
     314        if (code >= MAX_BITS || code == prefix[code])
    315315          return -1;
    316316
     317        // Even though suffix[] only holds characters through suffix[avail - 1],
     318        // allowing code >= avail here lets us be more tolerant of malformed
     319        // data. As long as code < MAX_BITS, the only risk is a garbled image,
     320        // which is no worse than refusing to display it.
    317321        *stackp++ = suffix[code];
    318322        code = prefix[code];
     
    446450      /* Initialize LZW parser/decoder */
    447451      int datasize = *q;
    448       if (datasize > MAX_LZW_BITS) {
     452      // Since we use a codesize of 1 more than the datasize, we need to ensure
     453      // that our datasize is strictly less than the MAX_LZW_BITS value (12).
     454      // This sets the largest possible codemask correctly at 4095.
     455      if (datasize >= MAX_LZW_BITS) {
    449456        state = gif_error;
    450457        break;
     
    469476        if (!frame_reader->suffix)
    470477          frame_reader->suffix = new unsigned char[MAX_BITS];
     478        // Clearing the whole suffix table lets us be more tolerant of bad data.
     479        memset(frame_reader->suffix, 0, MAX_BITS);
    471480        for (int i = 0; i < frame_reader->clear_code; i++)
    472481          frame_reader->suffix[i] = i;
     
    509518
    510519      // CALLBACK: Inform the decoderplugin of our size.
    511       if (clientptr)
    512         clientptr->sizeNowAvailable(screen_width, screen_height);
     520      if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
     521        return false;
    513522     
    514523      screen_bgcolor = q[5];
     
    735744
    736745        // CALLBACK: Inform the decoderplugin of our size.
    737         if (clientptr)
    738           clientptr->sizeNowAvailable(screen_width, screen_height);
     746        if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
     747          return false;
    739748      }
    740749
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

    r44175 r44553  
    3939#include "JPEGImageDecoder.h"
    4040#include <assert.h>
    41 #include <stdio.h>
    4241
    4342extern "C" {
    4443#include "jpeglib.h"
    4544}
    46 
    47 #if COMPILER(MSVC)
    48 // Remove warnings from warning level 4.
    49 #pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
    50 #endif // COMPILER(MSVC)
    5145
    5246#include <setjmp.h>
     
    220214
    221215                // We can fill in the size now that the header is available.
    222                 m_decoder->setSize(m_info.image_width, m_info.image_height);
     216                if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) {
     217                    m_state = JPEG_ERROR;
     218                    return false;
     219                }
    223220
    224221                if (m_decodingSizeOnly) {
     
    415412{
    416413    // If we have pending data to decode, send it to the JPEG reader now.
    417     if (!m_sizeAvailable && m_reader) {
     414    if (!ImageDecoder::isSizeAvailable() && m_reader) {
    418415        if (m_failed)
    419416            return false;
     
    424421    }
    425422
    426     return m_sizeAvailable;
     423    return ImageDecoder::isSizeAvailable();
    427424}
    428425
     
    464461    RGBA32Buffer& buffer = m_frameBufferCache[0];
    465462    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    466         // Let's resize our buffer now to the correct width/height.
    467         RGBA32Array& bytes = buffer.bytes();
    468         bytes.resize(size().width() * size().height());
     463        // Let's resize our buffer now to the correct width/height. This will
     464        // also initialize it to transparent.
     465        if (!buffer.setSize(size().width(), size().height())) {
     466            m_failed = true;
     467            return false;
     468        }
    469469
    470470        // Update our status to be partially complete.
    471471        buffer.setStatus(RGBA32Buffer::FramePartial);
     472        buffer.setHasAlpha(false);
    472473
    473474        // For JPEGs, the frame always fills the entire image.
    474         buffer.setRect(IntRect(0, 0, m_size.width(), m_size.height()));
    475 
    476         // We don't have alpha (this is the default when the buffer is constructed).
     475        buffer.setRect(IntRect(IntPoint(), size()));
    477476    }
    478477
     
    480479    JSAMPARRAY samples = m_reader->samples();
    481480
    482     unsigned* dst = buffer.bytes().data() + info->output_scanline * m_size.width();
     481    unsigned* dst = buffer.bytes().data() + info->output_scanline * size().width();
    483482   
    484483    while (info->output_scanline < info->output_height) {
     
    493492            RGBA32Buffer::setRGBA(*dst++, r, g, b, 0xFF);
    494493        }
    495 
    496         buffer.ensureHeight(info->output_scanline);
    497494    }
    498495
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h

    r44167 r44553  
    5555        JPEGImageReader* reader() { return m_reader; }
    5656
    57         void setSize(int width, int height) {
    58             if (!m_sizeAvailable) {
    59                 m_sizeAvailable = true;
    60                 m_size = IntSize(width, height);
    61             }
    62         }
    63 
    6457        bool outputScanlines();
    6558        void jpegComplete();
    6659
    6760    private:
     61        friend class JPEGImageReader;
    6862        mutable JPEGImageReader* m_reader;
    6963    };
  • trunk/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

    r44167 r44553  
    4141#include "assert.h"
    4242
    43 #if COMPILER(MSVC)
    44 // Remove warnings from warning level 4.
    45 #pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
    46 #endif // COMPILER(MSVC)
    47 
    4843namespace WebCore {
    4944
     
    144139    : m_reader(0)
    145140{
    146     m_frameBufferCache.resize(1);
    147141}
    148142
     
    170164{
    171165    // If we have pending data to decode, send it to the PNG reader now.
    172     if (!m_sizeAvailable && m_reader) {
     166    if (!ImageDecoder::isSizeAvailable() && m_reader) {
    173167        if (m_failed)
    174168            return false;
     
    179173    }
    180174
    181     return m_sizeAvailable;
     175    return ImageDecoder::isSizeAvailable();
    182176}
    183177
     
    186180    if (index)
    187181        return 0;
     182
     183    if (m_frameBufferCache.isEmpty())
     184        m_frameBufferCache.resize(1);
    188185
    189186    RGBA32Buffer& frame = m_frameBufferCache[0];
     
    202199    m_reader->decode(m_data->buffer(), sizeOnly);
    203200   
    204     if (m_failed || (m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) {
     201    if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) {
    205202        delete m_reader;
    206203        m_reader = 0;
     
    227224}
    228225
    229 void PNGImageDecoder::decodingFailed() {
     226void PNGImageDecoder::decodingFailed()
     227{
    230228    m_failed = true;
    231229}
     
    246244   
    247245    // We can fill in the size now that the header is available.
    248     if (!m_sizeAvailable) {
    249         m_sizeAvailable = true;
    250         m_size = IntSize(width, height);
     246    if (!ImageDecoder::isSizeAvailable()) {
     247        if (!setSize(width, height)) {
     248            // Size unreasonable, bail out.
     249            longjmp(png->jmpbuf, 1);
     250            return;
     251        }
    251252    }
    252253
     
    314315void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass)
    315316{
     317    if (m_frameBufferCache.isEmpty())
     318        return;
     319
    316320    // Resize to the width and height of the image.
    317321    RGBA32Buffer& buffer = m_frameBufferCache[0];
    318322    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    319323        // Let's resize our buffer now to the correct width/height.
    320         RGBA32Array& bytes = buffer.bytes();
    321         bytes.resize(size().width() * size().height());
     324        if (!buffer.setSize(size().width(), size().height())) {
     325            // Error allocating the bitmap. We should not continue.
     326            static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed();
     327            longjmp(reader()->pngPtr()->jmpbuf, 1);
     328            return;
     329        }
    322330
    323331        // Update our status to be partially complete.
    324332        buffer.setStatus(RGBA32Buffer::FramePartial);
     333        buffer.setHasAlpha(false);
    325334
    326335        // For PNGs, the frame always fills the entire image.
    327         buffer.setRect(IntRect(0, 0, size().width(), size().height()));
     336        buffer.setRect(IntRect(IntPoint(), size()));
    328337
    329338        if (reader()->pngPtr()->interlaced)
     
    389398        }
    390399    }
    391 
    392     buffer.ensureHeight(rowIndex + 1);
    393400}
    394401
     
    400407void PNGImageDecoder::pngComplete()
    401408{
     409    if (m_frameBufferCache.isEmpty())
     410        return;
     411
    402412    // Hand back an appropriately sized buffer, even if the image ended up being empty.
    403413    RGBA32Buffer& buffer = m_frameBufferCache[0];
  • trunk/WebCore/platform/image-decoders/skia/GIFImageReader.cpp

    r40173 r44553  
    519519
    520520      // CALLBACK: Inform the decoderplugin of our size.
    521       if (clientptr) {
    522         if (!clientptr->sizeNowAvailable(screen_width, screen_height))
    523           return false;
    524       }
     521      if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
     522        return false;
    525523     
    526524      screen_bgcolor = q[5];
     
    747745
    748746        // CALLBACK: Inform the decoderplugin of our size.
    749         if (clientptr)
    750           clientptr->sizeNowAvailable(screen_width, screen_height);
     747        if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
     748          return false;
    751749      }
    752750
  • trunk/WebCore/platform/image-decoders/skia/JPEGImageDecoder.cpp

    r44545 r44553  
    474474
    475475        // For JPEGs, the frame always fills the entire image.
    476         buffer.setRect(IntRect(0, 0, size().width(), size().height()));
     476        buffer.setRect(IntRect(IntPoint(), size()));
    477477    }
    478478
  • trunk/WebCore/platform/image-decoders/skia/PNGImageDecoder.cpp

    r44545 r44553  
    335335
    336336        // For PNGs, the frame always fills the entire image.
    337         buffer.setRect(IntRect(0, 0, size().width(), size().height()));
     337        buffer.setRect(IntRect(IntPoint(), size()));
    338338
    339339        if (reader()->pngPtr()->interlaced)
Note: See TracChangeset for help on using the changeset viewer.