1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 The Graphics Interchange Format(c) is the copyright property of CompuServe
8 Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
9 enhance, alter, modify or change in any way the definition of the format.
10 
11 CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
12 license for the use of the Graphics Interchange Format(sm) in computer
13 software; computer software utilizing GIF(sm) must acknowledge ownership of the
14 Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
15 User and Technical Documentation. Computer software utilizing GIF, which is
16 distributed or may be distributed without User or Technical Documentation must
17 display to the screen or printer a message acknowledging ownership of the
18 Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
19 this case, the acknowledgement may be displayed in an opening screen or leading
20 banner, or a closing screen or trailing banner. A message such as the following
21 may be used:
22 
23     "The Graphics Interchange Format(c) is the Copyright property of
24     CompuServe Incorporated. GIF(sm) is a Service Mark property of
25     CompuServe Incorporated."
26 
27 For further information, please contact :
28 
29     CompuServe Incorporated
30     Graphics Technology Department
31     5000 Arlington Center Boulevard
32     Columbus, Ohio  43220
33     U. S. A.
34 
35 CompuServe Incorporated maintains a mailing list with all those individuals and
36 organizations who wish to receive copies of this document when it is corrected
37 or revised. This service is offered free of charge; please provide us with your
38 mailing address.
39 */
40 
41 #include "nsGIFDecoder2.h"
42 
43 #include <stddef.h>
44 
45 #include "imgFrame.h"
46 #include "mozilla/EndianUtils.h"
47 #include "RasterImage.h"
48 #include "SurfacePipeFactory.h"
49 
50 #include "gfxColor.h"
51 #include "gfxPlatform.h"
52 #include "qcms.h"
53 #include <algorithm>
54 #include "mozilla/Telemetry.h"
55 
56 using namespace mozilla::gfx;
57 
58 using std::max;
59 
60 namespace mozilla {
61 namespace image {
62 
63 //////////////////////////////////////////////////////////////////////
64 // GIF Decoder Implementation
65 
66 static const size_t GIF_HEADER_LEN = 6;
67 static const size_t GIF_SCREEN_DESCRIPTOR_LEN = 7;
68 static const size_t BLOCK_HEADER_LEN = 1;
69 static const size_t SUB_BLOCK_HEADER_LEN = 1;
70 static const size_t EXTENSION_HEADER_LEN = 2;
71 static const size_t GRAPHIC_CONTROL_EXTENSION_LEN = 4;
72 static const size_t APPLICATION_EXTENSION_LEN = 11;
73 static const size_t IMAGE_DESCRIPTOR_LEN = 9;
74 
75 // Masks for reading color table information from packed fields in the screen
76 // descriptor and image descriptor blocks.
77 static const uint8_t PACKED_FIELDS_COLOR_TABLE_BIT = 0x80;
78 static const uint8_t PACKED_FIELDS_INTERLACED_BIT = 0x40;
79 static const uint8_t PACKED_FIELDS_TABLE_DEPTH_MASK = 0x07;
80 
nsGIFDecoder2(RasterImage * aImage)81 nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage)
82     : Decoder(aImage),
83       mLexer(Transition::To(State::GIF_HEADER, GIF_HEADER_LEN),
84              Transition::TerminateSuccess()),
85       mOldColor(0),
86       mCurrentFrameIndex(-1),
87       mColorTablePos(0),
88       mColormap(nullptr),
89       mColormapSize(0),
90       mColorMask('\0'),
91       mGIFOpen(false),
92       mSawTransparency(false),
93       mSwizzleFn(nullptr) {
94   // Clear out the structure, excluding the arrays. Ensure that the global
95   // colormap is initialized as opaque.
96   memset(&mGIFStruct, 0, sizeof(mGIFStruct));
97   memset(mGIFStruct.global_colormap, 0xFF, sizeof(mGIFStruct.global_colormap));
98 
99   // Each color table will need to be unpacked.
100   mSwizzleFn = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::OS_RGBA);
101   MOZ_ASSERT(mSwizzleFn);
102 }
103 
~nsGIFDecoder2()104 nsGIFDecoder2::~nsGIFDecoder2() { free(mGIFStruct.local_colormap); }
105 
FinishInternal()106 nsresult nsGIFDecoder2::FinishInternal() {
107   MOZ_ASSERT(!HasError(), "Shouldn't call FinishInternal after error!");
108 
109   // If the GIF got cut off, handle it anyway
110   if (!IsMetadataDecode() && mGIFOpen) {
111     if (mCurrentFrameIndex == mGIFStruct.images_decoded) {
112       EndImageFrame();
113     }
114     PostDecodeDone(mGIFStruct.loop_count);
115     mGIFOpen = false;
116   }
117 
118   return NS_OK;
119 }
120 
FlushImageData()121 void nsGIFDecoder2::FlushImageData() {
122   Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect();
123   if (!invalidRect) {
124     return;
125   }
126 
127   PostInvalidation(invalidRect->mInputSpaceRect,
128                    Some(invalidRect->mOutputSpaceRect));
129 }
130 
131 //******************************************************************************
132 // GIF decoder callback methods. Part of public API for GIF2
133 //******************************************************************************
134 
135 //******************************************************************************
BeginGIF()136 void nsGIFDecoder2::BeginGIF() {
137   if (mGIFOpen) {
138     return;
139   }
140 
141   mGIFOpen = true;
142 
143   PostSize(mGIFStruct.screen_width, mGIFStruct.screen_height);
144 }
145 
CheckForTransparency(const OrientedIntRect & aFrameRect)146 bool nsGIFDecoder2::CheckForTransparency(const OrientedIntRect& aFrameRect) {
147   // Check if the image has a transparent color in its palette.
148   if (mGIFStruct.is_transparent) {
149     PostHasTransparency();
150     return true;
151   }
152 
153   if (mGIFStruct.images_decoded > 0) {
154     return false;  // We only care about first frame padding below.
155   }
156 
157   // If we need padding on the first frame, that means we don't draw into part
158   // of the image at all. Report that as transparency.
159   OrientedIntRect imageRect(0, 0, mGIFStruct.screen_width,
160                             mGIFStruct.screen_height);
161   if (!imageRect.IsEqualEdges(aFrameRect)) {
162     PostHasTransparency();
163     mSawTransparency = true;  // Make sure we don't optimize it away.
164     return true;
165   }
166 
167   return false;
168 }
169 
170 //******************************************************************************
BeginImageFrame(const OrientedIntRect & aFrameRect,uint16_t aDepth,bool aIsInterlaced)171 nsresult nsGIFDecoder2::BeginImageFrame(const OrientedIntRect& aFrameRect,
172                                         uint16_t aDepth, bool aIsInterlaced) {
173   MOZ_ASSERT(HasSize());
174 
175   bool hasTransparency = CheckForTransparency(aFrameRect);
176 
177   // Make sure there's no animation if we're downscaling.
178   MOZ_ASSERT_IF(Size() != OutputSize(), !GetImageMetadata().HasAnimation());
179 
180   Maybe<AnimationParams> animParams;
181   if (!IsFirstFrameDecode()) {
182     animParams.emplace(aFrameRect.ToUnknownRect(),
183                        FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time),
184                        uint32_t(mGIFStruct.images_decoded), BlendMethod::OVER,
185                        DisposalMethod(mGIFStruct.disposal_method));
186   }
187 
188   SurfacePipeFlags pipeFlags =
189       aIsInterlaced ? SurfacePipeFlags::DEINTERLACE : SurfacePipeFlags();
190 
191   gfx::SurfaceFormat format;
192   if (mGIFStruct.images_decoded == 0) {
193     // The first frame may be displayed progressively.
194     pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
195 
196     // Only allow opaque surfaces if we are decoding a single image without
197     // transparency. For an animation, there isn't much benefit to RGBX given
198     // the current frame is constantly changing, and there are many risks
199     // since BlendAnimationFilter is able to clear rows of data.
200     format = hasTransparency || animParams ? SurfaceFormat::OS_RGBA
201                                            : SurfaceFormat::OS_RGBX;
202   } else {
203     format = SurfaceFormat::OS_RGBA;
204   }
205 
206   Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
207       this, Size(), OutputSize(), aFrameRect, format, format, animParams,
208       mTransform, pipeFlags);
209   mCurrentFrameIndex = mGIFStruct.images_decoded;
210 
211   if (!pipe) {
212     mPipe = SurfacePipe();
213     return NS_ERROR_FAILURE;
214   }
215 
216   mPipe = std::move(*pipe);
217   return NS_OK;
218 }
219 
220 //******************************************************************************
EndImageFrame()221 void nsGIFDecoder2::EndImageFrame() {
222   Opacity opacity = Opacity::SOME_TRANSPARENCY;
223 
224   if (mGIFStruct.images_decoded == 0) {
225     // We need to send invalidations for the first frame.
226     FlushImageData();
227 
228     // The first frame was preallocated with alpha; if it wasn't transparent, we
229     // should fix that. We can also mark it opaque unconditionally if we didn't
230     // actually see any transparent pixels - this test is only valid for the
231     // first frame.
232     if (!mGIFStruct.is_transparent && !mSawTransparency) {
233       opacity = Opacity::FULLY_OPAQUE;
234     }
235   }
236 
237   // Unconditionally increment images_decoded, because we unconditionally
238   // append frames in BeginImageFrame(). This ensures that images_decoded
239   // always refers to the frame in mImage we're currently decoding,
240   // even if some of them weren't decoded properly and thus are blank.
241   mGIFStruct.images_decoded++;
242 
243   // Reset graphic control extension parameters that we shouldn't reuse
244   // between frames.
245   mGIFStruct.delay_time = 0;
246 
247   // Tell the superclass we finished a frame
248   PostFrameStop(opacity);
249 
250   // Reset the transparent pixel
251   if (mOldColor) {
252     mColormap[mGIFStruct.tpixel] = mOldColor;
253     mOldColor = 0;
254   }
255 
256   mColormap = nullptr;
257   mColormapSize = 0;
258   mCurrentFrameIndex = -1;
259 }
260 
261 template <typename PixelSize>
ColormapIndexToPixel(uint8_t aIndex)262 PixelSize nsGIFDecoder2::ColormapIndexToPixel(uint8_t aIndex) {
263   MOZ_ASSERT(sizeof(PixelSize) == sizeof(uint32_t));
264 
265   // Retrieve the next color, clamping to the size of the colormap.
266   uint32_t color = mColormap[aIndex & mColorMask];
267 
268   // Check for transparency.
269   if (mGIFStruct.is_transparent) {
270     mSawTransparency = mSawTransparency || color == 0;
271   }
272 
273   return color;
274 }
275 
276 template <>
ColormapIndexToPixel(uint8_t aIndex)277 uint8_t nsGIFDecoder2::ColormapIndexToPixel<uint8_t>(uint8_t aIndex) {
278   return aIndex & mColorMask;
279 }
280 
281 template <typename PixelSize>
YieldPixels(const uint8_t * aData,size_t aLength,size_t * aBytesReadOut,PixelSize * aPixelBlock,int32_t aBlockSize)282 Tuple<int32_t, Maybe<WriteState>> nsGIFDecoder2::YieldPixels(
283     const uint8_t* aData, size_t aLength, size_t* aBytesReadOut,
284     PixelSize* aPixelBlock, int32_t aBlockSize) {
285   MOZ_ASSERT(aData);
286   MOZ_ASSERT(aBytesReadOut);
287   MOZ_ASSERT(mGIFStruct.stackp >= mGIFStruct.stack);
288 
289   // Advance to the next byte we should read.
290   const uint8_t* data = aData + *aBytesReadOut;
291 
292   int32_t written = 0;
293   while (aBlockSize > written) {
294     // If we don't have any decoded data to yield, try to read some input and
295     // produce some.
296     if (mGIFStruct.stackp == mGIFStruct.stack) {
297       while (mGIFStruct.bits < mGIFStruct.codesize &&
298              *aBytesReadOut < aLength) {
299         // Feed the next byte into the decoder's 32-bit input buffer.
300         mGIFStruct.datum += int32_t(*data) << mGIFStruct.bits;
301         mGIFStruct.bits += 8;
302         data += 1;
303         *aBytesReadOut += 1;
304       }
305 
306       if (mGIFStruct.bits < mGIFStruct.codesize) {
307         return MakeTuple(written, Some(WriteState::NEED_MORE_DATA));
308       }
309 
310       // Get the leading variable-length symbol from the data stream.
311       int code = mGIFStruct.datum & mGIFStruct.codemask;
312       mGIFStruct.datum >>= mGIFStruct.codesize;
313       mGIFStruct.bits -= mGIFStruct.codesize;
314 
315       const int clearCode = ClearCode();
316 
317       // Reset the dictionary to its original state, if requested
318       if (code == clearCode) {
319         mGIFStruct.codesize = mGIFStruct.datasize + 1;
320         mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1;
321         mGIFStruct.avail = clearCode + 2;
322         mGIFStruct.oldcode = -1;
323         return MakeTuple(written, Some(WriteState::NEED_MORE_DATA));
324       }
325 
326       // Check for explicit end-of-stream code. It should only appear after all
327       // image data, but if that was the case we wouldn't be in this function,
328       // so this is always an error condition.
329       if (code == (clearCode + 1)) {
330         return MakeTuple(written, Some(WriteState::FAILURE));
331       }
332 
333       if (mGIFStruct.oldcode == -1) {
334         if (code >= MAX_BITS) {
335           // The code's too big; something's wrong.
336           return MakeTuple(written, Some(WriteState::FAILURE));
337         }
338 
339         mGIFStruct.firstchar = mGIFStruct.oldcode = code;
340 
341         // Yield a pixel at the appropriate index in the colormap.
342         mGIFStruct.pixels_remaining--;
343         aPixelBlock[written++] =
344             ColormapIndexToPixel<PixelSize>(mGIFStruct.suffix[code]);
345         continue;
346       }
347 
348       int incode = code;
349       if (code >= mGIFStruct.avail) {
350         *mGIFStruct.stackp++ = mGIFStruct.firstchar;
351         code = mGIFStruct.oldcode;
352 
353         if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) {
354           // Stack overflow; something's wrong.
355           return MakeTuple(written, Some(WriteState::FAILURE));
356         }
357       }
358 
359       while (code >= clearCode) {
360         if ((code >= MAX_BITS) || (code == mGIFStruct.prefix[code])) {
361           return MakeTuple(written, Some(WriteState::FAILURE));
362         }
363 
364         *mGIFStruct.stackp++ = mGIFStruct.suffix[code];
365         code = mGIFStruct.prefix[code];
366 
367         if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) {
368           // Stack overflow; something's wrong.
369           return MakeTuple(written, Some(WriteState::FAILURE));
370         }
371       }
372 
373       *mGIFStruct.stackp++ = mGIFStruct.firstchar = mGIFStruct.suffix[code];
374 
375       // Define a new codeword in the dictionary.
376       if (mGIFStruct.avail < 4096) {
377         mGIFStruct.prefix[mGIFStruct.avail] = mGIFStruct.oldcode;
378         mGIFStruct.suffix[mGIFStruct.avail] = mGIFStruct.firstchar;
379         mGIFStruct.avail++;
380 
381         // If we've used up all the codewords of a given length increase the
382         // length of codewords by one bit, but don't exceed the specified
383         // maximum codeword size of 12 bits.
384         if (((mGIFStruct.avail & mGIFStruct.codemask) == 0) &&
385             (mGIFStruct.avail < 4096)) {
386           mGIFStruct.codesize++;
387           mGIFStruct.codemask += mGIFStruct.avail;
388         }
389       }
390 
391       mGIFStruct.oldcode = incode;
392     }
393 
394     if (MOZ_UNLIKELY(mGIFStruct.stackp <= mGIFStruct.stack)) {
395       MOZ_ASSERT_UNREACHABLE("No decoded data but we didn't return early?");
396       return MakeTuple(written, Some(WriteState::FAILURE));
397     }
398 
399     // Yield a pixel at the appropriate index in the colormap.
400     mGIFStruct.pixels_remaining--;
401     aPixelBlock[written++] =
402         ColormapIndexToPixel<PixelSize>(*--mGIFStruct.stackp);
403   }
404 
405   return MakeTuple(written, Maybe<WriteState>());
406 }
407 
408 /// Expand the colormap from RGB to Packed ARGB as needed by Cairo.
409 /// And apply any LCMS transformation.
ConvertColormap(uint32_t * aColormap,uint32_t aColors)410 void nsGIFDecoder2::ConvertColormap(uint32_t* aColormap, uint32_t aColors) {
411   if (!aColors) {
412     return;
413   }
414 
415   // Apply CMS transformation if enabled and available
416   if (mCMSMode == CMSMode::All) {
417     qcms_transform* transform = GetCMSsRGBTransform(SurfaceFormat::R8G8B8);
418     if (transform) {
419       qcms_transform_data(transform, aColormap, aColormap, aColors);
420     }
421   }
422 
423   // Expand color table from RGB to BGRA.
424   MOZ_ASSERT(mSwizzleFn);
425   uint8_t* data = reinterpret_cast<uint8_t*>(aColormap);
426   mSwizzleFn(data, data, aColors);
427 #if MOZ_BIG_ENDIAN()
428   SwizzleRow(SurfaceFormat::A8R8G8B8, SurfaceFormat::B8G8R8A8)(data, data, aColors);
429 #endif
430 }
431 
DoDecode(SourceBufferIterator & aIterator,IResumable * aOnResume)432 LexerResult nsGIFDecoder2::DoDecode(SourceBufferIterator& aIterator,
433                                     IResumable* aOnResume) {
434   MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
435 
436   return mLexer.Lex(
437       aIterator, aOnResume,
438       [=](State aState, const char* aData, size_t aLength) {
439         switch (aState) {
440           case State::GIF_HEADER:
441             return ReadGIFHeader(aData);
442           case State::SCREEN_DESCRIPTOR:
443             return ReadScreenDescriptor(aData);
444           case State::GLOBAL_COLOR_TABLE:
445             return ReadGlobalColorTable(aData, aLength);
446           case State::FINISHED_GLOBAL_COLOR_TABLE:
447             return FinishedGlobalColorTable();
448           case State::BLOCK_HEADER:
449             return ReadBlockHeader(aData);
450           case State::EXTENSION_HEADER:
451             return ReadExtensionHeader(aData);
452           case State::GRAPHIC_CONTROL_EXTENSION:
453             return ReadGraphicControlExtension(aData);
454           case State::APPLICATION_IDENTIFIER:
455             return ReadApplicationIdentifier(aData);
456           case State::NETSCAPE_EXTENSION_SUB_BLOCK:
457             return ReadNetscapeExtensionSubBlock(aData);
458           case State::NETSCAPE_EXTENSION_DATA:
459             return ReadNetscapeExtensionData(aData);
460           case State::IMAGE_DESCRIPTOR:
461             return ReadImageDescriptor(aData);
462           case State::FINISH_IMAGE_DESCRIPTOR:
463             return FinishImageDescriptor(aData);
464           case State::LOCAL_COLOR_TABLE:
465             return ReadLocalColorTable(aData, aLength);
466           case State::FINISHED_LOCAL_COLOR_TABLE:
467             return FinishedLocalColorTable();
468           case State::IMAGE_DATA_BLOCK:
469             return ReadImageDataBlock(aData);
470           case State::IMAGE_DATA_SUB_BLOCK:
471             return ReadImageDataSubBlock(aData);
472           case State::LZW_DATA:
473             return ReadLZWData(aData, aLength);
474           case State::SKIP_LZW_DATA:
475             return Transition::ContinueUnbuffered(State::SKIP_LZW_DATA);
476           case State::FINISHED_LZW_DATA:
477             return Transition::To(State::IMAGE_DATA_SUB_BLOCK,
478                                   SUB_BLOCK_HEADER_LEN);
479           case State::SKIP_SUB_BLOCKS:
480             return SkipSubBlocks(aData);
481           case State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS:
482             return Transition::ContinueUnbuffered(
483                 State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS);
484           case State::FINISHED_SKIPPING_DATA:
485             return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
486           default:
487             MOZ_CRASH("Unknown State");
488         }
489       });
490 }
491 
ReadGIFHeader(const char * aData)492 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadGIFHeader(
493     const char* aData) {
494   // We retrieve the version here but because many GIF encoders set header
495   // fields incorrectly, we barely use it; features which should only appear in
496   // GIF89a are always accepted.
497   if (strncmp(aData, "GIF87a", GIF_HEADER_LEN) == 0) {
498     mGIFStruct.version = 87;
499   } else if (strncmp(aData, "GIF89a", GIF_HEADER_LEN) == 0) {
500     mGIFStruct.version = 89;
501   } else {
502     return Transition::TerminateFailure();
503   }
504 
505   return Transition::To(State::SCREEN_DESCRIPTOR, GIF_SCREEN_DESCRIPTOR_LEN);
506 }
507 
ReadScreenDescriptor(const char * aData)508 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadScreenDescriptor(
509     const char* aData) {
510   mGIFStruct.screen_width = LittleEndian::readUint16(aData + 0);
511   mGIFStruct.screen_height = LittleEndian::readUint16(aData + 2);
512 
513   const uint8_t packedFields = aData[4];
514 
515   // XXX: Should we be capturing these values even if there is no global color
516   // table?
517   mGIFStruct.global_colormap_depth =
518       (packedFields & PACKED_FIELDS_TABLE_DEPTH_MASK) + 1;
519   mGIFStruct.global_colormap_count = 1 << mGIFStruct.global_colormap_depth;
520 
521   // We ignore several fields in the header. We don't care about the 'sort
522   // flag', which indicates if the global color table's entries are sorted in
523   // order of importance - if we need to render this image for a device with a
524   // narrower color gamut than GIF supports we'll handle that at a different
525   // layer. We have no use for the pixel aspect ratio as well. Finally, we
526   // intentionally ignore the background color index, as implementing that
527   // feature would not be web compatible - when a GIF image frame doesn't cover
528   // the entire area of the image, the area that's not covered should always be
529   // transparent.
530 
531   if (packedFields & PACKED_FIELDS_COLOR_TABLE_BIT) {
532     MOZ_ASSERT(mColorTablePos == 0);
533 
534     // We read the global color table in unbuffered mode since it can be quite
535     // large and it'd be preferable to avoid unnecessary copies.
536     const size_t globalColorTableSize = 3 * mGIFStruct.global_colormap_count;
537     return Transition::ToUnbuffered(State::FINISHED_GLOBAL_COLOR_TABLE,
538                                     State::GLOBAL_COLOR_TABLE,
539                                     globalColorTableSize);
540   }
541 
542   return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
543 }
544 
ReadGlobalColorTable(const char * aData,size_t aLength)545 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadGlobalColorTable(
546     const char* aData, size_t aLength) {
547   uint8_t* dest =
548       reinterpret_cast<uint8_t*>(mGIFStruct.global_colormap) + mColorTablePos;
549   memcpy(dest, aData, aLength);
550   mColorTablePos += aLength;
551   return Transition::ContinueUnbuffered(State::GLOBAL_COLOR_TABLE);
552 }
553 
554 LexerTransition<nsGIFDecoder2::State>
FinishedGlobalColorTable()555 nsGIFDecoder2::FinishedGlobalColorTable() {
556   ConvertColormap(mGIFStruct.global_colormap, mGIFStruct.global_colormap_count);
557   mColorTablePos = 0;
558   return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
559 }
560 
ReadBlockHeader(const char * aData)561 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadBlockHeader(
562     const char* aData) {
563   // Determine what type of block we're dealing with.
564   switch (aData[0]) {
565     case GIF_EXTENSION_INTRODUCER:
566       return Transition::To(State::EXTENSION_HEADER, EXTENSION_HEADER_LEN);
567 
568     case GIF_IMAGE_SEPARATOR:
569       return Transition::To(State::IMAGE_DESCRIPTOR, IMAGE_DESCRIPTOR_LEN);
570 
571     case GIF_TRAILER:
572       FinishInternal();
573       return Transition::TerminateSuccess();
574 
575     default:
576       // If we get anything other than GIF_IMAGE_SEPARATOR,
577       // GIF_EXTENSION_INTRODUCER, or GIF_TRAILER, there is extraneous data
578       // between blocks. The GIF87a spec tells us to keep reading until we find
579       // an image separator, but GIF89a says such a file is corrupt. We follow
580       // GIF89a and bail out.
581 
582       if (mGIFStruct.images_decoded > 0) {
583         // The file is corrupt, but we successfully decoded some frames, so we
584         // may as well consider the decode successful and display them.
585         FinishInternal();
586         return Transition::TerminateSuccess();
587       }
588 
589       // No images decoded; there is nothing to display.
590       return Transition::TerminateFailure();
591   }
592 }
593 
ReadExtensionHeader(const char * aData)594 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadExtensionHeader(
595     const char* aData) {
596   const uint8_t label = aData[0];
597   const uint8_t extensionHeaderLength = aData[1];
598 
599   // If the extension header is zero length, just treat it as a block terminator
600   // and move on to the next block immediately.
601   if (extensionHeaderLength == 0) {
602     return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
603   }
604 
605   switch (label) {
606     case GIF_GRAPHIC_CONTROL_LABEL:
607       // The GIF spec mandates that the Control Extension header block length is
608       // 4 bytes, and the parser for this block reads 4 bytes, so we must
609       // enforce that the buffer contains at least this many bytes. If the GIF
610       // specifies a different length, we allow that, so long as it's larger;
611       // the additional data will simply be ignored.
612       return Transition::To(
613           State::GRAPHIC_CONTROL_EXTENSION,
614           max<uint8_t>(extensionHeaderLength, GRAPHIC_CONTROL_EXTENSION_LEN));
615 
616     case GIF_APPLICATION_EXTENSION_LABEL:
617       // Again, the spec specifies that an application extension header is 11
618       // bytes, but for compatibility with GIFs in the wild, we allow deviation
619       // from the spec. This is important for real-world compatibility, as GIFs
620       // in the wild exist with application extension headers that are both
621       // shorter and longer than 11 bytes. However, we only try to actually
622       // interpret the application extension if the length is correct;
623       // otherwise, we just skip the block unconditionally.
624       return extensionHeaderLength == APPLICATION_EXTENSION_LEN
625                  ? Transition::To(State::APPLICATION_IDENTIFIER,
626                                   extensionHeaderLength)
627                  : Transition::ToUnbuffered(
628                        State::FINISHED_SKIPPING_DATA,
629                        State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
630                        extensionHeaderLength);
631 
632     default:
633       // Skip over any other type of extension block, including comment and
634       // plain text blocks.
635       return Transition::ToUnbuffered(State::FINISHED_SKIPPING_DATA,
636                                       State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
637                                       extensionHeaderLength);
638   }
639 }
640 
641 LexerTransition<nsGIFDecoder2::State>
ReadGraphicControlExtension(const char * aData)642 nsGIFDecoder2::ReadGraphicControlExtension(const char* aData) {
643   mGIFStruct.is_transparent = aData[0] & 0x1;
644   mGIFStruct.tpixel = uint8_t(aData[3]);
645   mGIFStruct.disposal_method = (aData[0] >> 2) & 0x7;
646 
647   if (mGIFStruct.disposal_method == 4) {
648     // Some encoders (and apparently some specs) represent
649     // DisposalMethod::RESTORE_PREVIOUS as 4, but 3 is used in the canonical
650     // spec and is more popular, so we normalize to 3.
651     mGIFStruct.disposal_method = 3;
652   } else if (mGIFStruct.disposal_method > 4) {
653     // This GIF is using a disposal method which is undefined in the spec.
654     // Treat it as DisposalMethod::NOT_SPECIFIED.
655     mGIFStruct.disposal_method = 0;
656   }
657 
658   DisposalMethod method = DisposalMethod(mGIFStruct.disposal_method);
659   if (method == DisposalMethod::CLEAR_ALL || method == DisposalMethod::CLEAR) {
660     // We may have to display the background under this image during animation
661     // playback, so we regard it as transparent.
662     PostHasTransparency();
663   }
664 
665   mGIFStruct.delay_time = LittleEndian::readUint16(aData + 1) * 10;
666   if (!HasAnimation() && mGIFStruct.delay_time > 0) {
667     PostIsAnimated(FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time));
668   }
669 
670   return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
671 }
672 
ReadApplicationIdentifier(const char * aData)673 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadApplicationIdentifier(
674     const char* aData) {
675   if ((strncmp(aData, "NETSCAPE2.0", 11) == 0) ||
676       (strncmp(aData, "ANIMEXTS1.0", 11) == 0)) {
677     // This is a Netscape application extension block.
678     return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
679                           SUB_BLOCK_HEADER_LEN);
680   }
681 
682   // This is an application extension we don't care about. Just skip it.
683   return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
684 }
685 
686 LexerTransition<nsGIFDecoder2::State>
ReadNetscapeExtensionSubBlock(const char * aData)687 nsGIFDecoder2::ReadNetscapeExtensionSubBlock(const char* aData) {
688   const uint8_t blockLength = aData[0];
689   if (blockLength == 0) {
690     // We hit the block terminator.
691     return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
692   }
693 
694   // We consume a minimum of 3 bytes in accordance with the specs for the
695   // Netscape application extension block, such as they are.
696   const size_t extensionLength = max<uint8_t>(blockLength, 3);
697   return Transition::To(State::NETSCAPE_EXTENSION_DATA, extensionLength);
698 }
699 
ReadNetscapeExtensionData(const char * aData)700 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadNetscapeExtensionData(
701     const char* aData) {
702   // Documentation for NETSCAPE2.0 / ANIMEXTS1.0 extensions can be found at:
703   //   https://wiki.whatwg.org/wiki/GIF
704   static const uint8_t NETSCAPE_LOOPING_EXTENSION_SUB_BLOCK_ID = 1;
705   static const uint8_t NETSCAPE_BUFFERING_EXTENSION_SUB_BLOCK_ID = 2;
706 
707   const uint8_t subBlockID = aData[0] & 7;
708   switch (subBlockID) {
709     case NETSCAPE_LOOPING_EXTENSION_SUB_BLOCK_ID:
710       // This is looping extension.
711       mGIFStruct.loop_count = LittleEndian::readUint16(aData + 1);
712       // Zero loop count is infinite animation loop request.
713       if (mGIFStruct.loop_count == 0) {
714         mGIFStruct.loop_count = -1;
715       }
716 
717       return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
718                             SUB_BLOCK_HEADER_LEN);
719 
720     case NETSCAPE_BUFFERING_EXTENSION_SUB_BLOCK_ID:
721       // We allow, but ignore, this extension.
722       return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
723                             SUB_BLOCK_HEADER_LEN);
724 
725     default:
726       return Transition::TerminateFailure();
727   }
728 }
729 
ReadImageDescriptor(const char * aData)730 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDescriptor(
731     const char* aData) {
732   // On the first frame, we don't need to yield, and none of the other checks
733   // below apply, so we can just jump right into FinishImageDescriptor().
734   if (mGIFStruct.images_decoded == 0) {
735     return FinishImageDescriptor(aData);
736   }
737 
738   if (!HasAnimation()) {
739     // We should've already called PostIsAnimated(); this must be a corrupt
740     // animated image with a first frame timeout of zero. Signal that we're
741     // animated now, before the first-frame decode early exit below, so that
742     // RasterImage can detect that this happened.
743     PostIsAnimated(FrameTimeout::FromRawMilliseconds(0));
744   }
745 
746   if (IsFirstFrameDecode()) {
747     // We're about to get a second frame, but we only want the first. Stop
748     // decoding now.
749     FinishInternal();
750     return Transition::TerminateSuccess();
751   }
752 
753   MOZ_ASSERT(Size() == OutputSize(), "Downscaling an animated image?");
754 
755   // Yield to allow access to the previous frame before we start a new one.
756   return Transition::ToAfterYield(State::FINISH_IMAGE_DESCRIPTOR);
757 }
758 
FinishImageDescriptor(const char * aData)759 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishImageDescriptor(
760     const char* aData) {
761   OrientedIntRect frameRect;
762 
763   // Get image offsets with respect to the screen origin.
764   frameRect.SetRect(
765       LittleEndian::readUint16(aData + 0), LittleEndian::readUint16(aData + 2),
766       LittleEndian::readUint16(aData + 4), LittleEndian::readUint16(aData + 6));
767 
768   if (!mGIFStruct.images_decoded) {
769     // Work around GIF files where
770     //   * at least one of the logical screen dimensions is smaller than the
771     //     same dimension in the first image, or
772     //   * GIF87a files where the first image's dimensions do not match the
773     //     logical screen dimensions.
774     if (mGIFStruct.screen_height < frameRect.Height() ||
775         mGIFStruct.screen_width < frameRect.Width() ||
776         mGIFStruct.version == 87) {
777       mGIFStruct.screen_height = frameRect.Height();
778       mGIFStruct.screen_width = frameRect.Width();
779       frameRect.MoveTo(0, 0);
780     }
781 
782     // Create the image container with the right size.
783     BeginGIF();
784     if (HasError()) {
785       // Setting the size led to an error.
786       return Transition::TerminateFailure();
787     }
788 
789     // If we're doing a metadata decode, we're done.
790     if (IsMetadataDecode()) {
791       CheckForTransparency(frameRect);
792       FinishInternal();
793       return Transition::TerminateSuccess();
794     }
795   }
796 
797   // Work around broken GIF files that have zero frame width or height; in this
798   // case, we'll treat the frame as having the same size as the overall image.
799   if (frameRect.Height() == 0 || frameRect.Width() == 0) {
800     frameRect.SetHeight(mGIFStruct.screen_height);
801     frameRect.SetWidth(mGIFStruct.screen_width);
802 
803     // If that still resulted in zero frame width or height, give up.
804     if (frameRect.Height() == 0 || frameRect.Width() == 0) {
805       return Transition::TerminateFailure();
806     }
807   }
808 
809   // Determine |depth| (log base 2 of the number of colors in the palette).
810   bool haveLocalColorTable = false;
811   uint16_t depth = 0;
812   uint8_t packedFields = aData[8];
813 
814   if (packedFields & PACKED_FIELDS_COLOR_TABLE_BIT) {
815     // Get the palette depth from the local color table.
816     depth = (packedFields & PACKED_FIELDS_TABLE_DEPTH_MASK) + 1;
817     haveLocalColorTable = true;
818   } else {
819     // Get the palette depth from the global color table.
820     depth = mGIFStruct.global_colormap_depth;
821   }
822 
823   // If the transparent color index is greater than the number of colors in the
824   // color table, we may need a higher color depth than |depth| would specify.
825   // Our internal representation of the image will instead use |realDepth|,
826   // which is the smallest color depth that can accommodate the existing palette
827   // *and* the transparent color index.
828   uint16_t realDepth = depth;
829   while (mGIFStruct.tpixel >= (1 << realDepth) && realDepth < 8) {
830     realDepth++;
831   }
832 
833   // Create a mask used to ensure that color values fit within the colormap.
834   mColorMask = 0xFF >> (8 - realDepth);
835 
836   // Determine if this frame is interlaced or not.
837   const bool isInterlaced = packedFields & PACKED_FIELDS_INTERLACED_BIT;
838 
839   // Create the SurfacePipe we'll use to write output for this frame.
840   if (NS_FAILED(BeginImageFrame(frameRect, realDepth, isInterlaced))) {
841     return Transition::TerminateFailure();
842   }
843 
844   // Clear state from last image.
845   mGIFStruct.pixels_remaining =
846       int64_t(frameRect.Width()) * int64_t(frameRect.Height());
847 
848   if (haveLocalColorTable) {
849     // We have a local color table, so prepare to read it into the palette of
850     // the current frame.
851     mGIFStruct.local_colormap_size = 1 << depth;
852 
853     if (!mColormap) {
854       // Ensure our current colormap buffer is large enough to hold the new one.
855       mColormapSize = sizeof(uint32_t) << realDepth;
856       if (mGIFStruct.local_colormap_buffer_size < mColormapSize) {
857         if (mGIFStruct.local_colormap) {
858           free(mGIFStruct.local_colormap);
859         }
860         mGIFStruct.local_colormap_buffer_size = mColormapSize;
861         mGIFStruct.local_colormap =
862             static_cast<uint32_t*>(moz_xmalloc(mColormapSize));
863         // Ensure the local colormap is initialized as opaque.
864         memset(mGIFStruct.local_colormap, 0xFF, mColormapSize);
865       } else {
866         mColormapSize = mGIFStruct.local_colormap_buffer_size;
867       }
868 
869       mColormap = mGIFStruct.local_colormap;
870     }
871 
872     MOZ_ASSERT(mColormap);
873 
874     const size_t size = 3 << depth;
875     if (mColormapSize > size) {
876       // Clear the part of the colormap which will be unused with this palette.
877       // If a GIF references an invalid palette entry, ensure the entry is
878       // opaque white. This is needed for Skia as if it isn't, RGBX surfaces
879       // will cause blending issues with Skia.
880       memset(reinterpret_cast<uint8_t*>(mColormap) + size, 0xFF,
881              mColormapSize - size);
882     }
883 
884     MOZ_ASSERT(mColorTablePos == 0);
885 
886     // We read the local color table in unbuffered mode since it can be quite
887     // large and it'd be preferable to avoid unnecessary copies.
888     return Transition::ToUnbuffered(State::FINISHED_LOCAL_COLOR_TABLE,
889                                     State::LOCAL_COLOR_TABLE, size);
890   }
891 
892   // There's no local color table; copy the global color table into the palette
893   // of the current frame.
894   if (mColormap) {
895     memcpy(mColormap, mGIFStruct.global_colormap, mColormapSize);
896   } else {
897     mColormap = mGIFStruct.global_colormap;
898   }
899 
900   return Transition::To(State::IMAGE_DATA_BLOCK, BLOCK_HEADER_LEN);
901 }
902 
ReadLocalColorTable(const char * aData,size_t aLength)903 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadLocalColorTable(
904     const char* aData, size_t aLength) {
905   uint8_t* dest = reinterpret_cast<uint8_t*>(mColormap) + mColorTablePos;
906   memcpy(dest, aData, aLength);
907   mColorTablePos += aLength;
908   return Transition::ContinueUnbuffered(State::LOCAL_COLOR_TABLE);
909 }
910 
FinishedLocalColorTable()911 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishedLocalColorTable() {
912   ConvertColormap(mColormap, mGIFStruct.local_colormap_size);
913   mColorTablePos = 0;
914   return Transition::To(State::IMAGE_DATA_BLOCK, BLOCK_HEADER_LEN);
915 }
916 
ReadImageDataBlock(const char * aData)917 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDataBlock(
918     const char* aData) {
919   // Make sure the transparent pixel is transparent in the colormap.
920   if (mGIFStruct.is_transparent) {
921     // Save the old value so we can restore it later.
922     if (mColormap == mGIFStruct.global_colormap) {
923       mOldColor = mColormap[mGIFStruct.tpixel];
924     }
925     mColormap[mGIFStruct.tpixel] = 0;
926   }
927 
928   // Initialize the LZW decoder.
929   mGIFStruct.datasize = uint8_t(aData[0]);
930   if (mGIFStruct.datasize > MAX_LZW_BITS) {
931     return Transition::TerminateFailure();
932   }
933   const int clearCode = ClearCode();
934   if (clearCode >= MAX_BITS) {
935     return Transition::TerminateFailure();
936   }
937 
938   mGIFStruct.avail = clearCode + 2;
939   mGIFStruct.oldcode = -1;
940   mGIFStruct.codesize = mGIFStruct.datasize + 1;
941   mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1;
942   mGIFStruct.datum = mGIFStruct.bits = 0;
943 
944   // Initialize the tables.
945   for (int i = 0; i < clearCode; i++) {
946     mGIFStruct.suffix[i] = i;
947   }
948 
949   mGIFStruct.stackp = mGIFStruct.stack;
950 
951   // Begin reading image data sub-blocks.
952   return Transition::To(State::IMAGE_DATA_SUB_BLOCK, SUB_BLOCK_HEADER_LEN);
953 }
954 
ReadImageDataSubBlock(const char * aData)955 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDataSubBlock(
956     const char* aData) {
957   const uint8_t subBlockLength = aData[0];
958   if (subBlockLength == 0) {
959     // We hit the block terminator.
960     EndImageFrame();
961     return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
962   }
963 
964   if (mGIFStruct.pixels_remaining == 0) {
965     // We've already written to the entire image; we should've hit the block
966     // terminator at this point. This image is corrupt, but we'll tolerate it.
967 
968     if (subBlockLength == GIF_TRAILER) {
969       // This GIF is missing the block terminator for the final block; we'll put
970       // up with it.
971       FinishInternal();
972       return Transition::TerminateSuccess();
973     }
974 
975     // We're not at the end of the image, so just skip the extra data.
976     return Transition::ToUnbuffered(State::FINISHED_LZW_DATA,
977                                     State::SKIP_LZW_DATA, subBlockLength);
978   }
979 
980   // Handle the standard case: there's data in the sub-block and pixels left to
981   // fill in the image. We read the sub-block unbuffered so we can get pixels on
982   // the screen as soon as possible.
983   return Transition::ToUnbuffered(State::FINISHED_LZW_DATA, State::LZW_DATA,
984                                   subBlockLength);
985 }
986 
ReadLZWData(const char * aData,size_t aLength)987 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadLZWData(
988     const char* aData, size_t aLength) {
989   const uint8_t* data = reinterpret_cast<const uint8_t*>(aData);
990   size_t length = aLength;
991 
992   while (mGIFStruct.pixels_remaining > 0 &&
993          (length > 0 || mGIFStruct.bits >= mGIFStruct.codesize)) {
994     size_t bytesRead = 0;
995 
996     auto result = mPipe.WritePixelBlocks<uint32_t>(
997         [&](uint32_t* aPixelBlock, int32_t aBlockSize) {
998           return YieldPixels<uint32_t>(data, length, &bytesRead, aPixelBlock,
999                                        aBlockSize);
1000         });
1001 
1002     if (MOZ_UNLIKELY(bytesRead > length)) {
1003       MOZ_ASSERT_UNREACHABLE("Overread?");
1004       bytesRead = length;
1005     }
1006 
1007     // Advance our position in the input based upon what YieldPixel() consumed.
1008     data += bytesRead;
1009     length -= bytesRead;
1010 
1011     switch (result) {
1012       case WriteState::NEED_MORE_DATA:
1013         continue;
1014 
1015       case WriteState::FINISHED:
1016         NS_WARNING_ASSERTION(mGIFStruct.pixels_remaining <= 0,
1017                              "too many pixels");
1018         mGIFStruct.pixels_remaining = 0;
1019         break;
1020 
1021       case WriteState::FAILURE:
1022         return Transition::TerminateFailure();
1023     }
1024   }
1025 
1026   // We're done, but keep going until we consume all the data in the sub-block.
1027   return Transition::ContinueUnbuffered(State::LZW_DATA);
1028 }
1029 
SkipSubBlocks(const char * aData)1030 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::SkipSubBlocks(
1031     const char* aData) {
1032   // In the SKIP_SUB_BLOCKS state we skip over data sub-blocks that we're not
1033   // interested in. Blocks consist of a block header (which can be up to 255
1034   // bytes in length) and a series of data sub-blocks. Each data sub-block
1035   // consists of a single byte length value, followed by the data itself. A data
1036   // sub-block with a length of zero terminates the overall block.
1037   // SKIP_SUB_BLOCKS reads a sub-block length value. If it's zero, we've arrived
1038   // at the next block. Otherwise, we enter the SKIP_DATA_THEN_SKIP_SUB_BLOCKS
1039   // state to skip over the sub-block data and return to SKIP_SUB_BLOCKS at the
1040   // start of the next sub-block.
1041 
1042   const uint8_t nextSubBlockLength = aData[0];
1043   if (nextSubBlockLength == 0) {
1044     // We hit the block terminator, so the sequence of data sub-blocks is over;
1045     // begin processing another block.
1046     return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
1047   }
1048 
1049   // Skip to the next sub-block length value.
1050   return Transition::ToUnbuffered(State::FINISHED_SKIPPING_DATA,
1051                                   State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
1052                                   nextSubBlockLength);
1053 }
1054 
SpeedHistogram() const1055 Maybe<Telemetry::HistogramID> nsGIFDecoder2::SpeedHistogram() const {
1056   return Some(Telemetry::IMAGE_DECODE_SPEED_GIF);
1057 }
1058 
1059 }  // namespace image
1060 }  // namespace mozilla
1061