CINXE.COM
Project Zero: July 2018
<!DOCTYPE html> <html class='v2' dir='ltr' lang='en' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='https://googleprojectzero.blogspot.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='https://googleprojectzero.blogspot.com/2018/07/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Project Zero - Atom" href="https://googleprojectzero.blogspot.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Project Zero - RSS" href="https://googleprojectzero.blogspot.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Project Zero - Atom" href="https://www.blogger.com/feeds/4838136820032157985/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='https://googleprojectzero.blogspot.com/2018/07/' property='og:url'/> <meta content='Project Zero' property='og:title'/> <meta content='News and updates from the Project Zero team at Google' property='og:description'/> <title>Project Zero: July 2018</title> <style type='text/css'>@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;font-stretch:normal;font-display:swap;src:url(//fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVY.eot);}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#000000"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#000000"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="transparent"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#eeeeee" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 12px Open Sans; color: #000000; background: #eeeeee none repeat scroll top left; padding: 0 0 0 0; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #2288bb; } a:visited { text-decoration:none; color: #888888; } a:hover { text-decoration:underline; color: #33aaff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent none repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent none repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 0 #333333; box-shadow: 0 0 0 rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 40px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: transparent none repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 40px Open Sans; color: #000000; text-shadow: 0 0 0 rgba(0, 0, 0, .2); } .Header h1 a { color: #000000; } .Header .description { font-size: 18px; color: #000000; } .header-inner .Header .titlewrapper { padding: 22px 0; } .header-inner .Header .descriptionwrapper { padding: 0 0; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #dddddd; } .tabs-inner .section:first-child ul { margin-top: -1px; border-top: 1px solid #dddddd; border-left: 1px solid #dddddd; border-right: 1px solid #dddddd; } .tabs-inner .widget ul { background: transparent none repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #dddddd; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 12px Open Sans; color: #000000; border-left: 1px solid #ffffff; border-right: 1px solid #dddddd; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid transparent; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid transparent; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid transparent; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px 'Trebuchet MS',Trebuchet,Verdana,sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: #bbbbbb; color: #ffffff; padding: 0.4em; letter-spacing: 3px; margin: inherit; } .main-inner { padding-top: 35px; padding-bottom: 65px; } .main-inner .column-center-inner { padding: 0 0; } .main-inner .column-center-inner .section { margin: 0 1em; } .post { margin: 0 0 45px 0; } h3.post-title, .comments h4 { font: normal normal 22px Open Sans; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #eeeeee; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #666666; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #eeeeee; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid transparent; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #eeeeee; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #eeeeee; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid transparent; } .blog-pager { background: transparent url(//www.blogblog.com/1kt/simple/paging_dot.png) repeat-x scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 1px dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #000000; } .mobile-link-button { background-color: #2288bb; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #dddddd; border-bottom: 1px solid #dddddd; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #dddddd; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 1120px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 1120px; max-width: 1120px; _width: 1120px; } .main-inner .columns { padding-left: 0; padding-right: 310px; } .main-inner .fauxcolumn-center-outer { left: 0; right: 310px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0") - parseInt("310px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0; } .main-inner .fauxcolumn-right-outer { width: 310px; } .main-inner .column-left-outer { width: 0; right: 100%; margin-left: -0; } .main-inner .column-right-outer { width: 310px; margin-right: -310px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } body#layout div.add_widget { padding: 8px; } body#layout div.add_widget a { margin-left: 32px; } --></style> <script type='text/javascript'> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-240546891-1', 'auto', 'blogger'); ga('blogger.send', 'pageview'); </script> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=4838136820032157985&zx=dd12d16f-47b1-45ec-9a52-9d6602fe5782' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=4838136820032157985&zx=dd12d16f-47b1-45ec-9a52-9d6602fe5782' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body class='loading'> <div class='navbar section' id='navbar' name='Navbar'><div class='widget Navbar' data-version='1' id='Navbar1'><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar/4838136820032157985?origin\x3dhttps://googleprojectzero.blogspot.com', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script><script type="text/javascript"> (function() { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '//pagead2.googlesyndication.com/pagead/js/google_top_exp.js'; var head = document.getElementsByTagName('head')[0]; if (head) { head.appendChild(script); }})(); </script> </div></div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header' name='Header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner'> <div class='titlewrapper'> <h1 class='title'> <a href='https://googleprojectzero.blogspot.com/'> Project Zero </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>News and updates from the Project Zero team at Google</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol' name='Cross-Column'></div> <div class='tabs no-items section' id='crosscol-overflow' name='Cross-Column 2'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main' name='Main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <h2 class='date-header'><span>Thursday, July 26, 2018</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqgonSA0dxi-0tpDJVx76ZtJVCabd8_I4ryeRJIbdAyvP4kDOaJxLuJcOtuUUttIXF9Pdl3m32vNuFowyk8k0KZtm5djQ7LGkDY37lUzID2SJQhVivsaxzO5kf6-Q2WKxcx80i_w1GYV_k7Wx6MCQPbwknsNkAiyzDZY9Fwi4PaSRrwNbzlOI2rVSj/s302/image1.png' itemprop='image_url'/> <meta content='4838136820032157985' itemprop='blogId'/> <meta content='2598238453898476096' itemprop='postId'/> <a name='2598238453898476096'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://googleprojectzero.blogspot.com/2018/07/drawing-outside-box-precision-issues-in.html'>Drawing Outside the Box: Precision Issues in Graphic Libraries</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-2598238453898476096' itemprop='description articleBody'> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">By Mark Brand and Ivan Fratric, Google Project Zero</span></div> <b id="docs-internal-guid-66a8a496-d776-b0c1-f5d5-4f7a867b6dbe" style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In this blog post, we are going to write about a seldom seen vulnerability class that typically affects graphic libraries (though it can also occur in other types of software). The root cause of such issues is using limited precision arithmetic in cases where a precision error would invalidate security assumptions made by the application.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">While we could also call other classes of bugs precision issues, namely integer overflows, the major difference is: with integer overflows, we are dealing with arithmetic operations where the magnitude of the result is </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">too large</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> to be accurately represented in the given precision. With the issues described in this blog post, we are dealing with arithmetic operations where the magnitude of the result or a part of the result is </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">too small</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> to be accurately represented in the given precision.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">These issues can occur when using floating-point arithmetic in operations where the result is security-sensitive, but, as we’ll demonstrate later, can also occur in integer arithmetic in some cases.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Let’s look at a trivial example:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float a = 100000000;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float b = 1;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float c = a + b;</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">If we were making the computation with arbitrary precision, the result would be 100000001. However, since </span><a href="https://en.wikipedia.org/wiki/IEEE_754" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">float</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> typically only allows for 24 bits of precision, the result is actually going to be 100000000. If an application makes the normally reasonable assumption that </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">a > 0</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b > 0</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> implies that </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">a + b</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">> a</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, then this could lead to issues.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In the example above, the difference between </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">a</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is so significant that </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> completely vanishes in the result of the calculation, but precision errors also happen if the difference is smaller, for example</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float a = 1000;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float b = 1.1111111;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: justify;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float c = a + b;</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The result of the above computation is going to be </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1001.111084</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and not </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1001.1111111</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> which would be the accurate result. Here, only a part of </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is lost, but even such results can sometimes have interesting consequences.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">While we used the </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">float</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> type in the above examples, and in these particular examples using </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">double</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> would result in more accurate computation, similar precision errors can happen with </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">double </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">as well.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In the remainder of this blog post, we are going to show several examples of precision issues with security impact. These issues were independently explored by two Project Zero members: Mark Brand, who looked at SwiftShader, a software OpenGL implementation used in Chrome, and Ivan Fratric, who looked at the Skia graphics library, used in Chrome and Firefox. </span></div> <h1 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 20pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 20pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SwiftShader</span></h1> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SwiftShader is “a high-performance CPU-based implementation of the OpenGL ES and Direct3D 9 graphics APIs”. It’s used in </span><a href="https://blog.chromium.org/2016/06/universal-rendering-with-swiftshader.html" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">Chrome</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> on all platforms as a fallback rendering option to work around limitations in graphics hardware or drivers, allowing universal use of WebGL and other advanced javascript rendering APIs on a far wider range of devices.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The code in SwiftShader needs to handle emulating a wide range of operations that would normally be performed by the GPU. One operation that we commonly think of as essentially “free” on a GPU is upscaling, or drawing from a small source texture to a larger area, for example on the screen. This requires computing memory indexes using non-integer values, which is where the </span><a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1584" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">vulnerability</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> occurs.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">As noted in the original bug report, the code that we’ll look at here is not quite the code which is actually run in practice - SwiftShader uses an LLVM-based JIT engine to optimize performance-critical code at runtime, but that code is more difficult to understand than their fallback implementation, and both contain the same bug, so we’ll discuss the fallback code. This code is the copy-loop used to copy pixels from one surface to another during rendering:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> source->lockInternal((int)sRect.x0, (int)sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float w = sRect.width() / dRect.width();</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float h = sRect.height() / dRect.height();</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> const float xStart = sRect.x0 + 0.5f * w;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float y = sRect.y0 + 0.5f * h;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> float x = xStart;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> for(int j = dRect.y0; j < dRect.y1; j++)</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> {</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x = xStart;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> for(int i = dRect.x0; i < dRect.x1; i++)</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> {</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> // FIXME: Support RGBA mask</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> dest->copyInternal(source, i, j, x, y, options.filter);</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x += w;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> }</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> y += h;</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> }</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> source->unlockInternal();</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> dest->unlockInternal();</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><br> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">So - what highlights this code as problematic? We know prior to entering this function that all the bounds-checking has already been performed, and that any call to </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">copyInternal</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> with </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">(i, j)</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> in </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dRect</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">(x, y)</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> in </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">sRect</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> will be safe.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The examples in the introduction above show cases where the resulting precision error means that a rounding-down occurs - in this case that wouldn’t be enough to produce an interesting security bug. Can we cause floating-point imprecision to result in a larger-than-correct value, leading to </span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">(x, y)</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> values that are larger than expected?</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">If we look at the code, the intention of the developers is to compute the following:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> for(int j = dRect.y0; j < dRect.y1; j++)</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> {</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> for(int i = dRect.x0; i < dRect.x1; i++)</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x = xStart + (i * w);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> Y = yStart + (j * h);</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> dest->copyInternal(source, i, j, x, y, options.filter);</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> }</span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: 'Courier New'; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> }</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">If this approach had been used instead, we’d still have precision errors - but without the iterative calculation, there’d be no propagation of the error, and we could expect the eventual magnitude of the precision error to be stable, and in direct proportion to the size of the operands. With the iterative calculation as performed in the code, the errors start to propagate/snowball into a larger and larger error.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">There are ways to estimate the maximum error in floating point calculations; and if you really, really need to avoid having extra bounds checks, using this kind of approach and making sure that you have conservative safety margins around those maximum errors might be a complicated and error-prone way to solve this issue. It’s not a great approach to identifying the pathological values that we want here to demonstrate a vulnerability; so instead we’ll take a brute-force approach. </span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Instinctively, we’re fairly sure that the multiplicative implementation will be roughly correct, and that the implementation with iterative addition will be much less correct. Given that the space of possible inputs is small (Chrome disallows textures with width or height greater than 8192), we can just run a brute force over all ratios of source width to destination width, comparing the two algorithms, and seeing where the results are most different. (Note that SwiftShader also limits us to even numbers). This leads us to the values of 5828, 8132; and if we compare the computations in this case (left side is the iterative addition, right side is the multiplication):</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">0: 1.075012 1.075012</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1: 1.791687 1.791687</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1000: 717.749878 717.749878 Up to here (at the precision shown) the values are still identical</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1001: 718.466553 718.466553</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2046: 1467.391724 1467.391724 At this point, the first significant errors start to occur, but note</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2047: 1468.108398 1468.108521 that the "incorrect" result is smaller than the more precise one.</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2856: 2047.898315 2047.898438</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2857: 2048.614990 2048.614990 Here our two computations coincide again, briefly, and from here onwards</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2858: 2049.331787 2049.331787 the precision errors consistently favour a larger result than the more</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2859: 2050.048584 2050.048340 precise calculation.</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">8129: 5827.567871 5826.924805</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">8130: 5828.284668 5827.641602</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">8131: 5829.001465 5828.358398 The last index is now sufficiently different that int conversion results in an oob index.</span><span style="background-color: white; color: black; font-family: Arial; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><br class="kix-line-break" /></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><br> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">(Note also that there will also be error in the “safe” calculation; it’s just that the lack of error propagation means that that error will remain directly proportional to the size of the input error, which we expect to be “small.”)</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">We can indeed see that, the multiplicative algorithm would remain within bounds; but that the iterative algorithm can return an index that is outside the bounds of the input texture!</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">As a result, we read an entire row of pixels past the end of our texture allocation - and this can be easily leaked back to javascript using WebGL. Stay tuned for an upcoming blog post in which we’ll use this vulnerability together with another unrelated issue in SwiftShader to take control of the GPU process from javascript.</span></div> <h1 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 20pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 20pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Skia</span></h1> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Skia is a graphics library used, among other places, in Chrome, Firefox and Android. In the web browsers it is used for example when drawing to a canvas HTML element using </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">CanvasRenderingContext2D</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> or when drawing SVG images. Skia is also used when drawing various other HTML elements, but canvas element and SVG images are more interesting from the security perspective because they enable more direct control over the objects being drawn by the graphic library.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The most complex type of object (and therefore, most interesting from the security perspective) that Skia can draw is a </span><a href="https://skia.org/user/api/SkPath_Reference" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">path</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. A path is an object that consists of elements such as lines, but also more complex curves, in particular quadratic or cubic </span><a href="https://en.wikipedia.org/wiki/Spline_(mathematics)" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">splines</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Due to the way software drawing algorithms work in Skia, the precision issues are very much possible and quite impactful when they happen, typically leading to out-of-bounds writes.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">To understand why these issues can happen, let’s assume you have an image in memory (represented as a buffer with </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">size</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">height</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">color size</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">). Normally, when drawing a pixel with coordinates (</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">y</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">) and color </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">c</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, you would want to make sure that the pixel actually falls within the space of the image, specifically that 0 <= </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> < </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and 0 <= </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">y</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> < </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">height</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. Failing to check this could result in attempting to write the pixel outside the bounds of the allocated buffer. In computer graphics, making sure that only the objects in the image region are being drawn is called </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">clipping</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">So, where is the problem? Making a clip check for every pixel is expensive in terms of CPU cycles and Skia prides itself on speed. So, instead of making a clip check for every pixel, what Skia does is, it first makes the clip check on an entire object (e.g. line, path or any other type of object being drawn). Depending on the clip check, there are three possible outcomes:</span></div> <b style="font-weight: normal;"><br /></b> <ol style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The object is completely outside of the drawing area: The drawing function doesn’t draw anything and returns immediately.</span></div> </li> </ol> <b style="font-weight: normal;"><br /></b> <ol start="2" style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The object is partially inside the drawing area: The drawing function proceeds with per-pixel clip enabled (usually by relying on </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkBlitter.h?l=187&rcl=c640d0dc96924699fdbb1a3cbdc907aa07b1cb3c" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkRectClipBlitter</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">).</span></div> </li> </ol> <b style="font-weight: normal;"><br /></b> <ol start="3" style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The entire object is in the drawing area: The drawing function draws directly into the buffer </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">without</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> performing per-pixel clip checks.</span></div> </li> </ol> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The problematic scenario is c) where the clip check is performed only per-object and the more precise, per-pixel checks are disabled. This means, if there is a precision issue somewhere between the per-object clip check and the drawing of pixels and if the precision issue causes the pixel coordinates to go outside of the drawing area, this could result in a security vulnerability.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">We can see per-object clip checks leading to dropping per-pixel checks in several places, for example:</span></div> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=d92a739d72ae70fc8122dc077b0f751d4b1dd023&l=497" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">hair_path</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> (function for drawing a path without filling), </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=d92a739d72ae70fc8122dc077b0f751d4b1dd023&l=504" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">clip</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is initially set to null (which disables clip checks). The clip is only set if the bounds of the path, </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=d92a739d72ae70fc8122dc077b0f751d4b1dd023&l=511" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">rounded up and extended by 1 or 2</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> depending on the drawing options </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=d92a739d72ae70fc8122dc077b0f751d4b1dd023&l=515" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">don’t fit in the drawing area</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. Extending the path bounds by 1 seems like a pretty large safety margin, but it is actually the least possible safe value because drawing objects with antialiasing on will sometimes result in drawing to nearby pixels.</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&rcl=50dbc0949fb256a316163143e649028eeed2970a&l=617" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkScan::FillPath</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> (function for filling a path with antialiasing turned off), the bounds of the path are first extended by </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&l=575&rcl=50dbc0949fb256a316163143e649028eeed2970a" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">kConservativeRoundBias</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&l=645&rcl=50dbc0949fb256a316163143e649028eeed2970a" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">rounded</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> to obtain the “conservative” path bounds. A </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&rcl=50dbc0949fb256a316163143e649028eeed2970a&l=653" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkScanClipper</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> object is then created for the current path. As we can see in the </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&l=534&rcl=50dbc0949fb256a316163143e649028eeed2970a" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">definition</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> of SkScanClipper, it will only use SkRectClipBlitter if the x coordinates of the path bounds are outside the drawing area or if irPreClipped is true (which only happens when path coordinates are very large).</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Similar patterns can be seen in other drawing functions.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Before we take a closer look at the issues, it is useful to quickly go over various number formats used by Skia:</span></div> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <a href="https://cs.chromium.org/chromium/src/third_party/skia/include/core/SkScalar.h?l=16&rcl=9236b02264d4b15208be3b8b8919f4ed441a3c85" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkScalar</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is a 32-bit floating point number</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkFDot6.h?l=16&rcl=c640d0dc96924699fdbb1a3cbdc907aa07b1cb3c" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkFDot6</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is defined as an integer, but it is actually a fixed-point number with 26 bits to the left and 6 bits to the right of the decimal point. For example, SkFDot6 value of 0x00000001 represents the number 1/64.</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <a href="https://cs.chromium.org/chromium/src/third_party/skia/include/private/SkFixed.h?l=23&rcl=c640d0dc96924699fdbb1a3cbdc907aa07b1cb3c" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkFixed</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is also a fixed-point number, this time with 16 bits to the left and 16 bits to the right of the decimal point. For example, SkFixed value of 0x00000001 represents 1/(2**16)</span></div> </li> </ul> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Precision error with integer to float conversion</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">We discovered the initial problem when doing </span><a href="https://googleprojectzero.blogspot.com/2017/09/the-great-dom-fuzz-off-of-2017.html" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">DOM fuzzing</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> against Firefox last year. </span><a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1155" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">This issue</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> where Skia wrote out-of-bounds caught our eye so we investigated further. It turned out the root cause was a discrepancy in the way Skia converted floating point to ints in several places. When making the per-path clip check, the lower coordinates (left and top of the bounding box) were rounded using this function:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">static inline int round_down_to_int(SkScalar x) {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> double xx = x;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> xx -= 0.5;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> return (int)ceil(xx);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Looking at the code you see that it will return a number greater or equal to zero (which is necessary for passing the path-level clip check) for numbers that are strictly larger than -0.5. However, in another part of the code, specifically SkEdge::setLine if SK_RASTERIZE_EVEN_ROUNDING is defined (which is the case in Firefox), floats are rounded to integers differently, using the following function:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">inline SkFDot6 SkScalarRoundToFDot6(SkScalar x, int shift = 0)</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">{</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> union {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> double fDouble;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> int32_t fBits[2];</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> } tmp;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> int fractionalBits = 6 + shift;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> double magic = (1LL << (52 - (fractionalBits))) * 1.5;</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> tmp.fDouble = SkScalarToDouble(x) + magic;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">#ifdef SK_CPU_BENDIAN</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> return tmp.fBits[1];</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">#else</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> return tmp.fBits[0];</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">#endif</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Now let’s take a look at what these two functions return for a number -0.499. For this number, round_down_to_int returns 0 (which always passes the clipping check) and SkScalarRoundToFDot6 returns -32 which corresponds to -0.5, so we actually end up with a number that is smaller than the one we started with.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">That’s not the only problem, though, because there’s another place where a precision error occurs in SkEdge::setLine.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Precision error when multiplying fractions</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SkEdge::setLine calls SkFixedMul which is defined as:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">static inline SkFixed(SkFixed a, SkFixed b) {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> return (SkFixed)((int64_t)a * b >> 16);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">This function is for multiplying two SkFixed numbers. An issue comes up when using this function to multiply negative numbers. Let’s look at a small example. Let’s assume a = -1/(2**16) and b = 1/(2**16). If we multiply these two numbers on paper, the result is -1/(2**32). However, due to the way SkFixedMul works, specifically because the right shift is used to convert the result back to SkFixed format, the result we actually end up with is 0xFFFFFFFF which is SkFixed for -1/(2**16). Thus, we end up with a result with a magnitude much larger than expected.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">As the result of this multiplication is used by SkEdge::setLine to adjust the x coordinate of the initial line point </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.h?rcl=38911a7cb53474575e1cd1cb545902b50ee00889&l=125" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">here</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, we can use the issue in SkFixedMul to cause an additional error up to 1/64 of a pixel to go outside of the drawing area bounds.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">By combining the previous two issues, it was possible to get the x coordinate of a line sufficiently small (smaller than -0.5), so that, when a fractional representation was rounded to an integer </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Path.cpp?g=0&rcl=a33b43d796f03e2f4b5abd8060272f4f775d7390&l=247" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">here</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, Skia attempted to draw at coordinates with </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = -1, which is clearly outside the image bounds. This then led to an out-of-bounds write as can be seen in the </span><a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1155" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">original bug report</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. This bug could be exploited in Firefox by drawing an SVG image with coordinates as described in the previous section.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Floating point precision error when converting splines to line segments</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">When drawing paths, Skia is going to convert all non-linear curves (conic shapes, quadratic and cubic splines) to line segments. Perhaps unsurprisingly, these conversions suffer from precision errors.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The conversion of splines into line segments happen in several places, but the most susceptible to floating-point precision errors are </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&l=233&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">hair_quad</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> (used for drawing quadratic curves) and </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467&l=359" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">hair_cubic</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> (used for drawing cubic curves). Both of these functions are called from </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&l=501&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">hair_path</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, which we already mentioned above. Because (unsurprisingly), larger precision errors occur when dealing with cubic splines, we’ll only consider the cubic case here.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">When approximating the spline, first the cubic coefficients are computed in </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkGeometry.h?g=0&l=375&rcl=b9bfb7b275d11eb6ba90dc2dfa9cfa9f73cc613e" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkCubicCoeff</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. The most interesting part is:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fA = P3 + three * (P1 - P2) - P0;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fB = three * (P2 - times_2(P1) + P0);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fC = three * (P1 - P0);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fD = P0;</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Where </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">P1</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">P2</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">P3</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> are input points and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fA</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fB</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fC</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fD</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> are output coefficients. The line segment points are then computed in </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467&l=359" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">hair_cubic</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> using the following code</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">const Sk2s dt(SK_Scalar1 / lines);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Sk2s t(0);</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Sk2s A = coeff.fA;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Sk2s B = coeff.fB;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Sk2s C = coeff.fC;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Sk2s D = coeff.fD;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">for (int i = 1; i < lines; ++i) {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> t = t + dt;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> Sk2s p = ((A * t + B) * t + C) * t + D;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> p.store(&tmp[i]);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Where </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is the output point and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">lines</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is the number of line segments we are using to approximate the curve. Depending on the length of the spline, a cubic spline can be approximated with up to 512 lines.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">It is obvious that the arithmetic here is not going to be precise. As identical computations happen for </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">y</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinates, let’s just consider the </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinate in the rest of the post.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Let’s assume the width of the drawing area is 1000 pixels. Because hair_path is used for drawing path with antialiasing turned on, it needs to make sure that all points of the path are between 1 and 999, which is done in the initial, path-level clip check. Let’s consider the following coordinates that all pass this check:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p0 = 1.501923</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p1 = 998.468811</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p2 = 998.998779</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p3 = 999.000000</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">For these points, the coefficients are as follows</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">a = 995.908203</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b = -2989.310547</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">c = 2990.900879</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">d = 1.501923</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">If you do the same computation in larger precision, you’re going to notice that the numbers here aren’t quite correct. Now let’s see what happens if we approximate the spline with 512 line segments. This results in 513 </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinates:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">0: 1.501923</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1: 7.332130</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2: 13.139574</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">3: 18.924301</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">4: 24.686356</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">5: 30.425781</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">500: 998.986389</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">501: 998.989563</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">502: 998.992126</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">503: 998.994141</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">504: 998.995972</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">505: 998.997314</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">506: 998.998291</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">507: 998.999084</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">508: 998.999695</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">509: 998.999878</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">510: 999.000000</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">511: 999.000244</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">512: 999.000000</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">We can see that the </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinate keeps growing and at point 511 clearly goes outside of the “safe” area and grows larger than 999.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">As it happens, this isn’t sufficient to trigger an out-of-bounds write, because, due to how drawing antialiased lines works in Skia, we need to go at least 1/64 of a pixel outside of the clip area for it to become a security issue. However, an interesting thing about the precision errors in this case is that the larger the drawing area, the larger the error that can happen.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">So let’s instead consider a drawing area of 32767 pixels (maximum canvas size in Chrome). The initial clipping check then checks that all path points are in the interval [1, 32766]. Now let’s consider the following points:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p0 = 1.7490234375</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p1 = 32765.9902343750</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p2 = 32766.000000</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">p3 = 32766.000000</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The corresponding coefficients</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">a = 32764.222656</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">b = -98292.687500</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">c = 98292.726562</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">d = 1.749023</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">And the corresponding line approximation</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">0: 1.74902343</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1: 193.352295</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2: 384.207123</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">3: 574.314941</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">4: 763.677246</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">5: 952.295532</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">…</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">505: 32765.925781</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">506: 32765.957031</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">507: 32765.976562</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">508: 32765.992188</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">509: 32766.003906</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">510: 32766.003906</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">511: 32766.015625</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">512: 32766.000000</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">You can see that we went out-of-bounds significantly more at index 511.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Fortunately for Skia and unfortunately for aspiring attackers, this bug can’t be used to trigger memory corruption, at least not in the up-to-date version of skia. The reason is </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkBitmapDevice.cpp?l=42&rcl=41f4f31cd7dadd1123600c38faa8fef6bd7fb29c" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkDrawTiler</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. Whenever Skia draws using SkBitmapDevice (as opposed to using a GPU device) and the drawing area is larger than 8191 pixels in any dimension, instead of drawing the whole image at once, Skia is going to split it into tiles of size (at most) 8191x8191 pixels. This </span><a href="https://skia.googlesource.com/skia.git/+/b5e1f7558052cc60deaf23ccc2c898d1c6c94c09" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">change</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> was made in March, not for security reasons, but to be able to support larger drawing surfaces. However, it still effectively prevented us from exploiting this issue and will also prevent exploiting other cases where a surface larger than 8191 is required to reach the precision error of a sufficient magnitude.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Still, this bug was exploitable before March and we think it nicely demonstrates the concept of precision errors.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Integer precision error when converting splines to line segments</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">There is another place where splines are approximated as line segments when drawing (in this case: filling) paths that was also affected by a precision error, in this case an exploitable one. Interestingly, here the precision error wasn’t in floating-point but rather in fixed-point arithmetic.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The error happens in </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.cpp?rcl=5eb8fc585e9b3c9ccc82b0921986e1020ddaff23&l=181" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkQuadraticEdge::setQuadraticWithoutUpdate</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.cpp?rcl=5eb8fc585e9b3c9ccc82b0921986e1020ddaff23&l=350" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkCubicEdge::setCubicWithoutUpdate</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. For simplicity, we are again going to concentrate just on the cubic spline version and, again, only on the </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinate.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.cpp?rcl=5eb8fc585e9b3c9ccc82b0921986e1020ddaff23&l=350" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkCubicEdge::setCubicWithoutUpdate</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, the curve coordinates are first converted to SkFDot6 type (integer with 6 bits used for fraction). After that, parameters corresponding to the first, second and third derivative of the curve at the initial point are going to be computed:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SkFixed B = SkFDot6UpShift(3 * (x1 - x0), upShift);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SkFixed C = SkFDot6UpShift(3 * (x0 - x1 - x1 + x2), upShift);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">SkFixed D = SkFDot6UpShift(x3 + 3 * (x1 - x2) - x0, upShift);</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCx = SkFDot6ToFixed(x0);</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx = B + (C >> shift) + (D >> 2*shift); // biased by shift</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDDx = 2*C + (3*D >> (shift - 1)); // biased by 2*shift</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDDDx = 3*D >> (shift - 1); // biased by 2*shift</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Where </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x0</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x1</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x2</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x3</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> are </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> coordinates of the 4 points that define the cubic spline and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">shift</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">upShift</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> depend on the length of the curve (this corresponds to the number of linear segments the curve is going to be approximated in). For simplicity, we can assume </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">shift</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">upShift</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = 6 (maximum possible values).</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Now let’s see what happens for some very simple input values:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x0 = -30</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x1 = -31</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x2 = -31</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x3 = -31</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Note that </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x0</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x1</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x2</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x3</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> are of the type SkFDot6 so value -30 corresponds to -0.46875 and -31 to -0.484375. These are close to -0.5 but not quite and are thus perfectly safe when rounded. Now let’s examine the values of the computed parameters:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">B = -192</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">C = 192</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D = -64</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCx = -30720</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx = -190</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDDx = 378</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDDDx = -6</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Do you see where the issue is? Hint: it’s in the formula for </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">When computing </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> (first derivation of a curve), the value of </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> needs is right-shifted by 12. However, </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is too small to do that precisely, and since </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is negative, the right shift</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D >> 2*shift</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Is going to result in -1, which is </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">larger</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> in magnitude than the intended result. (Since </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">D</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is of type SkFixed its actual value is -0.0009765625 and the shift, when interpreted as division by 4096, would result in -2.384185e-07). Because of this, the whole </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> ends up as a larger negative value than it should (-190 vs. -189.015).</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Afterwards, the value of </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">fCDx</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> gets used when calculating the </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> value of line segments. This happens in SkCubicEdge::updateCubic on </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.cpp?l=477&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">this line</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">newx = oldx + (fCDx >> dshift);</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> values, when approximating the spline with 64 line segments (maximum for this algorithm), are going to be (expressed as index, integer SkFixed value and the corresponding floating point value):</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">index raw interpretation</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">0: -30720 -0.46875</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">1: -30768 -0.469482</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">2: -30815 -0.470200</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">3: -30860 -0.470886</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">4: -30904 -0.471558</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">5: -30947 -0.472214</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">31: -31683 -0.483444</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">32: -31700 -0.483704</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">33: -31716 -0.483948</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">34: -31732 -0.484192</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">35: -31747 -0.484421</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">36: -31762 -0.484650</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">37: -31776 -0.484863</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">38: -31790 -0.485077</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">...</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">60: -32005 -0.488358</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">61: -32013 -0.488480</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">62: -32021 -0.488602</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">63: -32029 -0.488724</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">64: -32037 -0.488846</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">You can see that for the 35th point, the </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> value (-0.484421) ends up being smaller than the smallest input point (-0.484375) and the trend continues for the later points. This value would still get rounded to 0 though, but there is another problem.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The x values computed in SkCubicEdge::updateCubic are passed to SkEdge::updateLine, where they are converted from SkFixed type to SkFDot6 on the </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkEdge.cpp?g=0&l=114&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">following lines</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x0 >>= 10;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x1 >>= 10;</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Another right shift! And when, for example, SkFixed value -31747 gets shifted we end up with SkFDot6 value of -32 which represents -0.5.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">At this point we can use the same trick described above in the “</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Precision error when multiplying fractions</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">” section to go smaller than -0.5 and break out of the image bounds. In other words, we can make Skia draw to x = -1 when drawing a path.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">But, what can we do with it?</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In general, given that Skia allocates image pixels as a single allocation that is organized row by row (as most other software would allocate bitmaps), there are several cases of what can happen with precision issues. If we assume an </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> x </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">height</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> image and that we are only able to go one pixel out of bounds:</span></div> <b style="font-weight: normal;"><br /></b> <ol style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Drawing to y = -1 or y = height immediately leads to heap out-of-bounds write</span></div> </li> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Drawing to x = -1 with y = 0 immediately leads to a heap underflow of 1 pixel</span></div> </li> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Drawing to x = width with y = height - 1 immediately leads to heap overflow of 1 pixel</span></div> </li> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Drawing to x = -1 with y > 0 leads to a pixel “spilling” to the previous image row</span></div> </li> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: lower-alpha; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Drawing to x = height with y < height-1 leads to a pixel “spilling” to the next image row</span></div> </li> </ol> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">What we have here is scenario d) - unfortunately we can’t draw to x = 1 with y = 0 because the precision error needs to accumulate over the growing values of y.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Let’s take a look at the following example SVG image:</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><style></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">body {</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> margin-top: 0px;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> margin-right: 0px;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> margin-bottom: 0px;</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> margin-left: 0px</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">}</span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"></style></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><path d="M -0.46875 -0.484375 C -0.484375 -0.484375, -0.484375 -0.484375, -0.484375 100 L 1 100 L 1 -0.484375" fill="red" shape-rendering="crispEdges" /></span></div> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"></svg></span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">If we render this in an unpatched version of Firefox what we see is shown in the following image. Notice how the SVG only contains coordinates on the left side of the screen, but some of the red pixels get drawn on the right. This is because, due to the way images are allocated, drawing to </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = -1 and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">y</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">row</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is equal to drawing to </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> - 1 and </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">y</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">row</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> - 1.</span></div> <a href='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqgonSA0dxi-0tpDJVx76ZtJVCabd8_I4ryeRJIbdAyvP4kDOaJxLuJcOtuUUttIXF9Pdl3m32vNuFowyk8k0KZtm5djQ7LGkDY37lUzID2SJQhVivsaxzO5kf6-Q2WKxcx80i_w1GYV_k7Wx6MCQPbwknsNkAiyzDZY9Fwi4PaSRrwNbzlOI2rVSj/s302/image1.png' style='display: block; padding: 1em 0; text-align: center;'><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqgonSA0dxi-0tpDJVx76ZtJVCabd8_I4ryeRJIbdAyvP4kDOaJxLuJcOtuUUttIXF9Pdl3m32vNuFowyk8k0KZtm5djQ7LGkDY37lUzID2SJQhVivsaxzO5kf6-Q2WKxcx80i_w1GYV_k7Wx6MCQPbwknsNkAiyzDZY9Fwi4PaSRrwNbzlOI2rVSj/s302/image1.png" style="max-height: 750; max-width: 600;" /></a> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Opening an SVG image that triggers a Skia precision issue in Firefox. If you look closely you’ll notice some red pixels on the right side of the image. How did those get there? :) </span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Note that we used Mozilla Firefox and not Google Chrome because, due to SVG drawing internals (specifically: Skia seems to draw the entire image at once, while Chrome uses additional tiling) it is easier to demonstrate the issue in Firefox. However, both Chrome and Firefox were equally affected by this issue.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">But, other than drawing a funny image, is there real security impact to this issue? Here, </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkCoreBlitters.h?g=0&l=120&rcl=e102016fef339f59e4bfea4547276e16da298483" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkARGB32_Shader_Blitter</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> comes to the rescue (SkARGB32_Shader_Blitter is used whenever shader effects are applied to a color in Skia). What is specific about SkARGB32_Shader_Blitter is that it allocates a temporary buffer of the same size as a single image row. When </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkBlitter_ARGB32.cpp?g=0&l=368&rcl=a4083c97d48e8a4f88e2797d7363f141e3d42553" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">SkARGB32_Shader_Blitter::blitH</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> is used to draw an entire image row, if we can make it draw from </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = -1 to </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> - 1 (alternately from </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = 0 to </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">x</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> = </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">), it will need to write </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> + 1 pixels into a buffer that can only hold </span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">width</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> pixels, leading to a buffer overflow as can be seen in the ASan log in the </span><a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1579" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">bug report</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Note how the PoCs for Chrome and Firefox contain SVG images with a linearGradient element - the linear gradient is used specifically to select SkARGB32_Shader_Blitter instead of drawing pixels to the image directly, which would only result in pixels spilling to the previous row.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Another specific of this issue is that it can only be reached when drawing (more specifically: filling) paths with antialiasing turned off. As it is not currently possible to draw paths to a HTML canvas elements with antialiasing off (there is an imageSmoothingEnabled property but it only applies to drawing images, not paths), an SVG image with shape-rendering="crispEdges" must be used to trigger the issue.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">All precision issues we reported in Skia were fixed </span><a href="https://skia.googlesource.com/skia.git/+/b8e752198dde333e71cb1a9578cd3dfd404dd06c" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">by</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><a href="https://skia.googlesource.com/skia.git/+/861b52ea98d703786ce485389db07e58759c1792" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">increasing</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><a href="https://skia.googlesource.com/skia.git/+/3087c1f382f1cd547598dc75f47ccbc8fe1e6e0f" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">kConservativeRoundBias</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">. While the current bias value is large enough to cover the maximum precision errors we know about, we should not dismiss the possibility of other places where precision issues can occur.</span></div> <h1 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 20pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 20pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Conclusion</span></h1> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">While precision issues, such as described in this blog post, won’t be present in most software products, where they are present they can have quite serious consequences. To prevent them from occurring:</span></div> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Don’t use floating-point arithmetic in cases where the result is security-sensitive. If you absolutely have to, then you need to make sure that the maximum possible precision error cannot be larger than some safety margin. Potentially, </span><a href="https://www.boost.org/doc/libs/1_66_0/libs/numeric/interval/doc/interval.htm" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">interval arithmetic</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> could be used to determine the maximum precision error in some cases. Alternately, perform security checks on the result rather than input.</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <ul style="margin-bottom: 0pt; margin-top: 0pt;"> <li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">With integer arithmetic, be wary of any operations that can reduce the precision of the result, such as divisions and right shifts.</span></div> </li> </ul> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">When it comes to finding such issues, unfortunately, there doesn’t seem to be a great way to do it. When we started looking at Skia, initially we wanted to try using </span><a href="https://en.wikipedia.org/wiki/Symbolic_execution" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">symbolic execution</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> on the drawing algorithms to find input values that would lead to drawing out-of-bounds, as, on the surface, it seemed this is a problem symbolic execution would be well suited for. However, in practice, there were too many issues: most tools don’t support floating point symbolic variables and, even when running against just the integer parts of the </span><a href="https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkScan_Hairline.cpp?g=0&l=45&rcl=f08d1d0ce19c72bb911f059dcf916cf99a0a2467" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">simplest line drawing algorithm</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">, we were unsuccessful in completing the run in a reasonable time (we were using </span><a href="https://klee.github.io/" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline;">KLEE</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> with STP and Z3 backends).</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">In the end, what we ended up doing was a combination of the more old-school methods: manual source review, fuzzing (especially with values close to image boundaries) and, in some cases, when we already identified potentially problematic areas of code, even bruteforcing the range of all possible values.</span></div> <b style="font-weight: normal;"><br /></b> <div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Do you know of other instances where precision errors resulted in security issues? Let us know about them in the comments.</span></div> <br /> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <span itemprop='name'>Anonymous</span> </span> </span> <span class='post-timestamp'> at <meta content='https://googleprojectzero.blogspot.com/2018/07/drawing-outside-box-precision-issues-in.html' itemprop='url'/> <a class='timestamp-link' href='https://googleprojectzero.blogspot.com/2018/07/drawing-outside-box-precision-issues-in.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2018-07-26T09:47:00-07:00'>9:47 AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://googleprojectzero.blogspot.com/2018/07/drawing-outside-box-precision-issues-in.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-612473818'> <a href='https://www.blogger.com/post-edit.g?blogID=4838136820032157985&postID=2598238453898476096&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=2598238453898476096&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=2598238453898476096&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=2598238453898476096&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=2598238453898476096&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=2598238453898476096&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://googleprojectzero.blogspot.com/search?updated-max=2018-08-14T10:00:00-07:00&max-results=1&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://googleprojectzero.blogspot.com/search?updated-max=2018-07-26T09:47:00-07:00&max-results=1' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='https://googleprojectzero.blogspot.com/'>Home</a> </div> <div class='clear'></div> <div class='blog-feeds'> <div class='feed-links'> Subscribe to: <a class='feed-link' href='https://googleprojectzero.blogspot.com/feeds/posts/default' target='_blank' type='application/atom+xml'>Posts (Atom)</a> </div> </div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='https://googleprojectzero.blogspot.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget PageList' data-version='1' id='PageList1'> <h2>Pages</h2> <div class='widget-content'> <ul> <li> <a href='https://googleprojectzero.blogspot.com/p/about-project-zero.html'>About Project Zero</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/working-at-project-zero.html'>Working at Project Zero</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/0day.html'>0day "In the Wild"</a> </li> <li> <a href='https://googleprojectzero.github.io/0days-in-the-wild/rca.html'>0day Exploit Root Cause Analyses</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-faq.html'>Vulnerability Disclosure FAQ</a> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Archives</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2025/'> 2025 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2025/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/12/'> December </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(36)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/08/'> August </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/07/'> July </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/01/'> January </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/12/'> December </a> <span class='post-count' dir='ltr'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/10/'> October </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/08/'> August </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li><a href='https://googleprojectzero.blogspot.com/2018/07/drawing-outside-box-precision-issues-in.html'>Drawing Outside the Box: Precision Issues in Graph...</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(19)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/04/'> April </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/08/'> August </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/07/'> July </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/06/'> June </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> </div> </div> <script type='text/javascript'> //<![CDATA[ (function(){ let archive_list = document.getElementById('ArchiveList'); if (archive_list == null) return; let cur_year = archive_list.querySelector('.post-count-link').innerText.trim() - 0; let last_year = 2014; let elements = []; const MONTHS = ',Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','); let parent = document.getElementById('ArchiveList'); while (parent.childNodes.length) parent.removeChild(parent.childNodes[0]); function fetch_next_year() { let url = 'https://googleprojectzero.blogspot.com/?action=getTitles&widgetId=BlogArchive1&widgetType=BlogArchive&responseType=js&path=https%3A%2F%2Fgoogleprojectzero.blogspot.com%2F'+cur_year; fetch(url).then(resp => { if (!resp.ok) { console.log('http error'); return; } resp.text().then(text => { let scope = { _WidgetManager: { _HandleControllerResult: (name, method, results) => { elements.push(document.createElement('hr')); let year_header = document.createElement('div'); year_header.appendChild(document.createTextNode(cur_year)); year_header.style.fontSize = 'large'; elements.push(year_header); let list = document.createElement('ul'); elements.push(list); for (let obj of results.posts) { let link_parts = obj.url.split('/'); let year = link_parts[3]; let month = link_parts[4]; let el = document.createElement(/*'div'*/'li'); el.style.listStyleType = 'square'; el.style.listStylePosition = 'inside'; let link = document.createElement('a'); el.appendChild(link); link.appendChild(document.createTextNode(obj.title)); link.href = obj.url; let date_trailer = document.createElement('span'); el.appendChild(date_trailer); //date_trailer.appendChild(document.createTextNode(' ('+year+'-'+month+')')); date_trailer.appendChild(document.createTextNode(' ('+MONTHS[parseInt(month, 10)]+')')); //date_trailer.style.textAlign = 'right'; //elements.push(el); list.appendChild(el); } } } }; with (scope) { eval(text); } if (cur_year == last_year) { finish(); } else { cur_year--; fetch_next_year(); } }); }); } fetch_next_year(); function finish() { for (let obj of elements) { parent.appendChild(obj); } console.log(elements); } })(); //]]> </script> <div class='clear'></div> </div> </div></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='sidebar no-items section' id='sidebar-right-2-1'></div> </td> <td class='columns-cell'> <div class='sidebar no-items section' id='sidebar-right-2-2'></div> </td> </tr> </tbody> </table> <div class='sidebar no-items section' id='sidebar-right-3'></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3' name='Footer'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/688949419-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY7d0o1S1wkXWPhIjtlfxe2ArC8bbw:1739843007607';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d4838136820032157985','//googleprojectzero.blogspot.com/2018/07/','4838136820032157985'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '4838136820032157985', 'title': 'Project Zero', 'url': 'https://googleprojectzero.blogspot.com/2018/07/', 'canonicalUrl': 'https://googleprojectzero.blogspot.com/2018/07/', 'homepageUrl': 'https://googleprojectzero.blogspot.com/', 'searchUrl': 'https://googleprojectzero.blogspot.com/search', 'canonicalHomepageUrl': 'https://googleprojectzero.blogspot.com/', 'blogspotFaviconUrl': 'https://googleprojectzero.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-240546891-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Project Zero - Atom\x22 href\x3d\x22https://googleprojectzero.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Project Zero - RSS\x22 href\x3d\x22https://googleprojectzero.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Project Zero - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/4838136820032157985/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/f6e0cc369f0f1a05', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'July 2018', 'pageTitle': 'Project Zero: July 2018'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Project Zero', 'description': 'News and updates from the Project Zero team at Google', 'url': 'https://googleprojectzero.blogspot.com/2018/07/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2018, 'month': 7, 'rangeMessage': 'Showing posts from July, 2018'}}}]); _WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/1360229384-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/1964470060-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PageListView', new _WidgetInfo('PageList1', 'sidebar-right-1', document.getElementById('PageList1'), {'title': 'Pages', 'links': [{'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/about-project-zero.html', 'id': '4384467920505278144', 'title': 'About Project Zero'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/working-at-project-zero.html', 'id': '2459334498880008057', 'title': 'Working at Project Zero'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/0day.html', 'id': '3414239791814532209', 'title': '0day \x22In the Wild\x22'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.github.io/0days-in-the-wild/rca.html', 'title': '0day Exploit Root Cause Analyses'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-faq.html', 'id': '2935252455704572784', 'title': 'Vulnerability Disclosure FAQ'}], 'mobile': false, 'showPlaceholder': true, 'hasCurrentPage': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>