1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
Description: Add arithmetic overflow checks in woff encoding routines
Origin: mozilla-central, https://hg.mozilla.org/mozilla-central/rev/69eb050f2c0a
Last-Update: 2013-04-11
--- a/woff.c
+++ b/woff.c
@@ -89,10 +89,15 @@
const uint32_t * csumPtr;
const uint32_t * csumEnd;
uint32_t csum = 0;
- uint32_t length = LONGALIGN(READ32BE(dirEntry->length));
+ uint32_t length = READ32BE(dirEntry->length);
uint32_t offset = READ32BE(dirEntry->offset);
uint32_t tag;
- if ((offset & 3) != 0) {
+ 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) {
@@ -224,6 +229,9 @@
if (tag == TABLE_TAG_DSIG) {
status |= eWOFF_warn_removed_DSIG;
removedDsigSize = READ32BE(sfntDir[tableIndex].length);
+ if (LONGALIGN(removedDsigSize) < removedDsigSize) {
+ FAIL(eWOFF_invalid);
+ }
continue;
}
}
@@ -235,6 +243,7 @@
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) {
@@ -277,7 +286,15 @@
if (sourceLen > sfntLen || sourceOffset > sfntLen - sourceLen) {
FAIL(eWOFF_invalid);
}
- destLen = LONGALIGN(compressBound(sourceLen));
+ 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);
@@ -291,13 +308,19 @@
}
if (destLen < sourceLen) {
/* compressed table was smaller */
- tableOffset += destLen;
+ 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) {
@@ -306,6 +329,9 @@
/* 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;
}
@@ -316,7 +342,13 @@
}
/* 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);
}
@@ -442,10 +474,20 @@
totalSize = tableLimit; /* already long-aligned */
if (metaCompLen) {
+ if (totalSize + metaCompLen < totalSize) {
+ FAIL(eWOFF_invalid);
+ }
totalSize += metaCompLen;
}
if (privLen) {
- totalSize = LONGALIGN(totalSize) + 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) {
|