bug 833283 - remove the option to bypass OTS for downloaded fonts. r=jdaggett
authorJonathan Kew <jkew@mozilla.com>
Wed, 23 Jan 2013 16:41:18 +0000
changeset 119624 4da2cd42a9697d7308f32326cefb3a470c3a7388
parent 119623 6a48352004a29a96bc6705b5ab0d25784ebfe03c
child 119625 011d0b0befdcfe3992f5e9f0306e4df72bdf7ab3
push id21783
push userjkew@mozilla.com
push dateWed, 23 Jan 2013 16:42:18 +0000
treeherdermozilla-inbound@363a34802aef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs833283
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 833283 - remove the option to bypass OTS for downloaded fonts. r=jdaggett
gfx/thebes/Makefile.in
gfx/thebes/gfxFontUtils.cpp
gfx/thebes/gfxFontUtils.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/woff-private.h
gfx/thebes/woff.c
gfx/thebes/woff.h
modules/libpref/src/init/all.js
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -340,19 +340,17 @@ CPPSRCS +=      nsUnicodeRange.cpp
 CPPSRCS +=      gfxQuartzNativeDrawing.cpp
 
 CMMSRCS = \
 	gfxMacPlatformFontList.mm \
 	$(NULL)
 
 endif
 
-CSRCS += woff.c
-
-DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT -DHB_DONT_DEFINE_STDINT
+DEFINES += -DIMPL_THEBES -DHB_DONT_DEFINE_STDINT
 DEFINES += -DMOZ_OTS_REPORT_ERRORS
 
 ifeq (WINNT,$(OS_TARGET))
 DEFINES += -DOTS_DLL
 endif
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/gfx/thebes/gfxFontUtils.cpp
+++ b/gfx/thebes/gfxFontUtils.cpp
@@ -19,18 +19,16 @@
 #include "nsIStreamBufferAccess.h"
 #include "nsIUUIDGenerator.h"
 #include "nsMemory.h"
 #include "nsICharsetConverterManager.h"
 
 #include "plbase64.h"
 #include "prlog.h"
 
-#include "woff.h"
-
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 #ifdef PR_LOGGING
 
 #define LOG(log, args) PR_LOG(gfxPlatform::GetLog(log), \
                                PR_LOG_DEBUG, args)
@@ -1113,238 +1111,16 @@ gfxFontUtils::DetermineFontDataType(cons
         }
     }
     
     // tests for other formats here
     
     return GFX_USERFONT_UNKNOWN;
 }
 
-bool
-gfxFontUtils::ValidateSFNTHeaders(const uint8_t *aFontData, 
-                                  uint32_t aFontDataLength)
-{
-    NS_ASSERTION(aFontData, "null font data");
-
-    uint64_t dataLength(aFontDataLength);
-    
-    // read in the sfnt header
-    if (sizeof(SFNTHeader) > aFontDataLength) {
-        NS_WARNING("invalid font (insufficient data)");
-        return false;
-    }
-    
-    const SFNTHeader *sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData);
-    uint32_t sfntVersion = sfntHeader->sfntVersion;
-    if (!IsValidSFNTVersion(sfntVersion)) {
-        NS_WARNING("invalid font (SFNT version)");
-        return false;
-    }
-    
-    // iterate through the table headers to find the head, name and OS/2 tables
-#ifdef XP_WIN
-    bool foundOS2 = false;
-#endif
-    bool foundHead = false, foundName = false;
-    bool foundGlyphs = false, foundCFF = false, foundKern = false;
-    bool foundLoca = false, foundMaxp = false;
-    uint32_t headOffset = 0, headLen, nameOffset = 0, kernOffset = 0,
-        kernLen = 0, glyfLen = 0, locaOffset = 0, locaLen = 0,
-        maxpOffset = 0, maxpLen;
-    uint32_t i, numTables;
-
-    numTables = sfntHeader->numTables;
-    uint32_t headerLen = sizeof(SFNTHeader) + sizeof(TableDirEntry) * numTables;
-    if (headerLen > aFontDataLength) {
-        NS_WARNING("invalid font (table directory)");
-        return false;
-    }
-    
-    // table directory entries begin immediately following SFNT header
-    const TableDirEntry *dirEntry = 
-        reinterpret_cast<const TableDirEntry*>(aFontData + sizeof(SFNTHeader));
-    uint32_t checksum = 0;
-    
-    // checksum for font = (checksum of header) + (checksum of tables)
-    const AutoSwap_PRUint32 *headerData = 
-        reinterpret_cast<const AutoSwap_PRUint32*>(aFontData);
-
-    // header length is in bytes, checksum calculated in longwords
-    for (i = 0; i < (headerLen >> 2); i++, headerData++) {
-        checksum += *headerData;
-    }
-    
-    for (i = 0; i < numTables; i++, dirEntry++) {
-    
-        // sanity check on offset, length values
-        if (uint64_t(dirEntry->offset) + uint64_t(dirEntry->length) > dataLength) {
-            NS_WARNING("invalid font (table directory entry)");
-            return false;
-        }
-
-        checksum += dirEntry->checkSum;
-        
-        switch (dirEntry->tag) {
-
-        case TRUETYPE_TAG('h','e','a','d'):
-            foundHead = true;
-            headOffset = dirEntry->offset;
-            headLen = dirEntry->length;
-            if (headLen < sizeof(HeadTable)) {
-                NS_WARNING("invalid font (head table length)");
-                return false;
-            }
-            break;
-
-        case TRUETYPE_TAG('k','e','r','n'):
-            foundKern = true;
-            kernOffset = dirEntry->offset;
-            kernLen = dirEntry->length;
-            break;
-
-        case TRUETYPE_TAG('n','a','m','e'):
-            foundName = true;
-            nameOffset = dirEntry->offset;
-            break;
-
-        case TRUETYPE_TAG('O','S','/','2'):
-#ifdef XP_WIN
-            foundOS2 = true;
-#endif
-            break;
-
-        case TRUETYPE_TAG('g','l','y','f'):  // TrueType-style quadratic glyph table
-            foundGlyphs = true;
-            glyfLen = dirEntry->length;
-            break;
-
-        case TRUETYPE_TAG('l','o','c','a'):  // glyph location table
-            foundLoca = true;
-            locaOffset = dirEntry->offset;
-            locaLen = dirEntry->length;
-            break;
-
-        case TRUETYPE_TAG('m','a','x','p'):  // max profile
-            foundMaxp = true;
-            maxpOffset = dirEntry->offset;
-            maxpLen = dirEntry->length;
-            if (maxpLen < sizeof(MaxpTableHeader)) {
-                NS_WARNING("invalid font (maxp table length)");
-                return false;
-            }
-            break;
-
-        case TRUETYPE_TAG('C','F','F',' '):  // PS-style cubic glyph table
-            foundCFF = true;
-            break;
-
-        default:
-            break;
-        }
-
-    }
-
-    // simple sanity checks
-    
-    // -- fonts need head, name, maxp tables
-    if (!foundHead || !foundName || !foundMaxp) {
-        NS_WARNING("invalid font (missing head/name/maxp table)");
-        return false;
-    }
-    
-    // -- on Windows need OS/2 table
-#ifdef XP_WIN
-    if (!foundOS2) {
-        NS_WARNING("invalid font (missing OS/2 table)");
-        return false;
-    }
-#endif
-
-    // -- head table data
-    const HeadTable *headData = reinterpret_cast<const HeadTable*>(aFontData + headOffset);
-
-    if (headData->tableVersionNumber != HeadTable::HEAD_VERSION) {
-        NS_WARNING("invalid font (head table version)");
-        return false;
-    }
-
-    if (headData->magicNumber != HeadTable::HEAD_MAGIC_NUMBER) {
-        NS_WARNING("invalid font (head magic number)");
-        return false;
-    }
-
-    if (headData->checkSumAdjustment != (HeadTable::HEAD_CHECKSUM_CALC_CONST - checksum)) {
-        NS_WARNING("invalid font (bad checksum)");
-        // Bug 483459 - warn about a bad checksum but allow the font to be 
-        // used, since a small percentage of fonts don't calculate this 
-        // correctly and font systems aren't fussy about this
-        // return false;
-    }
-    
-    // need glyf or CFF table based on sfnt version
-    if (sfntVersion == TRUETYPE_TAG('O','T','T','O')) {
-        if (!foundCFF) {
-            NS_WARNING("invalid font (missing CFF table)");
-            return false;
-        }
-    } else {
-        if (!foundGlyphs || !foundLoca) {
-            NS_WARNING("invalid font (missing glyf or loca table)");
-            return false;
-        }
-
-        // sanity-check 'loca' offsets
-        const MaxpTableHeader *maxpData =
-            reinterpret_cast<const MaxpTableHeader*>(aFontData + maxpOffset);
-        if (!ValidateLocaTable(aFontData + locaOffset, locaLen, glyfLen,
-                               headData->indexToLocFormat,
-                               maxpData->numGlyphs)) {
-            NS_WARNING("invalid font (loca table offsets)");
-            return false;
-        }
-    }
-    
-    // -- name table data
-    const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(aFontData + nameOffset);
-
-    uint32_t nameCount = nameHeader->count;
-
-    // -- sanity check the number of name records
-    if (uint64_t(nameCount) * sizeof(NameRecord) + uint64_t(nameOffset) > dataLength) {
-        NS_WARNING("invalid font (name records)");
-        return false;
-    }
-    
-    // -- iterate through name records
-    const NameRecord *nameRecord = reinterpret_cast<const NameRecord*>
-                                       (aFontData + nameOffset + sizeof(NameHeader));
-    uint64_t nameStringsBase = uint64_t(nameOffset) + uint64_t(nameHeader->stringOffset);
-
-    for (i = 0; i < nameCount; i++, nameRecord++) {
-        uint32_t namelen = nameRecord->length;
-        uint32_t nameoff = nameRecord->offset;  // offset from base of string storage
-
-        if (nameStringsBase + uint64_t(nameoff) + uint64_t(namelen) > dataLength) {
-            NS_WARNING("invalid font (name table strings)");
-            return false;
-        }
-    }
-
-    // -- sanity-check the kern table, if present (see bug 487549)
-    if (foundKern) {
-        if (!ValidateKernTable(aFontData + kernOffset, kernLen)) {
-            NS_WARNING("invalid font (kern table)");
-            return false;
-        }
-    }
-
-    // everything seems consistent
-    return true;
-}
-
 nsresult
 gfxFontUtils::RenameFont(const nsAString& aName, const uint8_t *aFontData, 
                          uint32_t aFontDataLength, FallibleTArray<uint8_t> *aNewFont)
 {
     NS_ASSERTION(aNewFont, "null font data array");
     
     uint64_t dataLength(aFontDataLength);
 
--- a/gfx/thebes/gfxFontUtils.h
+++ b/gfx/thebes/gfxFontUtils.h
@@ -735,35 +735,27 @@ public:
     // for use with Windows T2Embed API AddFontResource type API's
     // effectively hide existing fonts with matching names aHeaderLen is
     // the size of the header buffer on input, the actual size of the
     // EOT header on output
     static nsresult
     MakeEOTHeader(const uint8_t *aFontData, uint32_t aFontDataLength,
                   FallibleTArray<uint8_t> *aHeader, FontDataOverlay *aOverlay);
 
-    // determine whether a font (which has already passed ValidateSFNTHeaders)
-    // is CFF format rather than TrueType
+    // determine whether a font (which has already been sanitized, so is known
+    // to be a valid sfnt) is CFF format rather than TrueType
     static bool
     IsCffFont(const uint8_t* aFontData, bool& hasVertical);
 
 #endif
 
     // determine the format of font data
     static gfxUserFontType
     DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength);
 
-    // checks for valid SFNT table structure, returns true if valid
-    // does *not* guarantee that all font data is valid, though it does
-    // check that key tables such as 'name' are present and readable.
-    // XXX to be removed if/when we eliminate the option to disable OTS,
-    // which does more thorough validation.
-    static bool
-    ValidateSFNTHeaders(const uint8_t *aFontData, uint32_t aFontDataLength);
-    
     // Read the fullname from the sfnt data (used to save the original name
     // prior to renaming the font for installation).
     // This is called with sfnt data that has already been validated,
     // so it should always succeed in finding the name table.
     static nsresult
     GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength,
                         nsAString& aFullName);
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -124,17 +124,16 @@ SRGBOverrideObserver::Observe(nsISupport
     NS_ASSERTION(NS_strcmp(someData,
                    NS_LITERAL_STRING("gfx.color_mangement.force_srgb").get()),
                  "Restarting CMS on wrong pref!");
     ShutdownCMS();
     return NS_OK;
 }
 
 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
-#define GFX_DOWNLOADABLE_FONTS_SANITIZE "gfx.downloadable_fonts.sanitize"
 
 #define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
 #define HARFBUZZ_SCRIPTS_DEFAULT  mozilla::unicode::SHAPING_DEFAULT
 #define GFX_PREF_FALLBACK_USE_CMAPS  "gfx.font_rendering.fallback.always_use_cmaps"
 
 #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
 
 #ifdef MOZ_GRAPHITE
@@ -235,17 +234,16 @@ static const char *gPrefLangNames[] = {
     "x-user-def"
 };
 
 gfxPlatform::gfxPlatform()
   : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
 {
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
-    mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
 #ifdef MOZ_GRAPHITE
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
 #endif
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
     uint32_t canvasMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
@@ -815,27 +813,16 @@ gfxPlatform::DownloadableFontsEnabled()
         mAllowDownloadableFonts =
             Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
     }
 
     return mAllowDownloadableFonts;
 }
 
 bool
-gfxPlatform::SanitizeDownloadedFonts()
-{
-    if (mDownloadableFontsSanitize == UNINITIALIZED_VALUE) {
-        mDownloadableFontsSanitize =
-            Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_SANITIZE, true);
-    }
-
-    return mDownloadableFontsSanitize;
-}
-
-bool
 gfxPlatform::UseCmapsDuringSystemFallback()
 {
     if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
         mFallbackUsesCmaps =
             Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
     }
 
     return mFallbackUsesCmaps;
@@ -1614,18 +1601,16 @@ gfxPlatform::GetBidiNumeralOption()
 }
 
 void
 gfxPlatform::FontsPrefsChanged(const char *aPref)
 {
     NS_ASSERTION(aPref != nullptr, "null preference");
     if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
         mAllowDownloadableFonts = UNINITIALIZED_VALUE;
-    } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_SANITIZE, aPref)) {
-        mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
         mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 #ifdef MOZ_GRAPHITE
     } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
         mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
         gfxFontCache *fontCache = gfxFontCache::GetCache();
         if (fontCache) {
             fontCache->AgeAllGenerations();
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -311,21 +311,16 @@ public:
                                            uint32_t aLength);
 
     /**
      * Whether to allow downloadable fonts via @font-face rules
      */
     bool DownloadableFontsEnabled();
 
     /**
-     * Whether to sanitize downloaded fonts using the OTS library
-     */
-    bool SanitizeDownloadedFonts();
-
-    /**
      * True when hinting should be enabled.  This setting shouldn't
      * change per gecko process, while the process is live.  If so the
      * results are not defined.
      *
      * NB: this bit is only honored by the FT2 backend, currently.
      */
     virtual bool FontHintingEnabled() { return true; }
 
@@ -565,17 +560,16 @@ protected:
      */
     static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
 
     mozilla::gfx::BackendType GetContentBackend() {
       return mContentBackend;
     }
 
     int8_t  mAllowDownloadableFonts;
-    int8_t  mDownloadableFontsSanitize;
 #ifdef MOZ_GRAPHITE
     int8_t  mGraphiteShapingEnabled;
 #endif
 
     int8_t  mBidiNumeralOption;
 
     // whether to always search font cmaps globally 
     // when doing system font fallback
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -13,18 +13,16 @@
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "prlong.h"
 #include "nsNetUtil.h"
 #include "nsIProtocolHandler.h"
 #include "nsIPrincipal.h"
 #include "mozilla/Telemetry.h"
 
-#include "woff.h"
-
 #include "opentype-sanitiser.h"
 #include "ots-memory-stream.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *
 gfxUserFontSet::GetUserFontsLog()
@@ -198,68 +196,16 @@ gfxUserFontSet::FindFontEntry(gfxFontFam
     // a fallback font -- but not if all sources failed (bug 633500)
     aWaitForUserFont = (status != STATUS_END_OF_LIST) &&
         (proxyEntry->mLoadingState < gfxProxyFontEntry::LOADING_SLOWLY);
 
     // if either loading or an error occurred, return null
     return nullptr;
 }
 
-// Given a buffer of downloaded font data, do any necessary preparation
-// to make it into usable OpenType.
-// May return the original pointer unchanged, or a newly-allocated
-// block (in which case the passed-in block is NS_Free'd).
-// aLength is updated if necessary to the new length of the data.
-// Returns NULL and NS_Free's the incoming data in case of errors.
-static const uint8_t*
-PrepareOpenTypeData(const uint8_t* aData, uint32_t* aLength)
-{
-    switch(gfxFontUtils::DetermineFontDataType(aData, *aLength)) {
-    
-    case GFX_USERFONT_OPENTYPE:
-        // nothing to do
-        return aData;
-        
-    case GFX_USERFONT_WOFF: {
-        uint32_t status = eWOFF_ok;
-        uint32_t bufferSize = woffGetDecodedSize(aData, *aLength, &status);
-        if (WOFF_FAILURE(status)) {
-            break;
-        }
-        uint8_t* decodedData = static_cast<uint8_t*>(NS_Alloc(bufferSize));
-        if (!decodedData) {
-            break;
-        }
-        woffDecodeToBuffer(aData, *aLength,
-                           decodedData, bufferSize,
-                           aLength, &status);
-        // replace original data with the decoded version
-        NS_Free((void*)aData);
-        aData = decodedData;
-        if (WOFF_FAILURE(status)) {
-            // something went wrong, discard the data and return NULL
-            break;
-        }
-        // success, return the decoded data
-        return aData;
-    }
-
-    // xxx - add support for other wrappers here
-
-    default:
-        NS_WARNING("unknown font format");
-        break;
-    }
-
-    // discard downloaded data that couldn't be used
-    NS_Free((void*)aData);
-
-    return nullptr;
-}
-
 // Based on ots::ExpandingMemoryStream from ots-memory-stream.h,
 // adapted to use Mozilla allocators and to allow the final
 // memory buffer to be adopted by the client.
 class ExpandingMemoryStream : public ots::OTSStream {
 public:
     ExpandingMemoryStream(size_t initial, size_t limit)
         : mLength(initial), mLimit(limit), mOff(0) {
         mPtr = NS_Alloc(mLength);
@@ -661,97 +607,60 @@ gfxUserFontSet::LoadFont(gfxMixedFontFam
                          gfxProxyFontEntry *aProxy,
                          const uint8_t *aFontData, uint32_t &aLength)
 {
     gfxFontEntry *fe = nullptr;
 
     gfxUserFontType fontType =
         gfxFontUtils::DetermineFontDataType(aFontData, aLength);
 
-    // Save a copy of the metadata block (if present) for nsIDOMFontFace
-    // to use if required. Ownership of the metadata block will be passed
-    // to the gfxUserFontData record below.
-    // NOTE: after the non-OTS codepath using PrepareOpenTypeData is
-    // removed, we should defer this until after we've created the new
-    // fontEntry.
-    nsTArray<uint8_t> metadata;
-    uint32_t metaOrigLen = 0;
-    if (fontType == GFX_USERFONT_WOFF) {
-        CopyWOFFMetadata(aFontData, aLength, &metadata, &metaOrigLen);
-    }
-
     // Unwrap/decompress/sanitize or otherwise munge the downloaded data
     // to make a usable sfnt structure.
 
     // Because platform font activation code may replace the name table
     // in the font with a synthetic one, we save the original name so that
     // it can be reported via the nsIDOMFontFace API.
     nsAutoString originalFullName;
 
-    if (gfxPlatform::GetPlatform()->SanitizeDownloadedFonts()) {
-       // Call the OTS sanitizer; this will also decode WOFF to sfnt
-        // if necessary. The original data in aFontData is left unchanged.
-        uint32_t saneLen;
-        const uint8_t* saneData =
-            SanitizeOpenTypeData(aFamily, aProxy, aFontData, aLength, saneLen,
-                                 fontType == GFX_USERFONT_WOFF);
-        if (!saneData) {
-            LogMessage(aFamily, aProxy, "rejected by sanitizer");
-        }
-        if (saneData) {
-            // The sanitizer ensures that we have a valid sfnt and a usable
-            // name table, so this should never fail unless we're out of
-            // memory, and GetFullNameFromSFNT is not directly exposed to
-            // arbitrary/malicious data from the web.
-            gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen,
-                                              originalFullName);
-            // Here ownership of saneData is passed to the platform,
-            // which will delete it when no longer required
-            fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy,
-                                                              saneData,
-                                                              saneLen);
-            if (!fe) {
-                LogMessage(aFamily, aProxy, "not usable by platform");
-            }
-        }
-    } else {
-        // FIXME: this code can be removed once we remove the pref to
-        // disable the sanitizer; the PrepareOpenTypeData and
-        // ValidateSFNTHeaders functions will then be obsolete.
-        aFontData = PrepareOpenTypeData(aFontData, &aLength);
-
-        if (aFontData) {
-            if (gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength)) {
-                // ValidateSFNTHeaders has checked that we have a valid
-                // sfnt structure and a usable 'name' table
-                gfxFontUtils::GetFullNameFromSFNT(aFontData, aLength,
-                                                  originalFullName);
-                // Here ownership of aFontData is passed to the platform,
-                // which will delete it when no longer required
-                fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy,
-                                                                  aFontData,
-                                                                  aLength);
-                if (!fe) {
-                    LogMessage(aFamily, aProxy, "not usable by platform");
-                }
-                aFontData = nullptr; // we must NOT free this!
-            } else {
-                // the data was unusable, so just discard it
-                // (error will be reported below, if logging is enabled)
-                LogMessage(aFamily, aProxy, "SFNT header or tables invalid");
-            }
+    // Call the OTS sanitizer; this will also decode WOFF to sfnt
+    // if necessary. The original data in aFontData is left unchanged.
+    uint32_t saneLen;
+    const uint8_t* saneData =
+        SanitizeOpenTypeData(aFamily, aProxy, aFontData, aLength, saneLen,
+                             fontType == GFX_USERFONT_WOFF);
+    if (!saneData) {
+        LogMessage(aFamily, aProxy, "rejected by sanitizer");
+    }
+    if (saneData) {
+        // The sanitizer ensures that we have a valid sfnt and a usable
+        // name table, so this should never fail unless we're out of
+        // memory, and GetFullNameFromSFNT is not directly exposed to
+        // arbitrary/malicious data from the web.
+        gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen,
+                                          originalFullName);
+        // Here ownership of saneData is passed to the platform,
+        // which will delete it when no longer required
+        fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy,
+                                                          saneData,
+                                                          saneLen);
+        if (!fe) {
+            LogMessage(aFamily, aProxy, "not usable by platform");
         }
     }
 
-    if (aFontData) {
-        NS_Free((void*)aFontData);
-        aFontData = nullptr;
-    }
+    if (fe) {
+        // Save a copy of the metadata block (if present) for nsIDOMFontFace
+        // to use if required. Ownership of the metadata block will be passed
+        // to the gfxUserFontData record below.
+        nsTArray<uint8_t> metadata;
+        uint32_t metaOrigLen = 0;
+        if (fontType == GFX_USERFONT_WOFF) {
+            CopyWOFFMetadata(aFontData, aLength, &metadata, &metaOrigLen);
+        }
 
-    if (fe) {
         // copy OpenType feature/language settings from the proxy to the
         // newly-created font entry
         fe->mFeatureSettings.AppendElements(aProxy->mFeatureSettings);
         fe->mLanguageOverride = aProxy->mLanguageOverride;
         StoreUserFontData(fe, aProxy, originalFullName,
                           &metadata, metaOrigLen);
 #ifdef PR_LOGGING
         if (LOG_ENABLED()) {
@@ -773,16 +682,20 @@ gfxUserFontSet::LoadFont(gfxMixedFontFam
             LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
                  " error making platform font\n",
                  this, aProxy->mSrcIndex, fontURI.get(),
                  NS_ConvertUTF16toUTF8(aFamily->Name()).get()));
         }
 #endif
     }
 
+    // The downloaded data can now be discarded; the font entry is using the
+    // sanitized copy
+    NS_Free((void*)aFontData);
+
     return fe;
 }
 
 gfxFontFamily*
 gfxUserFontSet::GetFamily(const nsAString& aFamilyName) const
 {
     nsAutoString key(aFamilyName);
     ToLowerCase(key);
deleted file mode 100644
--- a/gfx/thebes/woff-private.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WOFF_PRIVATE_H_
-#define WOFF_PRIVATE_H_
-
-#include "woff.h"
-
-/* private definitions used in the WOFF encoder/decoder functions */
-
-/* create an OT tag from 4 characters */
-#define TAG(a,b,c,d) ((a)<<24 | (b)<<16 | (c)<<8 | (d))
-
-#define WOFF_SIGNATURE    TAG('w','O','F','F')
-
-#define SFNT_VERSION_CFF  TAG('O','T','T','O')
-#define SFNT_VERSION_TT   0x00010000
-#define SFNT_VERSION_true TAG('t','r','u','e')
-
-#define TABLE_TAG_DSIG    TAG('D','S','I','G')
-#define TABLE_TAG_head    TAG('h','e','a','d')
-#define TABLE_TAG_bhed    TAG('b','h','e','d')
-
-#define SFNT_CHECKSUM_CALC_CONST  0xB1B0AFBAU /* from the TT/OT spec */
-
-#ifdef WOFF_MOZILLA_CLIENT/* Copies of the NS_SWAP16 and NS_SWAP32 macros; they are defined in
-   a C++ header in mozilla, so we cannot include that here */
-# include "prtypes.h" /* defines IS_LITTLE_ENDIAN / IS_BIG_ENDIAN */
-# if defined IS_LITTLE_ENDIAN
-#  define READ16BE(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
-#  define READ32BE(x) ((READ16BE((x) & 0xffff) << 16) | (READ16BE((x) >> 16)))
-# elif defined IS_BIG_ENDIAN
-#  define READ16BE(x) (x)
-#  define READ32BE(x) (x)
-# else
-#  error "Unknown byte order"
-# endif
-#else
-/* These macros to read values as big-endian only work on "real" variables,
-   not general expressions, because of the use of &(x), but they are
-   designed to work on both BE and LE machines without the need for a
-   configure check. For production code, we might want to replace this
-   with something more efficient. */
-/* read a 32-bit BigEndian value */
-# define READ32BE(x) ( ( (uint32_t) ((uint8_t*)&(x))[0] << 24 ) + \
-                       ( (uint32_t) ((uint8_t*)&(x))[1] << 16 ) + \
-                       ( (uint32_t) ((uint8_t*)&(x))[2] <<  8 ) + \
-                         (uint32_t) ((uint8_t*)&(x))[3]           )
-/* read a 16-bit BigEndian value */
-# define READ16BE(x) ( ( (uint16_t) ((uint8_t*)&(x))[0] << 8 ) + \
-                         (uint16_t) ((uint8_t*)&(x))[1]          )
-#endif
-
-#pragma pack(push,1)
-
-typedef struct {
-  uint32_t version;
-  uint16_t numTables;
-  uint16_t searchRange;
-  uint16_t entrySelector;
-  uint16_t rangeShift;
-} sfntHeader;
-
-typedef struct {
-  uint32_t tag;
-  uint32_t checksum;
-  uint32_t offset;
-  uint32_t length;
-} sfntDirEntry;
-
-typedef struct {
-  uint32_t signature;
-  uint32_t flavor;
-  uint32_t length;
-  uint16_t numTables;
-  uint16_t reserved;
-  uint32_t totalSfntSize;
-  uint16_t majorVersion;
-  uint16_t minorVersion;
-  uint32_t metaOffset;
-  uint32_t metaCompLen;
-  uint32_t metaOrigLen;
-  uint32_t privOffset;
-  uint32_t privLen;
-} woffHeader;
-
-typedef struct {
-  uint32_t tag;
-  uint32_t offset;
-  uint32_t compLen;
-  uint32_t origLen;
-  uint32_t checksum;
-} woffDirEntry;
-
-typedef struct {
-  uint32_t version;
-  uint32_t fontRevision;
-  uint32_t checkSumAdjustment;
-  uint32_t magicNumber;
-  uint16_t flags;
-  uint16_t unitsPerEm;
-  uint32_t created[2];
-  uint32_t modified[2];
-  int16_t xMin;
-  int16_t yMin;
-  int16_t xMax;
-  int16_t yMax;
-  uint16_t macStyle;
-  uint16_t lowestRecPpem;
-  int16_t fontDirectionHint;
-  int16_t indexToLocFormat;
-  int16_t glyphDataFormat;
-} sfntHeadTable;
-
-#define HEAD_TABLE_SIZE 54 /* sizeof(sfntHeadTable) may report 56 because of alignment */
-
-typedef struct {
-  uint32_t offset;
-  uint16_t oldIndex;
-  uint16_t newIndex;
-} tableOrderRec;
-
-#pragma pack(pop)
-
-#endif
deleted file mode 100644
--- a/gfx/thebes/woff.c
+++ /dev/null
@@ -1,1297 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "woff-private.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "zlib.h"
-
-#ifdef WOFF_MOZILLA_CLIENT /* define this when building as part of Gecko */
-# include "mozilla/mozalloc.h"
-# define malloc  moz_malloc
-# define realloc moz_realloc
-# define free    moz_free
-#endif
-
-/*
- * Just simple whole-file encoding and decoding functions; a more extensive
- * WOFF library could provide support for accessing individual tables from a
- * compressed font, alternative options for memory allocation/ownership and
- * error handling, etc.
- */
-
-/* on errors, each function sets a status variable and jumps to failure: */
-#undef FAIL
-#define FAIL(err) do { status |= err; goto failure; } while (0)
-
-/* adjust an offset for longword alignment */
-#define LONGALIGN(x) (((x) + 3) & ~3)
-
-static int
-compareOffsets(const void * lhs, const void * rhs)
-{
-  const tableOrderRec * a = (const tableOrderRec *) lhs;
-  const tableOrderRec * b = (const tableOrderRec *) rhs;
-  /* don't simply return a->offset - b->offset because these are unsigned
-     offset values; could convert to int, but possible integer overflow */
-  return a->offset > b->offset ? 1 :
-         a->offset < b->offset ? -1 :
-         0;
-}
-
-#ifndef WOFF_MOZILLA_CLIENT
-
-/******************************************************************/
-/* * * * * * * * * * * * * * ENCODING * * * * * * * * * * * * * * */
-/******************************************************************/
-
-static uint32_t
-calcChecksum(const sfntDirEntry * dirEntry,
-             const uint8_t * sfntData, uint32_t sfntLen)
-{
-  /* just returns zero on errors, they will be detected again elsewhere */
-  const uint32_t * csumPtr;
-  const uint32_t * csumEnd;
-  uint32_t csum = 0;
-  uint32_t length = READ32BE(dirEntry->length);
-  uint32_t offset = READ32BE(dirEntry->offset);
-  uint32_t tag;
-  if (LONGALIGN(length) < length) { /* overflow */
-    return csum;
-  } else {
-    length = LONGALIGN(length);
-  }
-  if ((offset & 3) != 0) { /* invalid - not properly aligned */
-    return csum;
-  }
-  if (length > sfntLen || offset > sfntLen - length) {
-    return csum;
-  }
-  csumPtr = (const uint32_t *) (sfntData + offset);
-  csumEnd = csumPtr + length / 4;
-  while (csumPtr < csumEnd) {
-    csum += READ32BE(*csumPtr);
-    csumPtr++;
-  }
-  tag = READ32BE(dirEntry->tag);
-  if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) {
-    const sfntHeadTable * head;
-    if (length < HEAD_TABLE_SIZE) {
-      return 0;
-    }
-    head = (const sfntHeadTable *)(sfntData + offset);
-    csum -= READ32BE(head->checkSumAdjustment);
-  }
-  return csum;
-}
-
-const uint8_t *
-woffEncode(const uint8_t * sfntData, uint32_t sfntLen,
-           uint16_t majorVersion, uint16_t minorVersion,
-           uint32_t * woffLen, uint32_t * pStatus)
-{
-  uint8_t * woffData = NULL;
-  tableOrderRec * tableOrder = NULL;
-
-  uint32_t tableOffset;
-  uint32_t totalSfntSize;
-
-  uint16_t numOrigTables;
-  uint16_t numTables;
-  uint16_t tableIndex;
-  uint16_t order;
-  const sfntDirEntry * sfntDir;
-  uint32_t tableBase;
-  uint32_t checkSumAdjustment = 0;
-  woffHeader * newHeader;
-  uint32_t tag = 0;
-  uint32_t removedDsigSize = 0;
-  uint32_t status = eWOFF_ok;
-
-  const sfntHeader * header = (const sfntHeader *) (sfntData);
-  const sfntHeadTable * head = NULL;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  if (READ32BE(header->version) != SFNT_VERSION_TT &&
-      READ32BE(header->version) != SFNT_VERSION_CFF &&
-      READ32BE(header->version) != SFNT_VERSION_true) {
-    status |= eWOFF_warn_unknown_version;
-  }
-
-  numOrigTables = READ16BE(header->numTables);
-  sfntDir = (const sfntDirEntry *) (sfntData + sizeof(sfntHeader));
-
-  for (tableIndex = 0; tableIndex < numOrigTables; ++tableIndex) {
-    /* validate table checksums, to figure out if we need to drop DSIG;
-       also check that table directory is correctly sorted */
-    uint32_t prevTag = tag;
-    uint32_t csum = calcChecksum(&sfntDir[tableIndex], sfntData, sfntLen);
-    if (csum != READ32BE(sfntDir[tableIndex].checksum)) {
-      status |= eWOFF_warn_checksum_mismatch;
-    }
-    checkSumAdjustment += csum;
-    tag = READ32BE(sfntDir[tableIndex].tag);
-    if (tag <= prevTag) {
-      FAIL(eWOFF_invalid);
-    }
-    if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) {
-      if (READ32BE(sfntDir[tableIndex].length) < HEAD_TABLE_SIZE) {
-        FAIL(eWOFF_invalid);
-      }
-      head = (const sfntHeadTable *)(sfntData +
-                                     READ32BE(sfntDir[tableIndex].offset));
-    }
-  }
-  if (!head) {
-    FAIL(eWOFF_invalid);
-  }
-  if ((status & eWOFF_warn_checksum_mismatch) == 0) {
-    /* no point even checking if we already have an error,
-       as fixing that will change the overall checksum too */
-    const uint32_t * csumPtr = (const uint32_t *) sfntData;
-    const uint32_t * csumEnd = csumPtr + 3 + 4 * numOrigTables;
-    while (csumPtr < csumEnd) {
-      checkSumAdjustment += READ32BE(*csumPtr);
-      ++csumPtr;
-    }
-    checkSumAdjustment = 0xB1B0AFBA - checkSumAdjustment;
-    if (checkSumAdjustment != READ32BE(head->checkSumAdjustment)) {
-      status |= eWOFF_warn_checksum_mismatch;
-    }
-  }
-
-  /* Fixing checkSumAdjustment is tricky, because if there's a DSIG table,
-     we're going to have to remove that, which in turn means that table
-     offsets in the directory will all change.
-     And recalculating checkSumAdjustment requires taking account of any
-     individual table checksum corrections, but they have not actually been
-     applied to the sfnt data at this point.
-     And finally, we'd need to get the corrected checkSumAdjustment into the
-     encoded head table (but we can't modify the original sfnt data).
-     An easier way out seems to be to go ahead and encode the font, knowing
-     that checkSumAdjustment will be wrong; then (if the status flag
-     eWOFF_warn_checksum_mismatch is set) we'll decode the font back to
-     sfnt format. This will fix up the checkSumAdjustment (and return a
-     warning status). We'll ignore that warning, and then re-encode the
-     new, cleaned-up sfnt to get the final WOFF data. Perhaps not the most
-     efficient approach, but it seems simpler than trying to predict the
-     correct final checkSumAdjustment and incorporate it into the head
-     table on the fly. */
-
-  tableOrder = (tableOrderRec *) malloc(numOrigTables * sizeof(tableOrderRec));
-  if (!tableOrder) {
-    FAIL(eWOFF_out_of_memory);
-  }
-  for (tableIndex = 0, numTables = 0;
-       tableIndex < numOrigTables; ++tableIndex) {
-    if ((status & eWOFF_warn_checksum_mismatch) != 0) {
-      /* check for DSIG table that we must drop if we're fixing checksums */
-      tag = READ32BE(sfntDir[tableIndex].tag);
-      if (tag == TABLE_TAG_DSIG) {
-        status |= eWOFF_warn_removed_DSIG;
-        removedDsigSize = READ32BE(sfntDir[tableIndex].length);
-        if (LONGALIGN(removedDsigSize) < removedDsigSize) {
-          FAIL(eWOFF_invalid);
-        }
-        continue;
-      }
-    }
-    tableOrder[numTables].offset = READ32BE(sfntDir[tableIndex].offset);
-    tableOrder[numTables].oldIndex = tableIndex;
-    tableOrder[numTables].newIndex = numTables;
-    ++numTables;
-  }
-  qsort(tableOrder, numTables, sizeof(tableOrderRec), compareOffsets);
-
-  /* initially, allocate space for header and directory */
-  /* cannot be too big because numTables is 16-bit */
-  tableOffset = sizeof(woffHeader) + numTables * sizeof(woffDirEntry);
-  woffData = (uint8_t *) malloc(tableOffset);
-  if (!woffData) {
-    FAIL(eWOFF_out_of_memory);
-  }
-
-  /* accumulator for total expected size of decoded font */
-  totalSfntSize = sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry);
-
-/*
- * We use a macro for this rather than creating a variable because woffData
- * will get reallocated during encoding. The macro avoids the risk of using a
- * stale pointer, and the compiler should optimize multiple successive uses.
- */
-#define WOFFDIR ((woffDirEntry *) (woffData + sizeof(woffHeader)))
-
-  for (order = 0; order < numTables; ++order) {
-    uLong sourceLen, destLen;
-    uint32_t sourceOffset;
-
-    uint16_t oldIndex = tableOrder[order].oldIndex;
-    uint16_t newIndex = tableOrder[order].newIndex;
-
-    WOFFDIR[newIndex].tag = sfntDir[oldIndex].tag;
-    if ((status & eWOFF_warn_checksum_mismatch) != 0) {
-      uint32_t csum = calcChecksum(&sfntDir[oldIndex], sfntData, sfntLen);
-      WOFFDIR[newIndex].checksum = READ32BE(csum);
-    } else {
-      WOFFDIR[newIndex].checksum = sfntDir[oldIndex].checksum;
-    }
-    WOFFDIR[newIndex].origLen = sfntDir[oldIndex].length;
-
-    /* we always realloc woffData to a long-aligned size, so this is safe */
-    while ((tableOffset & 3) != 0) {
-      woffData[tableOffset++] = 0;
-    }
-    WOFFDIR[newIndex].offset = READ32BE(tableOffset);
-
-    /* allocate enough space for upper bound of compressed size */
-    sourceOffset = READ32BE(sfntDir[oldIndex].offset);
-    if ((sourceOffset & 3) != 0) {
-      status |= eWOFF_warn_misaligned_table;
-    }
-    sourceLen = READ32BE(sfntDir[oldIndex].length);
-    if (sourceLen > sfntLen || sourceOffset > sfntLen - sourceLen) {
-      FAIL(eWOFF_invalid);
-    }
-    destLen = compressBound(sourceLen);
-    if (LONGALIGN(destLen) < destLen) {
-      /* something weird is going on if this overflows! */
-      FAIL(eWOFF_invalid);
-    }
-    destLen = LONGALIGN(destLen);
-    if (tableOffset + destLen < tableOffset) {
-      FAIL(eWOFF_invalid);
-    }
-    woffData = (uint8_t *) realloc(woffData, tableOffset + destLen);
-    if (!woffData) {
-      FAIL(eWOFF_out_of_memory);
-    }
-
-    /* do the compression directly into the WOFF data block */
-    if (compress2((Bytef *) (woffData + tableOffset), &destLen,
-                  (const Bytef *) (sfntData + sourceOffset),
-                  sourceLen, 9) != Z_OK) {
-      FAIL(eWOFF_compression_failure);
-    }
-    if (destLen < sourceLen) {
-      /* compressed table was smaller */
-      tableOffset += destLen; /* checked for potential overflow above */
-      WOFFDIR[newIndex].compLen = READ32BE(destLen);
-    } else {
-      /* compression didn't make it smaller, so store original data instead */
-      if (LONGALIGN(sourceLen) < sourceLen) {
-        FAIL(eWOFF_invalid); /* overflow, bail out */
-      }
-      destLen = sourceLen;
-      /* reallocate to ensure enough space for the table,
-         plus potential padding after it */
-      if (tableOffset + LONGALIGN(sourceLen) < tableOffset) {
-        FAIL(eWOFF_invalid); /* overflow, bail out */
-      }
-      woffData = (uint8_t *) realloc(woffData,
-                                     tableOffset + LONGALIGN(sourceLen));
-      if (!woffData) {
-        FAIL(eWOFF_out_of_memory);
-      }
-      /* copy the original data into place */
-      memcpy(woffData + tableOffset,
-             sfntData + READ32BE(sfntDir[oldIndex].offset), sourceLen);
-      if (tableOffset + sourceLen < tableOffset) {
-        FAIL(eWOFF_invalid); /* overflow, bail out */
-      }
-      tableOffset += sourceLen;
-      WOFFDIR[newIndex].compLen = WOFFDIR[newIndex].origLen;
-    }
-
-    /* update total size of uncompressed OpenType with table size */
-    if (totalSfntSize + sourceLen < totalSfntSize) {
-      FAIL(eWOFF_invalid); /* overflow, bail out */
-    }
-    totalSfntSize += sourceLen;
-    if (LONGALIGN(totalSfntSize) < totalSfntSize) {
-      FAIL(eWOFF_invalid);
-    }
-    totalSfntSize = LONGALIGN(totalSfntSize);
-  }
-
-  if (totalSfntSize > sfntLen) {
-    if (totalSfntSize > LONGALIGN(sfntLen)) {
-      FAIL(eWOFF_invalid);
-    } else {
-      status |= eWOFF_warn_unpadded_table;
-    }
-  } else if (totalSfntSize < sfntLen) {
-    /* check if the remaining data is a DSIG we're removing;
-       if so, we're already warning about that */
-    if ((status & eWOFF_warn_removed_DSIG) != 0 ||
-        sfntLen - totalSfntSize >
-          LONGALIGN(removedDsigSize) + sizeof(sfntDirEntry)) {
-      status |= eWOFF_warn_trailing_data;
-    }
-  }
-
-  /* write the header */
-  newHeader = (woffHeader *) (woffData);
-  newHeader->signature = WOFF_SIGNATURE;
-  newHeader->signature = READ32BE(newHeader->signature);
-  newHeader->flavor = header->version;
-  newHeader->length = READ32BE(tableOffset);
-  newHeader->numTables = READ16BE(numTables);
-  newHeader->reserved = 0;
-  newHeader->totalSfntSize = READ32BE(totalSfntSize);
-  newHeader->majorVersion = READ16BE(majorVersion);
-  newHeader->minorVersion = READ16BE(minorVersion);
-  newHeader->metaOffset = 0;
-  newHeader->metaCompLen = 0;
-  newHeader->metaOrigLen = 0;
-  newHeader->privOffset = 0;
-  newHeader->privLen = 0;
-
-  free(tableOrder);
-
-  if ((status & eWOFF_warn_checksum_mismatch) != 0) {
-    /* The original font had checksum errors, so we now decode our WOFF data
-       back to sfnt format (which fixes checkSumAdjustment), then re-encode
-       to get a clean copy. */
-    const uint8_t * cleanSfnt = woffDecode(woffData, tableOffset,
-                                           &sfntLen, &status);
-    if (WOFF_FAILURE(status)) {
-      FAIL(status);
-    }
-    free(woffData);
-    woffData = (uint8_t *) woffEncode(cleanSfnt, sfntLen,
-                                      majorVersion, minorVersion,
-                                      &tableOffset, &status);
-    free((void *) cleanSfnt);
-    if (WOFF_FAILURE(status)) {
-      FAIL(status);
-    }
-  }
-
-  if (woffLen) {
-    *woffLen = tableOffset;
-  }
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  return woffData;
-
-failure:
-  if (tableOrder) {
-    free(tableOrder);
-  }
-  if (woffData) {
-    free(woffData);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;
-}
-
-static const uint8_t *
-rebuildWoff(const uint8_t * woffData, uint32_t * woffLen,
-            const uint8_t * metaData, uint32_t metaCompLen, uint32_t metaOrigLen,
-            const uint8_t * privData, uint32_t privLen, uint32_t * pStatus)
-{
-  const woffHeader * origHeader;
-  const woffDirEntry * woffDir;
-  uint8_t * newData = NULL;
-  uint8_t * tableData = NULL;
-  woffHeader * newHeader;
-  uint16_t numTables;
-  uint32_t tableLimit, totalSize, offset;
-  uint16_t i;
-  uint32_t status = eWOFF_ok;
-
-  if (*woffLen < sizeof(woffHeader)) {
-    FAIL(eWOFF_invalid);
-  }
-  origHeader = (const woffHeader *) (woffData);
-
-  if (READ32BE(origHeader->signature) != WOFF_SIGNATURE) {
-    FAIL(eWOFF_bad_signature);
-  }
-
-  numTables = READ16BE(origHeader->numTables);
-  woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader));
-  tableLimit = 0;
-  for (i = 0; i < numTables; ++i) {
-    uint32_t end = READ32BE(woffDir[i].offset) + READ32BE(woffDir[i].compLen);
-    if (end > tableLimit) {
-      tableLimit = end;
-    }
-  }
-  tableLimit = LONGALIGN(tableLimit);
-
-  /* check for broken input (meta/priv data before sfnt tables) */
-  offset = READ32BE(origHeader->metaOffset);
-  if (offset != 0 && offset < tableLimit) {
-    FAIL(eWOFF_illegal_order);
-  }
-  offset = READ32BE(origHeader->privOffset);
-  if (offset != 0 && offset < tableLimit) {
-    FAIL(eWOFF_illegal_order);
-  }
-
-  totalSize = tableLimit; /* already long-aligned */
-  if (metaCompLen) {
-    if (totalSize + metaCompLen < totalSize) {
-      FAIL(eWOFF_invalid);
-    }
-    totalSize += metaCompLen;
-  }
-  if (privLen) {
-    if (LONGALIGN(totalSize) < totalSize) {
-      FAIL(eWOFF_invalid);
-    }
-    totalSize = LONGALIGN(totalSize);
-    if (totalSize + privLen < totalSize) {
-      FAIL(eWOFF_invalid);
-    }
-    totalSize += privLen;
-  }
-  newData = malloc(totalSize);
-  if (!newData) {
-    FAIL(eWOFF_out_of_memory);
-  }
-
-  /* copy the header, directory, and sfnt tables */
-  memcpy(newData, woffData, tableLimit);
-
-  /* then overwrite the header fields that should be changed */
-  newHeader = (woffHeader *) newData;
-  newHeader->length = READ32BE(totalSize);
-  newHeader->metaOffset = 0;
-  newHeader->metaCompLen = 0;
-  newHeader->metaOrigLen = 0;
-  newHeader->privOffset = 0;
-  newHeader->privLen = 0;
-
-  offset = tableLimit;
-  if (metaData && metaCompLen > 0 && metaOrigLen > 0) {
-    newHeader->metaOffset = READ32BE(offset);
-    newHeader->metaCompLen = READ32BE(metaCompLen);
-    newHeader->metaOrigLen = READ32BE(metaOrigLen);
-    memcpy(newData + offset, metaData, metaCompLen);
-    offset += metaCompLen;
-  }
-
-  if (privData && privLen > 0) {
-    while ((offset & 3) != 0) {
-      newData[offset++] = 0;
-    }
-    newHeader->privOffset = READ32BE(offset);
-    newHeader->privLen = READ32BE(privLen);
-    memcpy(newData + offset, privData, privLen);
-    offset += privLen;
-  }
-
-  *woffLen = offset;
-  free((void *) woffData);
-
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  return newData;
-
-failure:
-  if (newData) {
-    free(newData);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;
-}
-
-const uint8_t *
-woffSetMetadata(const uint8_t * woffData, uint32_t * woffLen,
-                const uint8_t * metaData, uint32_t metaLen,
-                uint32_t * pStatus)
-{
-  const woffHeader * header;
-  uLong compLen = 0;
-  uint8_t * compData = NULL;
-  const uint8_t * privData = NULL;
-  uint32_t privLen = 0;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  if (!woffData || !woffLen) {
-    FAIL(eWOFF_bad_parameter);
-  }
-
-  if (*woffLen < sizeof(woffHeader)) {
-    FAIL(eWOFF_invalid);
-  }
-  header = (const woffHeader *) (woffData);
-
-  if (READ32BE(header->signature) != WOFF_SIGNATURE) {
-    FAIL(eWOFF_bad_signature);
-  }
-
-  if (header->privOffset != 0 && header->privLen != 0) {
-    privData = woffData + READ32BE(header->privOffset);
-    privLen = READ32BE(header->privLen);
-    if (privData + privLen > woffData + *woffLen) {
-      FAIL(eWOFF_invalid);
-    }
-  }
-
-  if (metaData && metaLen > 0) {
-    compLen = compressBound(metaLen);
-    compData = malloc(compLen);
-    if (!compData) {
-      FAIL(eWOFF_out_of_memory);
-    }
-
-    if (compress2((Bytef *) compData, &compLen,
-                  (const Bytef *) metaData, metaLen, 9) != Z_OK) {
-      FAIL(eWOFF_compression_failure);
-    }
-  }
-
-  woffData = rebuildWoff(woffData, woffLen,
-                         compData, compLen, metaLen,
-                         privData, privLen, pStatus);
-  free(compData);
-  return woffData;
-
-failure:
-  if (compData) {
-    free(compData);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;
-}
-
-const uint8_t *
-woffSetPrivateData(const uint8_t * woffData, uint32_t * woffLen,
-                   const uint8_t * privData, uint32_t privLen,
-                   uint32_t * pStatus)
-{
-  const woffHeader * header;
-  const uint8_t * metaData = NULL;
-  uint32_t metaLen = 0;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  if (!woffData || !woffLen) {
-    FAIL(eWOFF_bad_parameter);
-  }
-
-  if (*woffLen < sizeof(woffHeader)) {
-    FAIL(eWOFF_invalid);
-  }
-  header = (const woffHeader *) (woffData);
-
-  if (READ32BE(header->signature) != WOFF_SIGNATURE) {
-    FAIL(eWOFF_bad_signature);
-  }
-
-  if (header->metaOffset != 0 && header->metaCompLen != 0) {
-    metaData = woffData + READ32BE(header->metaOffset);
-    metaLen = READ32BE(header->metaCompLen);
-    if (metaData + metaLen > woffData + *woffLen) {
-      FAIL(eWOFF_invalid);
-    }
-  }
-
-  woffData = rebuildWoff(woffData, woffLen,
-                         metaData, metaLen, READ32BE(header->metaOrigLen),
-                         privData, privLen, pStatus);
-  return woffData;
-
-failure:
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;
-}
-
-#endif /* WOFF_MOZILLA_CLIENT */
-
-/******************************************************************/
-/* * * * * * * * * * * * * * DECODING * * * * * * * * * * * * * * */
-/******************************************************************/
-
-static uint32_t
-sanityCheck(const uint8_t * woffData, uint32_t woffLen)
-{
-  const woffHeader * header;
-  uint16_t numTables, i;
-  const woffDirEntry * dirEntry;
-  uint64_t tableTotal = 0;
-
-  if (!woffData || !woffLen) {
-    return eWOFF_bad_parameter;
-  }
-
-  if (woffLen < sizeof(woffHeader)) {
-    return eWOFF_invalid;
-  }
-
-  header = (const woffHeader *) (woffData);
-  if (READ32BE(header->signature) != WOFF_SIGNATURE) {
-    return eWOFF_bad_signature;
-  }
-
-  if (READ32BE(header->length) != woffLen || header->reserved != 0) {
-    return eWOFF_invalid;
-  }
-
-  numTables = READ16BE(header->numTables);
-  if (woffLen < sizeof(woffHeader) + numTables * sizeof(woffDirEntry)) {
-    return eWOFF_invalid;
-  }
-
-  dirEntry = (const woffDirEntry *) (woffData + sizeof(woffHeader));
-  for (i = 0; i < numTables; ++i) {
-    uint64_t offs = READ32BE(dirEntry->offset);
-    uint64_t orig = READ32BE(dirEntry->origLen);
-    uint64_t comp = READ32BE(dirEntry->compLen);
-    if (comp > orig || comp > woffLen || offs > woffLen - comp) {
-      return eWOFF_invalid;
-    }
-    orig = (orig + 3) & ~3;
-    tableTotal += orig;
-    if (tableTotal > 0xffffffffU) {
-      return eWOFF_invalid;
-    }
-    ++dirEntry;
-  }
-
-  if (tableTotal > 0xffffffffU - sizeof(sfntHeader) -
-                                 numTables * sizeof(sfntDirEntry) ||
-      READ32BE(header->totalSfntSize) !=
-        tableTotal + sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry)) {
-    return eWOFF_invalid;
-  }
-
-  return eWOFF_ok;
-}
-
-uint32_t
-woffGetDecodedSize(const uint8_t * woffData, uint32_t woffLen,
-                   uint32_t * pStatus)
-{
-  uint32_t status = eWOFF_ok;
-  uint32_t totalLen = 0;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return 0;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  totalLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize);
-  /* totalLen must be correctly rounded up to 4-byte alignment, otherwise
-     sanityCheck would have failed */
-
-failure:
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return totalLen;
-}
-
-static void
-woffDecodeToBufferInternal(const uint8_t * woffData, uint32_t woffLen,
-                           uint8_t * sfntData, uint32_t bufferLen,
-                           uint32_t * pActualSfntLen, uint32_t * pStatus)
-{
-  /* this is only called after sanityCheck has verified that
-     (a) basic header fields are ok
-     (b) all the WOFF table offset/length pairs are valid (within the data)
-     (c) the sum of original sizes + header/directory matches totalSfntSize
-     so we don't have to re-check those overflow conditions here */
-  tableOrderRec * tableOrder = NULL;
-  const woffHeader * header;
-  uint16_t numTables;
-  uint16_t tableIndex;
-  uint16_t order;
-  const woffDirEntry * woffDir;
-  uint32_t totalLen;
-  sfntHeader * newHeader;
-  uint16_t searchRange, rangeShift, entrySelector;
-  uint32_t offset;
-  sfntDirEntry * sfntDir;
-  uint32_t headOffset = 0, headLength = 0;
-  sfntHeadTable * head;
-  uint32_t csum = 0;
-  const uint32_t * csumPtr;
-  uint32_t oldCheckSumAdjustment;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return;
-  }
-
-  /* check basic header fields */
-  header = (const woffHeader *) (woffData);
-  if (READ32BE(header->flavor) != SFNT_VERSION_TT &&
-      READ32BE(header->flavor) != SFNT_VERSION_CFF &&
-      READ32BE(header->flavor) != SFNT_VERSION_true) {
-    status |= eWOFF_warn_unknown_version;
-  }
-
-  numTables = READ16BE(header->numTables);
-  woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader));
-
-  totalLen = READ32BE(header->totalSfntSize);
-
-  /* construct the sfnt header */
-  newHeader = (sfntHeader *) (sfntData);
-  newHeader->version = header->flavor;
-  newHeader->numTables = READ16BE(numTables);
-  
-  /* calculate header fields for binary search */
-  searchRange = numTables;
-  searchRange |= (searchRange >> 1);
-  searchRange |= (searchRange >> 2);
-  searchRange |= (searchRange >> 4);
-  searchRange |= (searchRange >> 8);
-  searchRange &= ~(searchRange >> 1);
-  searchRange *= 16;
-  newHeader->searchRange = READ16BE(searchRange);
-  rangeShift = numTables * 16 - searchRange;
-  newHeader->rangeShift = READ16BE(rangeShift);
-  entrySelector = 0;
-  while (searchRange > 16) {
-    ++entrySelector;
-    searchRange >>= 1;
-  }
-  newHeader->entrySelector = READ16BE(entrySelector);
-
-  /* cannot be too big because numTables is 16-bit */
-  tableOrder = (tableOrderRec *) malloc(numTables * sizeof(tableOrderRec));
-  if (!tableOrder) {
-    FAIL(eWOFF_out_of_memory);
-  }
-  for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
-    tableOrder[tableIndex].offset = READ32BE(woffDir[tableIndex].offset);
-    tableOrder[tableIndex].oldIndex = tableIndex;
-  }
-  qsort(tableOrder, numTables, sizeof(tableOrderRec), compareOffsets);
-
-  /* process each table, filling in the sfnt directory */
-  offset = sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry);
-  sfntDir = (sfntDirEntry *) (sfntData + sizeof(sfntHeader));
-  for (order = 0; order < numTables; ++order) {
-    uint32_t origLen, compLen, tag, sourceOffset;
-    tableIndex = tableOrder[order].oldIndex;
-
-    /* validity of these was confirmed by sanityCheck */
-    origLen = READ32BE(woffDir[tableIndex].origLen);
-    compLen = READ32BE(woffDir[tableIndex].compLen);
-    sourceOffset = READ32BE(woffDir[tableIndex].offset);
-
-    sfntDir[tableIndex].tag = woffDir[tableIndex].tag;
-    sfntDir[tableIndex].offset = READ32BE(offset);
-    sfntDir[tableIndex].length = woffDir[tableIndex].origLen;
-    sfntDir[tableIndex].checksum = woffDir[tableIndex].checksum;
-    csum += READ32BE(sfntDir[tableIndex].checksum);
-
-    if (compLen < origLen) {
-      uLongf destLen = origLen;
-      if (uncompress((Bytef *)(sfntData + offset), &destLen,
-                     (const Bytef *)(woffData + sourceOffset),
-                     compLen) != Z_OK || destLen != origLen) {
-        FAIL(eWOFF_compression_failure);
-      }
-    } else {
-      memcpy(sfntData + offset, woffData + sourceOffset, origLen);
-    }
-
-    /* note that old Mac bitmap-only fonts have no 'head' table
-       (eg NISC18030.ttf) but a 'bhed' table instead */
-    tag = READ32BE(sfntDir[tableIndex].tag);
-    if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) {
-      headOffset = offset;
-      headLength = origLen;
-    }
-
-    offset += origLen;
-
-    while (offset < totalLen && (offset & 3) != 0) {
-      sfntData[offset++] = 0;
-    }
-  }
-
-  if (headOffset > 0) {
-    /* the font checksum in the 'head' table depends on all the individual
-       table checksums (collected above), plus the header and directory
-       which are added in here */
-    if (headLength < HEAD_TABLE_SIZE) {
-      FAIL(eWOFF_invalid);
-    }
-    head = (sfntHeadTable *)(sfntData + headOffset);
-    oldCheckSumAdjustment = READ32BE(head->checkSumAdjustment);
-    head->checkSumAdjustment = 0;
-    csumPtr = (const uint32_t *)sfntData;
-    while (csumPtr < (const uint32_t *)(sfntData + sizeof(sfntHeader) +
-                                        numTables * sizeof(sfntDirEntry))) {
-      csum += READ32BE(*csumPtr);
-      csumPtr++;
-    }
-    csum = SFNT_CHECKSUM_CALC_CONST - csum;
-
-    if (oldCheckSumAdjustment != csum) {
-      /* if the checksum doesn't match, we fix it; but this will invalidate
-         any DSIG that may be present */
-      status |= eWOFF_warn_checksum_mismatch;
-    }
-    head->checkSumAdjustment = READ32BE(csum);
-  }
-
-  if (pActualSfntLen) {
-    *pActualSfntLen = totalLen;
-  }
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  free(tableOrder);
-  return;
-
-failure:
-  if (tableOrder) {
-    free(tableOrder);
-  }
-  if (pActualSfntLen) {
-    *pActualSfntLen = 0;
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-}
-
-void
-woffDecodeToBuffer(const uint8_t * woffData, uint32_t woffLen,
-                   uint8_t * sfntData, uint32_t bufferLen,
-                   uint32_t * pActualSfntLen, uint32_t * pStatus)
-{
-  uint32_t status = eWOFF_ok;
-  uint32_t totalLen;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  if (!sfntData) {
-    FAIL(eWOFF_bad_parameter);
-  }
-
-  totalLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize);
-  if (bufferLen < totalLen) {
-    FAIL(eWOFF_buffer_too_small);
-  }
-
-  woffDecodeToBufferInternal(woffData, woffLen, sfntData, bufferLen,
-                             pActualSfntLen, pStatus);
-  return;
-
-failure:
-  if (pActualSfntLen) {
-    *pActualSfntLen = 0;
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-}
-
-const uint8_t *
-woffDecode(const uint8_t * woffData, uint32_t woffLen,
-           uint32_t * sfntLen, uint32_t * pStatus)
-{
-  uint32_t status = eWOFF_ok;
-  uint8_t * sfntData = NULL;
-  uint32_t bufLen;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  bufLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize);
-  sfntData = (uint8_t *) malloc(bufLen);
-  if (!sfntData) {
-    FAIL(eWOFF_out_of_memory);
-  }
-
-  woffDecodeToBufferInternal(woffData, woffLen, sfntData, bufLen,
-                             sfntLen, &status);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  return sfntData;
-
-failure:
-  if (sfntData) {
-    free(sfntData);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;
-}
-
-/* functions to get size and data of a single table */
-
-uint32_t woffGetTableSize(const uint8_t * woffData, uint32_t woffLen,
-                          uint32_t tag, uint32_t * pStatus)
-{
-  uint32_t status = eWOFF_ok;
-  const woffHeader * header;
-  uint16_t numTables;
-  uint16_t tableIndex;
-  const woffDirEntry * woffDir;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return 0;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  header = (const woffHeader *) (woffData);
-
-  numTables = READ16BE(header->numTables);
-  woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader));
-
-  for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
-    uint32_t thisTag;
-    thisTag = READ32BE(woffDir[tableIndex].tag);
-    if (thisTag < tag) {
-      continue;
-    }
-    if (thisTag > tag) {
-      break;
-    }
-    return READ32BE(woffDir[tableIndex].origLen);
-  }
-
-  status = eWOFF_warn_no_such_table;
-
-failure:
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return 0;
-}
-
-void woffGetTableToBuffer(const uint8_t * woffData, uint32_t woffLen,
-                          uint32_t tag, uint8_t * buffer, uint32_t bufferLen,
-                          uint32_t * pTableLen, uint32_t * pStatus)
-{
-  uint32_t status = eWOFF_ok;
-  const woffHeader * header;
-  uint16_t numTables;
-  uint16_t tableIndex;
-  const woffDirEntry * woffDir;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  header = (const woffHeader *) (woffData);
-
-  numTables = READ16BE(header->numTables);
-  woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader));
-
-  for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
-    uint32_t thisTag, origLen, compLen, sourceOffset;
-    thisTag = READ32BE(woffDir[tableIndex].tag);
-    if (thisTag < tag) {
-      continue;
-    }
-    if (thisTag > tag) {
-      break;
-    }
-
-    /* found the required table: decompress it (checking for overflow) */
-    origLen = READ32BE(woffDir[tableIndex].origLen);
-    if (origLen > bufferLen) {
-      FAIL(eWOFF_buffer_too_small);
-    }
-
-    compLen = READ32BE(woffDir[tableIndex].compLen);
-    sourceOffset = READ32BE(woffDir[tableIndex].offset);
-
-    if (compLen < origLen) {
-      uLongf destLen = origLen;
-      if (uncompress((Bytef *)(buffer), &destLen,
-                     (const Bytef *)(woffData + sourceOffset),
-                     compLen) != Z_OK || destLen != origLen) {
-        FAIL(eWOFF_compression_failure);
-      }
-    } else {
-      memcpy(buffer, woffData + sourceOffset, origLen);
-    }
-
-    if (pTableLen) {
-      *pTableLen = origLen;
-    }
-
-    return;
-  }
-
-  status = eWOFF_warn_no_such_table;
-
-failure:
-  if (pStatus) {
-    *pStatus = status;
-  }
-}
-
-
-#ifndef WOFF_MOZILLA_CLIENT
-
-const uint8_t *
-woffGetMetadata(const uint8_t * woffData, uint32_t woffLen,
-                uint32_t * metaLen, uint32_t * pStatus)
-{
-  const woffHeader * header;
-  uint32_t offset, compLen;
-  uLong origLen;
-  uint8_t * data = NULL;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  header = (const woffHeader *) (woffData);
-
-  offset = READ32BE(header->metaOffset);
-  compLen = READ32BE(header->metaCompLen);
-  origLen = READ32BE(header->metaOrigLen);
-  if (offset == 0 || compLen == 0 || origLen == 0) {
-    return NULL;
-  }
-
-  if (compLen > woffLen || offset > woffLen - compLen) {
-    FAIL(eWOFF_invalid);
-  }
-
-  data = malloc(origLen);
-  if (!data) {
-    FAIL(eWOFF_out_of_memory);
-  }
-
-  if (uncompress((Bytef *)data, &origLen,
-                 (const Bytef *)woffData + offset, compLen) != Z_OK ||
-      origLen != READ32BE(header->metaOrigLen)) {
-    FAIL(eWOFF_compression_failure);
-  }
-
-  if (metaLen) {
-    *metaLen = origLen;
-  }
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  return data;
-
-failure:
-  if (data) {
-    free(data);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;    
-}
-
-const uint8_t *
-woffGetPrivateData(const uint8_t * woffData, uint32_t woffLen,
-                   uint32_t * privLen, uint32_t * pStatus)
-{
-  const woffHeader * header;
-  uint32_t offset, length;
-  uint8_t * data = NULL;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return NULL;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  header = (const woffHeader *) (woffData);
-
-  offset = READ32BE(header->privOffset);
-  length = READ32BE(header->privLen);
-  if (offset == 0 || length == 0) {
-    return NULL;
-  }
-
-  if (length > woffLen || offset > woffLen - length) {
-    FAIL(eWOFF_invalid);
-  }
-
-  data = malloc(length);
-  if (!data) {
-    FAIL(eWOFF_out_of_memory);
-  }
-
-  memcpy(data, woffData + offset, length);
-
-  if (privLen) {
-    *privLen = length;
-  }
-  if (pStatus) {
-    *pStatus |= status;
-  }
-  return data;
-
-failure:
-  if (data) {
-    free(data);
-  }
-  if (pStatus) {
-    *pStatus = status;
-  }
-  return NULL;    
-}
-
-void
-woffGetFontVersion(const uint8_t * woffData, uint32_t woffLen,
-                   uint16_t * major, uint16_t * minor, uint32_t * pStatus)
-{
-  const woffHeader * header;
-  uint32_t status = eWOFF_ok;
-
-  if (pStatus && WOFF_FAILURE(*pStatus)) {
-    return;
-  }
-
-  status = sanityCheck(woffData, woffLen);
-  if (WOFF_FAILURE(status)) {
-    FAIL(status);
-  }
-
-  if (!major || !minor) {
-    FAIL(eWOFF_bad_parameter);
-  }
-
-  *major = *minor = 0;
-
-  header = (const woffHeader *) (woffData);
-
-  *major = READ16BE(header->majorVersion);
-  *minor = READ16BE(header->minorVersion);
-
-failure:
-  if (pStatus) {
-    *pStatus = status;
-  }
-}
-
-/* utility to print messages corresponding to WOFF encoder/decoder errors */
-void
-woffPrintStatus(FILE * f, uint32_t status, const char * prefix)
-{
-  if (!prefix) {
-    prefix = "";
-  }
-  if (WOFF_WARNING(status)) {
-    const char * template = "%sWOFF warning: %s\n";
-    if (status & eWOFF_warn_unknown_version) {
-      fprintf(f, template, prefix, "unrecognized sfnt version");
-    }
-    if (status & eWOFF_warn_checksum_mismatch) {
-      fprintf(f, template, prefix, "checksum mismatch (corrected)");
-    }
-    if (status & eWOFF_warn_misaligned_table) {
-      fprintf(f, template, prefix, "misaligned font table");
-    }
-    if (status & eWOFF_warn_trailing_data) {
-      fprintf(f, template, prefix, "extraneous input data discarded");
-    }
-    if (status & eWOFF_warn_unpadded_table) {
-      fprintf(f, template, prefix, "final table not correctly padded");
-    }
-    if (status & eWOFF_warn_removed_DSIG) {
-      fprintf(f, template, prefix, "digital signature (DSIG) table removed");
-    }
-  }
-  if (WOFF_FAILURE(status)) {
-    const char * template = "%sWOFF error: %s\n";
-    const char * msg;
-    switch (status & 0xff) {
-    case eWOFF_out_of_memory:
-      msg = "memory allocation failure";
-      break;
-    case eWOFF_invalid:
-      msg = "invalid input font";
-      break;
-    case eWOFF_compression_failure:
-      msg = "zlib compression/decompression failure";
-      break;
-    case eWOFF_bad_signature:
-      msg = "incorrect WOFF file signature";
-      break;
-    case eWOFF_buffer_too_small:
-      msg = "buffer too small";
-      break;
-    case eWOFF_bad_parameter:
-      msg = "bad parameter to WOFF function";
-      break;
-    case eWOFF_illegal_order:
-      msg = "incorrect table directory order";
-      break;
-    default:
-      msg = "unknown internal error";
-      break;
-    }
-    fprintf(f, template, prefix, msg);
-  }
-}
-
-#endif /* not WOFF_MOZILLA_CLIENT */
deleted file mode 100644
--- a/gfx/thebes/woff.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WOFF_H_
-#define WOFF_H_
-
-/* API for the WOFF encoder and decoder */
-
-#include "mozilla/StandardInteger.h"
-
-#include <stdio.h> /* only for FILE, needed for woffPrintStatus */
-
-/* error codes returned in the status parameter of WOFF functions */
-enum {
-  /* Success */
-  eWOFF_ok = 0,
-
-  /* Errors: no valid result returned */
-  eWOFF_out_of_memory = 1,       /* malloc or realloc failed */
-  eWOFF_invalid = 2,             /* invalid input file (e.g., bad offset) */
-  eWOFF_compression_failure = 3, /* error in zlib call */
-  eWOFF_bad_signature = 4,       /* unrecognized file signature */
-  eWOFF_buffer_too_small = 5,    /* the provided buffer is too small */
-  eWOFF_bad_parameter = 6,       /* bad parameter (e.g., null source ptr) */
-  eWOFF_illegal_order = 7,       /* improperly ordered chunks in WOFF font */
-
-  /* Warnings: call succeeded but something odd was noticed.
-     Multiple warnings may be OR'd together. */
-  eWOFF_warn_unknown_version = 0x0100,   /* unrecognized version of sfnt,
-                                            not standard TrueType or CFF */
-  eWOFF_warn_checksum_mismatch = 0x0200, /* bad checksum, use with caution;
-                                            any DSIG will be invalid */
-  eWOFF_warn_misaligned_table = 0x0400,  /* table not long-aligned; fixing,
-                                            but DSIG will be invalid */
-  eWOFF_warn_trailing_data = 0x0800,     /* trailing junk discarded,
-                                            any DSIG may be invalid */
-  eWOFF_warn_unpadded_table = 0x1000,    /* sfnt not correctly padded,
-                                            any DSIG may be invalid */
-  eWOFF_warn_removed_DSIG = 0x2000,      /* removed digital signature
-                                            while fixing checksum errors */
-  eWOFF_warn_no_such_table = 0x4000      /* specified table not present */
-};
-
-/* Note: status parameters must be initialized to eWOFF_ok before calling
-   WOFF functions. If the status parameter contains an error code,
-   functions will return immediately. */
-
-#define WOFF_SUCCESS(status) (((uint32_t)(status) & 0xff) == eWOFF_ok)
-#define WOFF_FAILURE(status) (!WOFF_SUCCESS(status))
-#define WOFF_WARNING(status) ((uint32_t)(status) & ~0xff)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef WOFF_DISABLE_ENCODING
-
-/*****************************************************************************
- * Returns a new malloc() block containing the encoded data, or NULL on error;
- * caller should free() this when finished with it.
- * Returns length of the encoded data in woffLen.
- * The new WOFF has no metadata or private block;
- * see the following functions to update these elements.
- */
-const uint8_t * woffEncode(const uint8_t * sfntData, uint32_t sfntLen,
-                           uint16_t majorVersion, uint16_t minorVersion,
-                           uint32_t * woffLen, uint32_t * status);
-
-
-/*****************************************************************************
- * Add the given metadata block to the WOFF font, replacing any existing
- * metadata block. The block will be zlib-compressed.
- * Metadata is required to be valid XML (use of UTF-8 is recommended),
- * though this function does not currently check this.
- * The woffData pointer must be a malloc() block (typically from woffEncode);
- * it will be freed by this function and a new malloc() block will be returned.
- * Returns NULL if an error occurs, in which case the original WOFF is NOT freed.
- */
-const uint8_t * woffSetMetadata(const uint8_t * woffData, uint32_t * woffLen,
-                                const uint8_t * metaData, uint32_t metaLen,
-                                uint32_t * status);
-
-
-/*****************************************************************************
- * Add the given private data block to the WOFF font, replacing any existing
- * private block. The block will NOT be zlib-compressed.
- * Private data may be any arbitrary block of bytes; it may be externally
- * compressed by the client if desired.
- * The woffData pointer must be a malloc() block (typically from woffEncode);
- * it will be freed by this function and a new malloc() block will be returned.
- * Returns NULL if an error occurs, in which case the original WOFF is NOT freed.
- */
-const uint8_t * woffSetPrivateData(const uint8_t * woffData, uint32_t * woffLen,
-                                   const uint8_t * privData, uint32_t privLen,
-                                   uint32_t * status);
-
-#endif /* WOFF_DISABLE_ENCODING */
-
-/*****************************************************************************
- * Returns the size of buffer needed to decode the font (or zero on error).
- */
-uint32_t woffGetDecodedSize(const uint8_t * woffData, uint32_t woffLen,
-                            uint32_t * pStatus);
-
-
-/*****************************************************************************
- * Decodes WOFF font to a caller-supplied buffer of size bufferLen.
- * Returns the actual size of the decoded sfnt data in pActualSfntLen
- * (must be <= bufferLen, otherwise an error will be returned).
- */
-void woffDecodeToBuffer(const uint8_t * woffData, uint32_t woffLen,
-                        uint8_t * sfntData, uint32_t bufferLen,
-                        uint32_t * pActualSfntLen, uint32_t * pStatus);
-
-
-/*****************************************************************************
- * Returns a new malloc() block containing the decoded data, or NULL on error;
- * caller should free() this when finished with it.
- * Returns length of the decoded data in sfntLen.
- */
-const uint8_t * woffDecode(const uint8_t * woffData, uint32_t woffLen,
-                           uint32_t * sfntLen, uint32_t * status);
-
-
-/*****************************************************************************
- * Returns the size of buffer needed for a specific table (or zero on error).
- */
-uint32_t woffGetTableSize(const uint8_t * woffData, uint32_t woffLen,
-                          uint32_t tag, uint32_t * pStatus);
-
-
-/*****************************************************************************
- * Gets a table from a WOFF font to a caller-supplied buffer of size bufferLen.
- * Returns the actual size of the decoded table in pTableLen
- * (must be <= bufferLen, otherwise an error will be returned).
- */
-void woffGetTableToBuffer(const uint8_t * woffData, uint32_t woffLen,
-                          uint32_t tag, uint8_t * buffer, uint32_t bufferLen,
-                          uint32_t * pTableLen, uint32_t * pStatus);
-
-
-/*****************************************************************************
- * Returns a new malloc() block containing the metadata from the WOFF font,
- * or NULL if an error occurs or no metadata is present.
- * Length of the metadata is returned in metaLen.
- * The metadata is decompressed before returning.
- */
-const uint8_t * woffGetMetadata(const uint8_t * woffData, uint32_t woffLen,
-                                uint32_t * metaLen, uint32_t * status);
-
-
-/*****************************************************************************
- * Returns a new malloc() block containing the private data from the WOFF font,
- * or NULL if an error occurs or no private data is present.
- * Length of the private data is returned in privLen.
- */
-const uint8_t * woffGetPrivateData(const uint8_t * woffData, uint32_t woffLen,
-                                   uint32_t * privLen, uint32_t * status);
-
-
-/*****************************************************************************
- * Returns the font version numbers from the WOFF font in the major and minor
- * parameters.
- * Check the status result to know if the function succeeded.
- */
-void woffGetFontVersion(const uint8_t * woffData, uint32_t woffLen,
-                        uint16_t * major, uint16_t * minor,
-                        uint32_t * status);
-
-
-/*****************************************************************************
- * Utility to print warning and/or error status to the specified FILE*.
- * The prefix string will be prepended to each line (ok to pass NULL if no
- * prefix is wanted).
- * (Provides terse English messages only, not intended for end-user display;
- * user-friendly tools should map the status codes to their own messages.)
- */
-void woffPrintStatus(FILE * f, uint32_t status, const char * prefix);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -206,17 +206,16 @@ pref("gfx.hidpi.enabled", 2);
 // See eCMSMode in gfx/thebes/gfxPlatform.h
 pref("gfx.color_management.mode", 2);
 pref("gfx.color_management.display_profile", "");
 pref("gfx.color_management.rendering_intent", 0);
 pref("gfx.color_management.enablev4", false);
 
 pref("gfx.downloadable_fonts.enabled", true);
 pref("gfx.downloadable_fonts.fallback_delay", 3000);
-pref("gfx.downloadable_fonts.sanitize", true);
 
 pref("gfx.filter.nearest.force-enabled", false);
 
 // whether to always search all font cmaps during system font fallback
 pref("gfx.font_rendering.fallback.always_use_cmaps", false);
 
 #ifdef MOZ_GRAPHITE
 pref("gfx.font_rendering.graphite.enabled", false);