<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>159089</bug_id>
          
          <creation_ts>2016-06-24 06:04:05 -0700</creation_ts>
          <short_desc>REGRESSION(r198782, r201043): [image-decoders] Flickering with some animated gif</short_desc>
          <delta_ts>2016-06-30 06:46:51 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>Platform</component>
          <version>WebKit Local Build</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=159297</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>Gtk, Regression</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Carlos Garcia Campos">cgarcia</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>bugs-noreply</cc>
    
    <cc>sabouhallawa</cc>
    
    <cc>simon.fraser</cc>
    
    <cc>thorton</cc>
    
    <cc>tonikitoo</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1205063</commentid>
    <comment_count>0</comment_count>
    <who name="Carlos Garcia Campos">cgarcia</who>
    <bug_when>2016-06-24 06:04:05 -0700</bug_when>
    <thetext>There&apos;s some flickering when loading big enough animated gifs running the animation in a loop, you can try this one for example:

https://media0.giphy.com/media/l3UceJyj8Wwlkve8M/200.gif

The first time it loads everything is fine, but after the first loop iteration there are several flickering effects, once every time the animation finishes and some others happening in the middle of the animation loop. This doesn&apos;t affect mac ports, only ports using image-decoders implementation. The flickering happens because we fail to render some of the frames, and it has two diferent causes:

 - In r198782, ImageDecoder::createFrameImageAtIndex(), was modified to check first if the image is empty to return early, and then try to get the frame image from the decoder. This is the aone causing flickerin always on the first frame after one iteration. It happens because ImageDecoder::size() is always empty at that point. The first doesn&apos;t happen because the gif is loaded and BitmapImage calls isSizeAvailable() from BitmapImage::dataChanged(). The isSizeAvailable call makes the gif decoder calculate the size. But for the next iterations, frames are cached and BitmapImage already has the decoded data so isSizeAvailable is not called again. When createFrameImageAtIndex() is called again for the first frame, size is empty, until the gif decoder creates the reader again, which happens when frameBufferAtIndex() si called, so after that the size is available. So, we could call isSizeAvailable before checking the size, or simply do the check after the frameBufferAtIndex() as we used to do.

 - In r201043 BitmapImage::destroyDecodedDataIfNecessary() was fixed to use the actual bytes used by the frame in order to decide whether to destroy decoded data or not. This actually revealed a bug, it didn&apos;t happen before because we were never destroying frames before. The bug is in the gif decoder that doesn&apos;t correctly handle the case of destroying only some of the frames from the buffer. The gif decoder is designed to always process the frames in order, the reader keeps an index of the currently processed frame, when some frames are read from the cache, and then we ask the decoder for a not cached frame, the currently processed frame is not in sync with the actual frame we are asking for, and we end do not processing any frame at all.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1205064</commentid>
    <comment_count>1</comment_count>
      <attachid>281971</attachid>
    <who name="Carlos Garcia Campos">cgarcia</who>
    <bug_when>2016-06-24 06:16:18 -0700</bug_when>
    <thetext>Created attachment 281971
Patch</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206029</commentid>
    <comment_count>2</comment_count>
      <attachid>281971</attachid>
    <who name="Antonio Gomes">tonikitoo</who>
    <bug_when>2016-06-28 08:08:17 -0700</bug_when>
    <thetext>Comment on attachment 281971
Patch

I am confident to review it, given the logical changelog explanation.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206097</commentid>
    <comment_count>3</comment_count>
      <attachid>281971</attachid>
    <who name="Said Abou-Hallawa">sabouhallawa</who>
    <bug_when>2016-06-28 11:24:49 -0700</bug_when>
    <thetext>Comment on attachment 281971
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=281971&amp;action=review

&gt; Source/WebCore/platform/image-decoders/ImageDecoder.cpp:319
&gt; +    if (!buffer || buffer-&gt;status() == ImageFrame::FrameEmpty || size().isEmpty())

I don&apos;t like this kind of dependency and implicit hidden calculation. How do I know or remember that to get the size of image in the ImageDecoder I have to call frameBufferAtIndex() first? Can&apos;t we fix this by changing the base class function ImageDecoder::setSize() to be like this:

virtual IntSize size() { return frameBufferAtIndex(0) ? m_size : IntSize(); }</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206315</commentid>
    <comment_count>4</comment_count>
    <who name="Carlos Garcia Campos">cgarcia</who>
    <bug_when>2016-06-28 23:22:18 -0700</bug_when>
    <thetext>(In reply to comment #3)
&gt; Comment on attachment 281971 [details]
&gt; Patch
&gt; 
&gt; View in context:
&gt; https://bugs.webkit.org/attachment.cgi?id=281971&amp;action=review
&gt; 
&gt; &gt; Source/WebCore/platform/image-decoders/ImageDecoder.cpp:319
&gt; &gt; +    if (!buffer || buffer-&gt;status() == ImageFrame::FrameEmpty || size().isEmpty())
&gt; 
&gt; I don&apos;t like this kind of dependency and implicit hidden calculation. How do
&gt; I know or remember that to get the size of image in the ImageDecoder I have
&gt; to call frameBufferAtIndex() first?

Yes, I agree, that&apos;s why I added the comment there. But note that it&apos;s not required to call frameBufferAtIndex specifically, it just happens that frameBufferAtIndex ensures the size is retrieved from the image data. In this case, we just take advantage that we are calling this method to avoid any other check.

&gt; Can&apos;t we fix this by changing the base
&gt; class function ImageDecoder::setSize() to be like this:
&gt; 
&gt; virtual IntSize size() { return frameBufferAtIndex(0) ? m_size : IntSize(); }

I thought about that, although not using frameBufferAtIndex, but isSizeAvailable() instead, that decodes enough data to get the size. However, I thought there was a reason why we have isSizeAvailable() and size() public, instead of just making size() do the isSizeAvailable() implicitly. In this particular case, we would end up decoding twice, first to get the size and then to get the buffer. We could avoid that by checking the size after frameBufferAtIndex (because the isSizeAvailable is cached), but we would be in the same situation.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206327</commentid>
    <comment_count>5</comment_count>
    <who name="Carlos Garcia Campos">cgarcia</who>
    <bug_when>2016-06-29 00:24:25 -0700</bug_when>
    <thetext>Committed r202616: &lt;http://trac.webkit.org/changeset/202616&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206447</commentid>
    <comment_count>6</comment_count>
    <who name="Said Abou-Hallawa">sabouhallawa</who>
    <bug_when>2016-06-29 11:41:22 -0700</bug_when>
    <thetext>(In reply to comment #4)
&gt; (In reply to comment #3)
&gt; &gt; Comment on attachment 281971 [details]
&gt; &gt; Patch
&gt; &gt; 
&gt; &gt; View in context:
&gt; &gt; https://bugs.webkit.org/attachment.cgi?id=281971&amp;action=review
&gt; &gt; 
&gt; &gt; &gt; Source/WebCore/platform/image-decoders/ImageDecoder.cpp:319
&gt; &gt; &gt; +    if (!buffer || buffer-&gt;status() == ImageFrame::FrameEmpty || size().isEmpty())
&gt; &gt; 
&gt; &gt; I don&apos;t like this kind of dependency and implicit hidden calculation. How do
&gt; &gt; I know or remember that to get the size of image in the ImageDecoder I have
&gt; &gt; to call frameBufferAtIndex() first?
&gt; 
&gt; Yes, I agree, that&apos;s why I added the comment there. But note that it&apos;s not
&gt; required to call frameBufferAtIndex specifically, it just happens that
&gt; frameBufferAtIndex ensures the size is retrieved from the image data. In
&gt; this case, we just take advantage that we are calling this method to avoid
&gt; any other check.
&gt; 
&gt; &gt; Can&apos;t we fix this by changing the base
&gt; &gt; class function ImageDecoder::setSize() to be like this:
&gt; &gt; 
&gt; &gt; virtual IntSize size() { return frameBufferAtIndex(0) ? m_size : IntSize(); }
&gt; 
&gt; I thought about that, although not using frameBufferAtIndex, but
&gt; isSizeAvailable() instead, that decodes enough data to get the size.
&gt; However, I thought there was a reason why we have isSizeAvailable() and
&gt; size() public, instead of just making size() do the isSizeAvailable()
&gt; implicitly. In this particular case, we would end up decoding twice, first
&gt; to get the size and then to get the buffer. We could avoid that by checking
&gt; the size after frameBufferAtIndex (because the isSizeAvailable is cached),
&gt; but we would be in the same situation.

I don&apos;t think your reasoning about decoding the first frame twice is correct. The parser of the ImageDecoder is state machine. It moves along the encoded data and changes its state when finishing decoding the data for the current state. All the decoded data, either image metadata or images frames are cached. So querying the size from the first frame should not be repeated when querying the frame itself.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1206658</commentid>
    <comment_count>7</comment_count>
    <who name="Carlos Garcia Campos">cgarcia</who>
    <bug_when>2016-06-29 23:45:58 -0700</bug_when>
    <thetext>(In reply to comment #6)
&gt; (In reply to comment #4)
&gt; &gt; (In reply to comment #3)
&gt; &gt; &gt; Comment on attachment 281971 [details]
&gt; &gt; &gt; Patch
&gt; &gt; &gt; 
&gt; &gt; &gt; View in context:
&gt; &gt; &gt; https://bugs.webkit.org/attachment.cgi?id=281971&amp;action=review
&gt; &gt; &gt; 
&gt; &gt; &gt; &gt; Source/WebCore/platform/image-decoders/ImageDecoder.cpp:319
&gt; &gt; &gt; &gt; +    if (!buffer || buffer-&gt;status() == ImageFrame::FrameEmpty || size().isEmpty())
&gt; &gt; &gt; 
&gt; &gt; &gt; I don&apos;t like this kind of dependency and implicit hidden calculation. How do
&gt; &gt; &gt; I know or remember that to get the size of image in the ImageDecoder I have
&gt; &gt; &gt; to call frameBufferAtIndex() first?
&gt; &gt; 
&gt; &gt; Yes, I agree, that&apos;s why I added the comment there. But note that it&apos;s not
&gt; &gt; required to call frameBufferAtIndex specifically, it just happens that
&gt; &gt; frameBufferAtIndex ensures the size is retrieved from the image data. In
&gt; &gt; this case, we just take advantage that we are calling this method to avoid
&gt; &gt; any other check.
&gt; &gt; 
&gt; &gt; &gt; Can&apos;t we fix this by changing the base
&gt; &gt; &gt; class function ImageDecoder::setSize() to be like this:
&gt; &gt; &gt; 
&gt; &gt; &gt; virtual IntSize size() { return frameBufferAtIndex(0) ? m_size : IntSize(); }
&gt; &gt; 
&gt; &gt; I thought about that, although not using frameBufferAtIndex, but
&gt; &gt; isSizeAvailable() instead, that decodes enough data to get the size.
&gt; &gt; However, I thought there was a reason why we have isSizeAvailable() and
&gt; &gt; size() public, instead of just making size() do the isSizeAvailable()
&gt; &gt; implicitly. In this particular case, we would end up decoding twice, first
&gt; &gt; to get the size and then to get the buffer. We could avoid that by checking
&gt; &gt; the size after frameBufferAtIndex (because the isSizeAvailable is cached),
&gt; &gt; but we would be in the same situation.
&gt; 
&gt; I don&apos;t think your reasoning about decoding the first frame twice is
&gt; correct. The parser of the ImageDecoder is state machine. It moves along the
&gt; encoded data and changes its state when finishing decoding the data for the
&gt; current state. All the decoded data, either image metadata or images frames
&gt; are cached. So querying the size from the first frame should not be repeated
&gt; when querying the frame itself.

Well, I didn&apos;t say we decode the first frame twice, but that we decode data twice. Normally to get the size you only need to decode some data, and to get the frame you need to decode the same data than for the size and more, so my point was that getting the frame directly we decode once and get both. You are indeed right that after getting the size, the reader is created and then getting the frame just reuses the reader, so this micro optimization is probably not worth it. I&apos;ll file a different bug report to make size() always return the right size, then.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>281971</attachid>
            <date>2016-06-24 06:16:18 -0700</date>
            <delta_ts>2016-06-28 08:08:17 -0700</delta_ts>
            <desc>Patch</desc>
            <filename>wcore-gif-flickering.diff</filename>
            <type>text/plain</type>
            <size>5390</size>
            <attacher name="Carlos Garcia Campos">cgarcia</attacher>
            
              <data encoding="base64">ZGlmZiAtLWdpdCBhL1NvdXJjZS9XZWJDb3JlL0NoYW5nZUxvZyBiL1NvdXJjZS9XZWJDb3JlL0No
YW5nZUxvZwppbmRleCA4YWIyYWEyLi5hODFhNGFjIDEwMDY0NAotLS0gYS9Tb3VyY2UvV2ViQ29y
ZS9DaGFuZ2VMb2cKKysrIGIvU291cmNlL1dlYkNvcmUvQ2hhbmdlTG9nCkBAIC0xLDMgKzEsMzkg
QEAKKzIwMTYtMDYtMjQgIENhcmxvcyBHYXJjaWEgQ2FtcG9zICA8Y2dhcmNpYUBpZ2FsaWEuY29t
PgorCisgICAgICAgIFJFR1JFU1NJT04ocjE5ODc4MiwgcjIwMTA0Myk6IFtpbWFnZS1kZWNvZGVy
c10gRmxpY2tlcmluZyB3aXRoIHNvbWUgYW5pbWF0ZWQgZ2lmCisgICAgICAgIGh0dHBzOi8vYnVn
cy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xNTkwODkKKworICAgICAgICBSZXZpZXdlZCBi
eSBOT0JPRFkgKE9PUFMhKS4KKworICAgICAgICBUaGVyZSdzIHNvbWUgZmxpY2tlcmluZyB3aGVu
IGxvYWRpbmcgYmlnIGVub3VnaCBhbmltYXRlZCBnaWZzIHJ1bm5pbmcgdGhlIGFuaW1hdGlvbiBp
biBhIGxvb3AuIFRoZSBmaXJzdCB0aW1lIGl0CisgICAgICAgIGxvYWRzIGV2ZXJ5dGhpbmcgaXMg
ZmluZSwgYnV0IGFmdGVyIHRoZSBmaXJzdCBsb29wIGl0ZXJhdGlvbiB0aGVyZSBhcmUgc2V2ZXJh
bCBmbGlja2VyaW5nIGVmZmVjdHMsIG9uY2UgZXZlcnkKKyAgICAgICAgdGltZSB0aGUgYW5pbWF0
aW9uIGZpbmlzaGVzIGFuZCBzb21lIG90aGVycyBoYXBwZW5pbmcgaW4gdGhlIG1pZGRsZSBvZiB0
aGUgYW5pbWF0aW9uIGxvb3AuIFRoZSBmbGlja2VyaW5nCisgICAgICAgIGhhcHBlbnMgYmVjYXVz
ZSB3ZSBmYWlsIHRvIHJlbmRlciBzb21lIG9mIHRoZSBmcmFtZXMsIGFuZCBpdCBoYXMgdHdvIGRp
ZmVyZW50IGNhdXNlczoKKworICAgICAgICAgLSBJbiByMTk4NzgyLCBJbWFnZURlY29kZXI6OmNy
ZWF0ZUZyYW1lSW1hZ2VBdEluZGV4KCksIHdhcyBtb2RpZmllZCB0byBjaGVjayBmaXJzdCBpZiB0
aGUgaW1hZ2UgaXMgZW1wdHkgdG8KKyAgICAgICAgcmV0dXJuIGVhcmx5LCBhbmQgdGhlbiB0cnkg
dG8gZ2V0IHRoZSBmcmFtZSBpbWFnZSBmcm9tIHRoZSBkZWNvZGVyLiBUaGlzIGlzIHRoZSBhb25l
IGNhdXNpbmcgdGhlIGZsaWNrZXJpbmcKKyAgICAgICAgYWx3YXlzIG9uIHRoZSBmaXJzdCBmcmFt
ZSBhZnRlciBvbmUgaXRlcmF0aW9uLiBJdCBoYXBwZW5zIGJlY2F1c2UgSW1hZ2VEZWNvZGVyOjpz
aXplKCkgaXMgYWx3YXlzIGVtcHR5IGF0IHRoYXQKKyAgICAgICAgcG9pbnQuIFRoZSBmaXJzdCB0
aW1lIGRvZXNuJ3QgaGFwcGVuIGJlY2F1c2UgdGhlIGdpZiBpcyBsb2FkZWQgYW5kIEJpdG1hcElt
YWdlIGNhbGxzIGlzU2l6ZUF2YWlsYWJsZSgpIGZyb20KKyAgICAgICAgQml0bWFwSW1hZ2U6OmRh
dGFDaGFuZ2VkKCkuIFRoZSBpc1NpemVBdmFpbGFibGUgY2FsbCBtYWtlcyB0aGUgZ2lmIGRlY29k
ZXIgY2FsY3VsYXRlIHRoZSBzaXplLiBCdXQgZm9yIHRoZSBuZXh0CisgICAgICAgIGl0ZXJhdGlv
bnMsIGZyYW1lcyBhcmUgY2FjaGVkIGFuZCBCaXRtYXBJbWFnZSBhbHJlYWR5IGhhcyB0aGUgZGVj
b2RlZCBkYXRhIHNvIGlzU2l6ZUF2YWlsYWJsZSBpcyBub3QgY2FsbGVkCisgICAgICAgIGFnYWlu
LiBXaGVuIGNyZWF0ZUZyYW1lSW1hZ2VBdEluZGV4KCkgaXMgY2FsbGVkIGFnYWluIGZvciB0aGUg
Zmlyc3QgZnJhbWUsIHNpemUgaXMgZW1wdHkgdW50aWwgdGhlIGdpZiBkZWNvZGVyCisgICAgICAg
IGNyZWF0ZXMgdGhlIHJlYWRlciBhZ2Fpbiwgd2hpY2ggaGFwcGVucyB3aGVuIGZyYW1lQnVmZmVy
QXRJbmRleCgpIGlzIGNhbGxlZCwgc28gYWZ0ZXIgdGhhdCB0aGUgc2l6ZSBpcworICAgICAgICBh
dmFpbGFibGUuIFNvLCB3ZSBjb3VsZCBjYWxsIGlzU2l6ZUF2YWlsYWJsZSBiZWZvcmUgY2hlY2tp
bmcgdGhlIHNpemUsIG9yIHNpbXBseSBkbyB0aGUgY2hlY2sgYWZ0ZXIgdGhlCisgICAgICAgIGZy
YW1lQnVmZmVyQXRJbmRleCgpIGNhbGwgYXMgd2UgdXNlZCB0byBkby4KKworICAgICAgICAgLSBJ
biByMjAxMDQzIEJpdG1hcEltYWdlOjpkZXN0cm95RGVjb2RlZERhdGFJZk5lY2Vzc2FyeSgpIHdh
cyBmaXhlZCB0byB1c2UgdGhlIGFjdHVhbCBieXRlcyB1c2VkIGJ5IHRoZSBmcmFtZQorICAgICAg
ICBpbiBvcmRlciB0byBkZWNpZGUgd2hldGhlciB0byBkZXN0cm95IGRlY29kZWQgZGF0YSBvciBu
b3QuIFRoaXMgYWN0dWFsbHkgcmV2ZWFsZWQgYSBidWcsIGl0IGRpZG4ndCBoYXBwZW4gYmVmb3Jl
CisgICAgICAgIGJlY2F1c2Ugd2Ugd2VyZSBuZXZlciBkZXN0cm95aW5nIGZyYW1lcyBiZWZvcmUu
IFRoZSBidWcgaXMgaW4gdGhlIGdpZiBkZWNvZGVyIHRoYXQgZG9lc24ndCBjb3JyZWN0bHkgaGFu
ZGxlIHRoZQorICAgICAgICBjYXNlIG9mIGRlc3Ryb3lpbmcgb25seSBzb21lIG9mIHRoZSBmcmFt
ZXMgZnJvbSB0aGUgYnVmZmVyIGNhY2hlLiBUaGUgZ2lmIGRlY29kZXIgaXMgZGVzaWduZWQgdG8g
YWx3YXlzIHByb2Nlc3MgdGhlCisgICAgICAgIGZyYW1lcyBpbiBvcmRlciwgdGhlIHJlYWRlciBr
ZWVwcyBhbiBpbmRleCBvZiB0aGUgY3VycmVudGx5IHByb2Nlc3NlZCBmcmFtZSwgc28gd2hlbiBz
b21lIGZyYW1lcyBhcmUgcmVhZCBmcm9tIHRoZQorICAgICAgICBjYWNoZSwgYW5kIHRoZW4gd2Ug
YXNrIHRoZSBkZWNvZGVyIGZvciBhIG5vdCBjYWNoZWQgZnJhbWUsIHRoZSBjdXJyZW50bHkgcHJv
Y2Vzc2VkIGZyYW1lIGlzIG5vdCBpbiBzeW5jIHdpdGggdGhlCisgICAgICAgIGFjdHVhbCBmcmFt
ZSB3ZSBhcmUgYXNraW5nIGZvciwgYW5kIHdlIGVuZCBkbyBub3QgcHJvY2Vzc2luZyBhbnkgZnJh
bWUgYXQgYWxsLgorCisgICAgICAgICogcGxhdGZvcm0vaW1hZ2UtZGVjb2RlcnMvSW1hZ2VEZWNv
ZGVyLmNwcDoKKyAgICAgICAgKFdlYkNvcmU6OkltYWdlRGVjb2Rlcjo6Y3JlYXRlRnJhbWVJbWFn
ZUF0SW5kZXgpOiBDaGVjayB0aGUgc2l6ZSBhZnRlciBjYWxsaW5nIGZyYW1lQnVmZmVyQXRJbmRl
eCgpLgorICAgICAgICAqIHBsYXRmb3JtL2ltYWdlLWRlY29kZXJzL2dpZi9HSUZJbWFnZURlY29k
ZXIuY3BwOgorICAgICAgICAoV2ViQ29yZTo6R0lGSW1hZ2VEZWNvZGVyOjpjbGVhckZyYW1lQnVm
ZmVyQ2FjaGUpOiBEZWxldGUgdGhlIHJlYWRlciB3aGVuIGNsZWFyaW5nIHRoZSBjYWNoZSBzaW5j
ZSBpdCdzIG91dCBvZiBzeW5jLgorCiAyMDE2LTA2LTI0ICBHeXV5b3VuZyBLaW0gIDxneXV5b3Vu
Zy5raW1Ad2Via2l0Lm9yZz4KIAogICAgICAgICBVbnJldmlld2VkIEVGTCBidWlsZCBmaXguCmRp
ZmYgLS1naXQgYS9Tb3VyY2UvV2ViQ29yZS9wbGF0Zm9ybS9pbWFnZS1kZWNvZGVycy9JbWFnZURl
Y29kZXIuY3BwIGIvU291cmNlL1dlYkNvcmUvcGxhdGZvcm0vaW1hZ2UtZGVjb2RlcnMvSW1hZ2VE
ZWNvZGVyLmNwcAppbmRleCA4ODY3ZGZlLi42ZmMxYTIyIDEwMDY0NAotLS0gYS9Tb3VyY2UvV2Vi
Q29yZS9wbGF0Zm9ybS9pbWFnZS1kZWNvZGVycy9JbWFnZURlY29kZXIuY3BwCisrKyBiL1NvdXJj
ZS9XZWJDb3JlL3BsYXRmb3JtL2ltYWdlLWRlY29kZXJzL0ltYWdlRGVjb2Rlci5jcHAKQEAgLTMx
MiwxMyArMzEyLDExIEBAIGZsb2F0IEltYWdlRGVjb2Rlcjo6ZnJhbWVEdXJhdGlvbkF0SW5kZXgo
c2l6ZV90IGluZGV4KQogCiBOYXRpdmVJbWFnZVB0ciBJbWFnZURlY29kZXI6OmNyZWF0ZUZyYW1l
SW1hZ2VBdEluZGV4KHNpemVfdCBpbmRleCwgU3Vic2FtcGxpbmdMZXZlbCkKIHsKLSAgICAvLyBa
ZXJvLWhlaWdodCBpbWFnZXMgY2FuIGNhdXNlIHByb2JsZW1zIGZvciBzb21lIHBvcnRzLiBJZiB3
ZSBoYXZlIGFuCi0gICAgLy8gZW1wdHkgaW1hZ2UgZGltZW5zaW9uLCBqdXN0IGJhaWwuCi0gICAg
aWYgKHNpemUoKS5pc0VtcHR5KCkpCi0gICAgICAgIHJldHVybiBudWxscHRyOwotCiAgICAgSW1h
Z2VGcmFtZSogYnVmZmVyID0gZnJhbWVCdWZmZXJBdEluZGV4KGluZGV4KTsKLSAgICBpZiAoIWJ1
ZmZlciB8fCBidWZmZXItPnN0YXR1cygpID09IEltYWdlRnJhbWU6OkZyYW1lRW1wdHkpCisgICAg
Ly8gWmVyby1oZWlnaHQgaW1hZ2VzIGNhbiBjYXVzZSBwcm9ibGVtcyBmb3Igc29tZSBwb3J0cy4g
SWYgd2UgaGF2ZSBhbiBlbXB0eSBpbWFnZSBkaW1lbnNpb24sIGp1c3QgYmFpbC4KKyAgICAvLyBJ
dCdzIGltcG9ydGFudCB0byBjaGVjayB0aGUgc2l6ZSBhZnRlciBjYWxsaW5nIGZyYW1lQnVmZmVy
QXRJbmRleCgpIHRvIGVuc3VyZSB0aGUgZGVjb2RlciBoYXMgdXBkYXRlZCB0aGUgc2l6ZS4KKyAg
ICAvLyBTZWUgaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTE1OTA4OS4K
KyAgICBpZiAoIWJ1ZmZlciB8fCBidWZmZXItPnN0YXR1cygpID09IEltYWdlRnJhbWU6OkZyYW1l
RW1wdHkgfHwgc2l6ZSgpLmlzRW1wdHkoKSkKICAgICAgICAgcmV0dXJuIG51bGxwdHI7CiAKICAg
ICAvLyBSZXR1cm4gdGhlIGJ1ZmZlciBjb250ZW50cyBhcyBhIG5hdGl2ZSBpbWFnZS4gRm9yIHNv
bWUgcG9ydHMsIHRoZSBkYXRhCmRpZmYgLS1naXQgYS9Tb3VyY2UvV2ViQ29yZS9wbGF0Zm9ybS9p
bWFnZS1kZWNvZGVycy9naWYvR0lGSW1hZ2VEZWNvZGVyLmNwcCBiL1NvdXJjZS9XZWJDb3JlL3Bs
YXRmb3JtL2ltYWdlLWRlY29kZXJzL2dpZi9HSUZJbWFnZURlY29kZXIuY3BwCmluZGV4IDc5MTUx
NTYuLjlmOTkyYTcgMTAwNjQ0Ci0tLSBhL1NvdXJjZS9XZWJDb3JlL3BsYXRmb3JtL2ltYWdlLWRl
Y29kZXJzL2dpZi9HSUZJbWFnZURlY29kZXIuY3BwCisrKyBiL1NvdXJjZS9XZWJDb3JlL3BsYXRm
b3JtL2ltYWdlLWRlY29kZXJzL2dpZi9HSUZJbWFnZURlY29kZXIuY3BwCkBAIC0xNzYsNiArMTc2
LDEwIEBAIHZvaWQgR0lGSW1hZ2VEZWNvZGVyOjpjbGVhckZyYW1lQnVmZmVyQ2FjaGUoc2l6ZV90
IGNsZWFyQmVmb3JlRnJhbWUpCiAgICAgICAgIGlmIChqLT5zdGF0dXMoKSAhPSBJbWFnZUZyYW1l
OjpGcmFtZUVtcHR5KQogICAgICAgICAgICAgai0+Y2xlYXJQaXhlbERhdGEoKTsKICAgICB9CisK
KyAgICAvLyBXaGVuIHNvbWUgZnJhbWVzIGFyZSBjbGVhcmVkLCB0aGUgcmVhZGVyIGlzIG91dCBv
ZiBzeW5jLCBzaW5jZSB0aGUgY2FsbGVyIG1pZ2h0IGFzayBmb3IgYW55IGZyYW1lIG5vdAorICAg
IC8vIG5lY2Vzc2FyaWx5IGluIHRoZSBvcmRlciBleHBlY3RlZCBieSB0aGUgcmVhZGVyLiBTZWUg
aHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTE1OTA4OS4KKyAgICBtX3Jl
YWRlciA9IG51bGxwdHI7CiB9CiAKIGJvb2wgR0lGSW1hZ2VEZWNvZGVyOjpoYXZlRGVjb2RlZFJv
dyh1bnNpZ25lZCBmcmFtZUluZGV4LCBjb25zdCBWZWN0b3I8dW5zaWduZWQgY2hhcj4mIHJvd0J1
ZmZlciwgc2l6ZV90IHdpZHRoLCBzaXplX3Qgcm93TnVtYmVyLCB1bnNpZ25lZCByZXBlYXRDb3Vu
dCwgYm9vbCB3cml0ZVRyYW5zcGFyZW50UGl4ZWxzKQo=
</data>
<flag name="review"
          id="305804"
          type_id="1"
          status="+"
          setter="tonikitoo"
    />
          </attachment>
      

    </bug>

</bugzilla>