@@ -69,6 +69,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
69
69
}
70
70
}
71
71
72
+ template <typename T>
73
+ static inline bool qSafeFromBigEndian (const uchar *source, const uchar *end, T *output)
74
+ {
75
+ if (source + sizeof (T) > end)
76
+ return false ;
77
+
78
+ *output = qFromBigEndian<T>(source);
79
+ return true ;
80
+ }
81
+
72
82
// Harfbuzz helper functions
73
83
74
84
static HB_Bool hb_stringToGlyphs (HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
@@ -808,26 +818,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
808
818
return ;
809
819
810
820
const uchar *table = reinterpret_cast <const uchar *>(tab.constData ());
821
+ const uchar *end = table + tab.size ();
822
+
823
+ quint16 version;
824
+ if (!qSafeFromBigEndian (table, end, &version))
825
+ return ;
811
826
812
- unsigned short version = qFromBigEndian<quint16>(table);
813
827
if (version != 0 ) {
814
828
// qDebug("wrong version");
815
829
return ;
816
830
}
817
831
818
- unsigned short numTables = qFromBigEndian<quint16>(table + 2 );
832
+ quint16 numTables;
833
+ if (!qSafeFromBigEndian (table + 2 , end, &numTables))
834
+ return ;
835
+
819
836
{
820
837
int offset = 4 ;
821
838
for (int i = 0 ; i < numTables; ++i) {
822
- if (offset + 6 > tab.size ()) {
823
- // qDebug("offset out of bounds");
824
- goto end;
825
- }
826
839
const uchar *header = table + offset;
827
840
828
- ushort version = qFromBigEndian<quint16>(header);
829
- ushort length = qFromBigEndian<quint16>(header+2 );
830
- ushort coverage = qFromBigEndian<quint16>(header+4 );
841
+ quint16 version;
842
+ if (!qSafeFromBigEndian (header, end, &version))
843
+ goto end;
844
+
845
+ quint16 length;
846
+ if (!qSafeFromBigEndian (header + 2 , end, &length))
847
+ goto end;
848
+
849
+ quint16 coverage;
850
+ if (!qSafeFromBigEndian (header + 4 , end, &coverage))
851
+ goto end;
852
+
831
853
// qDebug("subtable: version=%d, coverage=%x",version, coverage);
832
854
if (version == 0 && coverage == 0x0001 ) {
833
855
if (offset + length > tab.size ()) {
@@ -836,7 +858,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
836
858
}
837
859
const uchar *data = table + offset + 6 ;
838
860
839
- ushort nPairs = qFromBigEndian<quint16>(data);
861
+ quint16 nPairs;
862
+ if (!qSafeFromBigEndian (data, end, &nPairs))
863
+ goto end;
864
+
840
865
if (nPairs * 6 + 8 > length - 6 ) {
841
866
// qDebug("corrupt table!");
842
867
// corrupt table
@@ -846,8 +871,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
846
871
int off = 8 ;
847
872
for (int i = 0 ; i < nPairs; ++i) {
848
873
QFontEngine::KernPair p;
849
- p.left_right = (((uint )qFromBigEndian<quint16>(data+off)) << 16 ) + qFromBigEndian<quint16>(data+off+2 );
850
- p.adjust = QFixed (((int )(short )qFromBigEndian<quint16>(data+off+4 ))) / scalingFactor;
874
+
875
+ quint16 tmp;
876
+ if (!qSafeFromBigEndian (data + off, end, &tmp))
877
+ goto end;
878
+
879
+ p.left_right = uint (tmp) << 16 ;
880
+ if (!qSafeFromBigEndian (data + off + 2 , end, &tmp))
881
+ goto end;
882
+
883
+ p.left_right |= tmp;
884
+
885
+ if (!qSafeFromBigEndian (data + off + 4 , end, &tmp))
886
+ goto end;
887
+
888
+ p.adjust = QFixed (int (short (tmp))) / scalingFactor;
851
889
kerning_pairs.append (p);
852
890
off += 6 ;
853
891
}
@@ -872,26 +910,31 @@ int QFontEngine::glyphCount() const
872
910
QByteArray maxpTable = getSfntTable (MAKE_TAG (' m' , ' a' , ' x' , ' p' ));
873
911
if (maxpTable.size () < 6 )
874
912
return 0 ;
875
- return qFromBigEndian<quint16>(reinterpret_cast <const uchar *>(maxpTable.constData () + 4 ));
913
+
914
+ const uchar *source = reinterpret_cast <const uchar *>(maxpTable.constData () + 4 );
915
+ const uchar *end = source + maxpTable.size ();
916
+
917
+ quint16 count = 0 ;
918
+ qSafeFromBigEndian (source, end, &count);
919
+ return count;
876
920
}
877
921
878
922
const uchar *QFontEngine::getCMap (const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
879
923
{
880
924
const uchar *header = table;
881
- if (tableSize < 4 )
882
- return 0 ;
883
-
884
925
const uchar *endPtr = table + tableSize;
885
926
886
927
// version check
887
- if (qFromBigEndian<quint16>(header) != 0 )
928
+ quint16 version;
929
+ if (!qSafeFromBigEndian (header, endPtr, &version) || version != 0 )
888
930
return 0 ;
889
931
890
- unsigned short numTables = qFromBigEndian<quint16>(header + 2 );
891
- const uchar *maps = table + 4 ;
892
- if (maps + 8 * numTables > endPtr)
932
+ quint16 numTables;
933
+ if (!qSafeFromBigEndian (header + 2 , endPtr, &numTables))
893
934
return 0 ;
894
935
936
+ const uchar *maps = table + 4 ;
937
+
895
938
enum {
896
939
Invalid,
897
940
AppleRoman,
@@ -906,8 +949,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
906
949
int tableToUse = -1 ;
907
950
int score = Invalid;
908
951
for (int n = 0 ; n < numTables; ++n) {
909
- const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
910
- const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2 );
952
+ quint16 platformId;
953
+ if (!qSafeFromBigEndian (maps + 8 * n, endPtr, &platformId))
954
+ return 0 ;
955
+
956
+ quint16 platformSpecificId;
957
+ if (!qSafeFromBigEndian (maps + 8 * n + 2 , endPtr, &platformSpecificId))
958
+ return 0 ;
959
+
911
960
switch (platformId) {
912
961
case 0 : // Unicode
913
962
if (score < Unicode &&
@@ -961,20 +1010,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
961
1010
resolveTable:
962
1011
*isSymbolFont = (symbolTable > -1 );
963
1012
964
- unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8 *tableToUse + 4 );
1013
+ quint32 unicode_table;
1014
+ if (!qSafeFromBigEndian (maps + 8 * tableToUse + 4 , endPtr, &unicode_table))
1015
+ return 0 ;
965
1016
966
- if (!unicode_table || unicode_table + 8 > tableSize )
1017
+ if (!unicode_table)
967
1018
return 0 ;
968
1019
969
1020
// get the header of the unicode table
970
1021
header = table + unicode_table;
971
1022
972
- unsigned short format = qFromBigEndian<quint16>(header);
973
- unsigned int length;
974
- if (format < 8 )
975
- length = qFromBigEndian<quint16>(header + 2 );
976
- else
977
- length = qFromBigEndian<quint32>(header + 4 );
1023
+ quint16 format;
1024
+ if (!qSafeFromBigEndian (header, endPtr, &format))
1025
+ return 0 ;
1026
+
1027
+ quint32 length;
1028
+ if (format < 8 ) {
1029
+ quint16 tmp;
1030
+ if (!qSafeFromBigEndian (header + 2 , endPtr, &tmp))
1031
+ return 0 ;
1032
+ length = tmp;
1033
+ } else {
1034
+ if (!qSafeFromBigEndian (header + 4 , endPtr, &length))
1035
+ return 0 ;
1036
+ }
978
1037
979
1038
if (table + unicode_table + length > endPtr)
980
1039
return 0 ;
@@ -989,7 +1048,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
989
1048
// Check that none of the latin1 range are in the unicode table
990
1049
bool unicodeTableHasLatin1 = false ;
991
1050
for (int uc=0x00 ; uc<0x100 ; ++uc) {
992
- if (getTrueTypeGlyphIndex (selectedTable, uc) != 0 ) {
1051
+ if (getTrueTypeGlyphIndex (selectedTable, length, uc) != 0 ) {
993
1052
unicodeTableHasLatin1 = true ;
994
1053
break ;
995
1054
}
@@ -999,7 +1058,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
999
1058
bool unicodeTableHasSymbols = false ;
1000
1059
if (!unicodeTableHasLatin1) {
1001
1060
for (int uc=0xf000 ; uc<0xf100 ; ++uc) {
1002
- if (getTrueTypeGlyphIndex (selectedTable, uc) != 0 ) {
1061
+ if (getTrueTypeGlyphIndex (selectedTable, length, uc) != 0 ) {
1003
1062
unicodeTableHasSymbols = true ;
1004
1063
break ;
1005
1064
}
@@ -1017,12 +1076,17 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
1017
1076
return table + unicode_table;
1018
1077
}
1019
1078
1020
- quint32 QFontEngine::getTrueTypeGlyphIndex (const uchar *cmap, uint unicode)
1079
+ quint32 QFontEngine::getTrueTypeGlyphIndex (const uchar *cmap, int cmapSize, uint unicode)
1021
1080
{
1022
- unsigned short format = qFromBigEndian<quint16>(cmap);
1081
+ const uchar *end = cmap + cmapSize;
1082
+ quint16 format;
1083
+ if (!qSafeFromBigEndian (cmap, end, &format))
1084
+ return 0 ;
1085
+
1023
1086
if (format == 0 ) {
1024
- if (unicode < 256 )
1025
- return (int ) *(cmap+6 +unicode);
1087
+ const uchar *ptr = cmap + 6 + unicode;
1088
+ if (unicode < 256 && ptr < end)
1089
+ return quint32 (*ptr);
1026
1090
} else if (format == 4 ) {
1027
1091
/* some fonts come with invalid cmap tables, where the last segment
1028
1092
specified end = start = rangeoffset = 0xffff, delta = 0x0001
@@ -1031,25 +1095,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
1031
1095
*/
1032
1096
if (unicode >= 0xffff )
1033
1097
return 0 ;
1034
- quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6 );
1098
+
1099
+ quint16 segCountX2;
1100
+ if (!qSafeFromBigEndian (cmap + 6 , end, &segCountX2))
1101
+ return 0 ;
1102
+
1035
1103
const unsigned char *ends = cmap + 14 ;
1104
+
1036
1105
int i = 0 ;
1037
- for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2 *i) < unicode; i++) {}
1106
+ for (; i < segCountX2/2 ; ++i) {
1107
+ quint16 codePoint;
1108
+ if (!qSafeFromBigEndian (ends + 2 * i, end, &codePoint))
1109
+ return 0 ;
1110
+ if (codePoint >= unicode)
1111
+ break ;
1112
+ }
1038
1113
1039
1114
const unsigned char *idx = ends + segCountX2 + 2 + 2 *i;
1040
- quint16 startIndex = qFromBigEndian<quint16>(idx);
1041
1115
1116
+ quint16 startIndex;
1117
+ if (!qSafeFromBigEndian (idx, end, &startIndex))
1118
+ return 0 ;
1042
1119
if (startIndex > unicode)
1043
1120
return 0 ;
1044
1121
1045
1122
idx += segCountX2;
1046
- qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
1123
+
1124
+ quint16 tmp;
1125
+ if (!qSafeFromBigEndian (idx, end, &tmp))
1126
+ return 0 ;
1127
+ qint16 idDelta = qint16 (tmp);
1128
+
1047
1129
idx += segCountX2;
1048
- quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
1130
+
1131
+ quint16 idRangeoffset_t;
1132
+ if (!qSafeFromBigEndian (idx, end, &idRangeoffset_t))
1133
+ return 0 ;
1049
1134
1050
1135
quint16 glyphIndex;
1051
1136
if (idRangeoffset_t) {
1052
- quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2 *(unicode - startIndex) + idx);
1137
+ quint16 id;
1138
+ if (!qSafeFromBigEndian (idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
1139
+ return 0 ;
1140
+
1053
1141
if (id)
1054
1142
glyphIndex = (idDelta + id) % 0x10000 ;
1055
1143
else
@@ -1059,13 +1147,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
1059
1147
}
1060
1148
return glyphIndex;
1061
1149
} else if (format == 6 ) {
1062
- quint16 tableSize = qFromBigEndian<quint16>(cmap + 2 );
1150
+ quint16 tableSize;
1151
+ if (!qSafeFromBigEndian (cmap + 2 , end, &tableSize))
1152
+ return 0 ;
1063
1153
1064
- quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6 );
1154
+ quint16 firstCode6;
1155
+ if (!qSafeFromBigEndian (cmap + 6 , end, &firstCode6))
1156
+ return 0 ;
1065
1157
if (unicode < firstCode6)
1066
1158
return 0 ;
1067
1159
1068
- quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8 );
1160
+ quint16 entryCount6;
1161
+ if (!qSafeFromBigEndian (cmap + 8 , end, &entryCount6))
1162
+ return 0 ;
1069
1163
if (entryCount6 * 2 + 10 > tableSize)
1070
1164
return 0 ;
1071
1165
@@ -1074,23 +1168,39 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
1074
1168
return 0 ;
1075
1169
1076
1170
quint16 entryIndex6 = unicode - firstCode6;
1077
- return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2 ));
1171
+
1172
+ quint16 index = 0 ;
1173
+ qSafeFromBigEndian (cmap + 10 + (entryIndex6 * 2 ), end, &index );
1174
+ return index ;
1078
1175
} else if (format == 12 ) {
1079
- quint32 nGroups = qFromBigEndian<quint32>(cmap + 12 );
1176
+ quint32 nGroups;
1177
+ if (!qSafeFromBigEndian (cmap + 12 , end, &nGroups))
1178
+ return 0 ;
1080
1179
1081
1180
cmap += 16 ; // move to start of groups
1082
1181
1083
1182
int left = 0 , right = nGroups - 1 ;
1084
1183
while (left <= right) {
1085
1184
int middle = left + ( ( right - left ) >> 1 );
1086
1185
1087
- quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12 *middle);
1186
+ quint32 startCharCode;
1187
+ if (!qSafeFromBigEndian (cmap + 12 * middle, end, &startCharCode))
1188
+ return 0 ;
1189
+
1088
1190
if (unicode < startCharCode)
1089
1191
right = middle - 1 ;
1090
1192
else {
1091
- quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12 *middle + 4 );
1092
- if (unicode <= endCharCode)
1093
- return qFromBigEndian<quint32>(cmap + 12 *middle + 8 ) + unicode - startCharCode;
1193
+ quint32 endCharCode;
1194
+ if (!qSafeFromBigEndian (cmap + 12 * middle + 4 , end, &endCharCode))
1195
+ return 0 ;
1196
+
1197
+ if (unicode <= endCharCode) {
1198
+ quint32 index ;
1199
+ if (!qSafeFromBigEndian (cmap + 12 * middle + 8 , end, &index ))
1200
+ return 0 ;
1201
+
1202
+ return index + unicode - startCharCode;
1203
+ }
1094
1204
left = middle + 1 ;
1095
1205
}
1096
1206
}
0 commit comments