Firefox · Graphics
CVE-2026-117886
Logic Error in Graphics
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
OTS_APIgfx/ots/include/opentype-sanitiser.h |
modified | |
OTSContextgfx/ots/include/opentype-sanitiser.h |
modified | |
OTSContextgfx/ots/include/opentype-sanitiser.h |
modified | |
ifgfx/ots/src/glat.cc |
modified | |
ifgfx/ots/src/glyf.cc |
modified | |
ifgfx/ots/src/ots.cc |
modified | |
ifgfx/ots/src/silf.cc |
modified |
Files Changed
gfx/ots/include/opentype-sanitiser.hgfx/ots/moz.yamlgfx/ots/src/glat.ccgfx/ots/src/glyf.ccgfx/ots/src/ots.ccgfx/ots/src/silf.cc
Patch
diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-sanitiser.h
index 27d4d5e815b..10c2042249c 100644
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -5,26 +5,6 @@
#ifndef OPENTYPE_SANITISER_H_
#define OPENTYPE_SANITISER_H_
-#if defined(_WIN32) || defined(__CYGWIN__)
- #define OTS_DLL_IMPORT __declspec(dllimport)
- #define OTS_DLL_EXPORT __declspec(dllexport)
-#else
- #if __GNUC__ >= 4
- #define OTS_DLL_IMPORT __attribute__((visibility ("default")))
- #define OTS_DLL_EXPORT __attribute__((visibility ("default")))
- #endif
-#endif
-
-#ifdef OTS_DLL
- #ifdef OTS_DLL_EXPORTS
- #define OTS_API OTS_DLL_EXPORT
- #else
- #define OTS_API OTS_DLL_IMPORT
- #endif
-#else
- #define OTS_API
-#endif
-
#if defined(_WIN32)
#include <stdlib.h>
typedef signed char int8_t;
@@ -197,7 +177,7 @@ enum TableAction {
// sanitzation even if this table fails/is dropped
};
-class OTS_API OTSContext {
+class OTSContext {
public:
OTSContext() {}
virtual ~OTSContext() {}
diff --git a/gfx/ots/moz.yaml b/gfx/ots/moz.yaml
index 4abf77379c2..ca77d575d47 100644
--- a/gfx/ots/moz.yaml
+++ b/gfx/ots/moz.yaml
@@ -10,8 +10,8 @@ origin:
url: https://github.com/khaledhosny/ots
- release: 62634335137d86473c84b20a8de9b9d97645bbd6 (2026-09-11T14:03:29Z).
- revision: 62634335137d86473c84b20a8de9b9d97645bbd6
+ release: 6540e90426c17de7ddcae650409a9af5a450ea7a (2026-10-13T11:40:17Z).
+ revision: 6540e90426c17de7ddcae650409a9af5a450ea7a
license: BSD-3-Clause
license-file: LICENSE
diff --git a/gfx/ots/src/glat.cc b/gfx/ots/src/glat.cc
index 296e208628c..6c9079c47c2 100644
--- a/gfx/ots/src/glat.cc
+++ b/gfx/ots/src/glat.cc
@@ -5,7 +5,7 @@
#include "glat.h"
#include "gloc.h"
-#include "mozilla/Compression.h"
+#include "lz4.h"
#include <list>
#include <memory>
@@ -217,15 +217,14 @@ bool OpenTypeGLAT_v3::Parse(const uint8_t* data, size_t length,
decompressed_size / (1024.0 * 1024.0));
}
std::unique_ptr<uint8_t> decompressed(new uint8_t[decompressed_size]());
- size_t outputSize = 0;
- bool ret = mozilla::Compression::LZ4::decompressPartial(
+ int ret = LZ4_decompress_safe_partial(
reinterpret_cast<const char*>(data + table.offset()),
- table.remaining(), // input buffer size (input size + padding)
reinterpret_cast<char*>(decompressed.get()),
+ table.remaining(), // input buffer size (input size + padding)
decompressed_size, // target output size
- &outputSize); // output buffer size
- if (!ret || outputSize != decompressed_size) {
- return DropGraphite("Decompression failed");
+ decompressed_size); // output buffer size
+ if (ret < 0 || unsigned(ret) != decompressed_size) {
+ return DropGraphite("Decompression failed with error code %d", ret);
}
return this->Parse(decompressed.get(), decompressed_size, true);
}
diff --git a/gfx/ots/src/glyf.cc b/gfx/ots/src/glyf.cc
index 30e836062be..2ef046edd72 100644
--- a/gfx/ots/src/glyf.cc
+++ b/gfx/ots/src/glyf.cc
@@ -277,7 +277,17 @@ bool OpenTypeGLYF::ParseCompositeGlyph(
std::vector<edit_rec> edits;
unsigned prev_start = 0;
bool we_have_instructions = false;
+ unsigned num_components = 0;
do {
+ if (++num_components > 0x7fff) {
+ Warning("Too many components in composite: discarding glyph %u", glyph_id);
+ // Reset the buffer position such that all the glyph data will be dropped,
+ // making it an empty (non-composite) glyph.
+ glyph.set_offset(0);
+ component_point_count->gid_stack.clear();
+ return true;
+ }
+
unsigned start = glyph.offset();
if (!glyph.ReadU16(&flags) || !glyph.ReadU16(&gid)) {
diff --git a/gfx/ots/src/ots.cc b/gfx/ots/src/ots.cc
index df7366adef3..92fb89c7e56 100644
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -14,7 +14,7 @@
#include <map>
#include <vector>
-#include "../RLBoxWOFF2Host.h"
+#include <woff2/decode.h>
// The OpenType Font File
// http://www.microsoft.com/typography/otspec/otff.htm
@@ -525,9 +525,44 @@ bool ProcessWOFF(ots::FontFile *header,
return ProcessGeneric(header, font, woff_tag, output, data, length, tables, file);
}
-bool ProcessWOFF2(ots::FontFile* header, ots::OTSStream* output,
- const uint8_t* data, size_t length, uint32_t index) {
- return RLBoxProcessWOFF2(header, output, data, length, index, ProcessTTC, ProcessTTF);
+bool ProcessWOFF2(ots::FontFile *header,
+ ots::OTSStream *output,
+ const uint8_t *data,
+ size_t length,
+ uint32_t index) {
+ size_t decompressed_size = woff2::ComputeWOFF2FinalSize(data, length);
+
+ if (decompressed_size < length) {
+ return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is less than compressed size");
+ }
+
+ if (decompressed_size == 0) {
+ return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is set to 0");
+ }
+ // decompressed font must be <= OTS_MAX_DECOMPRESSED_FILE_SIZE
+ if (decompressed_size > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
+ return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 font exceeds %gMB",
+ OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0));
+ }
+
+ if (decompressed_size > output->size()) {
+ return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 font exceeds output size (%gMB)", output->size() / (1024.0 * 1024.0));
+ }
+
+ std::string buf(decompressed_size, 0);
+ woff2::WOFF2StringOut out(&buf);
+ out.SetMaxSize(decompressed_size);
+ if (!woff2::ConvertWOFF2ToTTF(data, length, &out)) {
+ return OTS_FAILURE_MSG_HDR("Failed to convert WOFF 2.0 font to SFNT");
+ }
+ const uint8_t *decompressed = reinterpret_cast<const uint8_t*>(buf.data());
+
+ if (data[4] == 't' && data[5] == 't' && data[6] == 'c' && data[7] == 'f') {
+ return ProcessTTC(header, output, decompressed, out.Size(), index);
+ } else {
+ ots::Font font(header);
+ return ProcessTTF(header, &font, output, decompressed, out.Size());
+ }
}
ots::TableAction GetTableAction(const ots::FontFile *header, uint32_t tag) {
diff --git a/gfx/ots/src/silf.cc b/gfx/ots/src/silf.cc
index 5ac80b1864b..ea589981037 100644
--- a/gfx/ots/src/silf.cc
+++ b/gfx/ots/src/silf.cc
@@ -5,7 +5,7 @@
#include "silf.h"
#include "name.h"
-#include "mozilla/Compression.h"
+#include "lz4.h"
#include <cmath>
#include <memory>
@@ -50,15 +50,14 @@ bool OpenTypeSILF::Parse(const uint8_t* data, size_t length,
decompressed_size / (1024.0 * 1024.0));
}
std::unique_ptr<uint8_t[]> decompressed(new uint8_t[decompressed_size]());
- size_t outputSize = 0;
- bool ret = mozilla::Compression::LZ4::decompressPartial(
+ int ret = LZ4_decompress_safe_partial(
reinterpret_cast<const char*>(data + table.offset()),
- table.remaining(), // input buffer size (input size + padding)
reinterpret_cast<char*>(decompressed.get()),
+ table.remaining(), // input buffer size (input size + padding)
decompressed_size, // target output size
- &outputSize); // output buffer size
- if (!ret || outputSize != decompressed_size) {
- return DropGraphite("Decompression failed");
+ decompressed_size); // output buffer size
+ if (ret < 0 || unsigned(ret) != decompressed_size) {
+ return DropGraphite("Decompression failed with error code %d", ret);
}
return this->Parse(decompressed.get(), decompressed_size, true);
}
Loading diff…
References
On This Page