Avoid infinite loop in CoverageFormat2 iteration with bad fonts

Fixes https://github.com/behdad/harfbuzz/issues/363
This commit is contained in:
Behdad Esfahbod 2016-12-21 15:51:28 -06:00
parent a0688e8e7b
commit eab418c5e6
1 changed files with 18 additions and 11 deletions

View File

@ -731,8 +731,8 @@ struct CoverageFormat1
inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
inline bool more (void) { return i < c->glyphArray.len; } inline bool more (void) { return i < c->glyphArray.len; }
inline void next (void) { i++; } inline void next (void) { i++; }
inline uint16_t get_glyph (void) { return c->glyphArray[i]; } inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
inline uint16_t get_coverage (void) { return i; } inline unsigned int get_coverage (void) { return i; }
private: private:
const struct CoverageFormat1 *c; const struct CoverageFormat1 *c;
@ -829,26 +829,33 @@ struct CoverageFormat2
public: public:
/* Older compilers need this to be public. */ /* Older compilers need this to be public. */
struct Iter { struct Iter
inline void init (const CoverageFormat2 &c_) { {
inline void init (const CoverageFormat2 &c_)
{
c = &c_; c = &c_;
coverage = 0; coverage = 0;
i = 0; i = 0;
j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
} }
inline bool more (void) { return i < c->rangeRecord.len; } inline bool more (void) { return i < c->rangeRecord.len; }
inline void next (void) { inline void next (void)
coverage++; {
if (j == c->rangeRecord[i].end) { if (j >= c->rangeRecord[i].end)
{
i++; i++;
if (more ()) if (more ())
{
j = c->rangeRecord[i].start; j = c->rangeRecord[i].start;
coverage = c->rangeRecord[i].value;
}
return; return;
} }
coverage++;
j++; j++;
} }
inline uint16_t get_glyph (void) { return j; } inline hb_codepoint_t get_glyph (void) { return j; }
inline uint16_t get_coverage (void) { return coverage; } inline unsigned int get_coverage (void) { return coverage; }
private: private:
const struct CoverageFormat2 *c; const struct CoverageFormat2 *c;
@ -957,14 +964,14 @@ struct Coverage
default: break; default: break;
} }
} }
inline uint16_t get_glyph (void) { inline hb_codepoint_t get_glyph (void) {
switch (format) { switch (format) {
case 1: return u.format1.get_glyph (); case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph (); case 2: return u.format2.get_glyph ();
default:return 0; default:return 0;
} }
} }
inline uint16_t get_coverage (void) { inline unsigned int get_coverage (void) {
switch (format) { switch (format) {
case 1: return u.format1.get_coverage (); case 1: return u.format1.get_coverage ();
case 2: return u.format2.get_coverage (); case 2: return u.format2.get_coverage ();