bug 633322 - ensure GetDetailedGlyphs() is not called when glyph count is zero. r=roc a=blocking
authorJonathan Kew <jfkthame@gmail.com>
Fri, 11 Feb 2011 22:05:09 +0000
changeset 62426 fcf6c9b3bd7d797f825fd44ca33c39ff5f5eb26d
parent 62425 43a8f82dfb3de98c12e6c8606899faa9cdf9ed29
child 62427 f36e81d4d60dc115d49219fa5cc0841e5d2cedbb
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewersroc, blocking
bugs633322
milestone2.0b12pre
bug 633322 - ensure GetDetailedGlyphs() is not called when glyph count is zero. r=roc a=blocking
gfx/thebes/gfxFont.h
layout/generic/nsTextRunTransformations.cpp
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1921,22 +1921,28 @@ public:
      * that some glyph extents might not be fetched due to OOM or other
      * errors.
      */
     void FetchGlyphExtents(gfxContext *aRefContext);
 
     // API for access to the raw glyph data, needed by gfxFont::Draw
     // and gfxFont::GetBoundingBox
     const CompressedGlyph *GetCharacterGlyphs() { return mCharacterGlyphs; }
+
+    // NOTE that this must not be called for a character offset that does
+    // not have any DetailedGlyph records; callers must have verified that
+    // mCharacterGlyphs[aCharIndex].GetGlyphCount() is greater than zero.
     DetailedGlyph *GetDetailedGlyphs(PRUint32 aCharIndex) {
-        if (!mDetailedGlyphs) {
-            return nsnull;
-        }
+        NS_ASSERTION(mDetailedGlyphs != nsnull &&
+                     !mCharacterGlyphs[aCharIndex].IsSimpleGlyph() &&
+                     mCharacterGlyphs[aCharIndex].GetGlyphCount() > 0,
+                     "invalid use of GetDetailedGlyphs; check the caller!");
         return mDetailedGlyphs->Get(aCharIndex);
     }
+
     PRBool HasDetailedGlyphs() { return mDetailedGlyphs != nsnull; }
     PRUint32 CountMissingGlyphs();
     const GlyphRun *GetGlyphRuns(PRUint32 *aNumGlyphRuns) {
         *aNumGlyphRuns = mGlyphRuns.Length();
         return mGlyphRuns.Elements();
     }
     // Returns the index of the GlyphRun containing the given offset.
     // Returns mGlyphRuns.Length() when aOffset is mCharacterCount.
@@ -2077,16 +2083,21 @@ private:
 
         // This is optimized for the most common calling patterns:
         // we rarely need random access to the records, access is most commonly
         // sequential through the textRun, so we record the last-used index
         // and check whether the caller wants the same record again, or the
         // next; if not, it's most likely we're starting over from the start
         // of the run, so we check the first entry before resorting to binary
         // search as a last resort.
+        // NOTE that this must not be called for a character offset that does
+        // not have any DetailedGlyph records; callers must have verified that
+        // mCharacterGlyphs[aOffset].GetGlyphCount() is greater than zero
+        // before calling this, otherwise the assertions here will fire (in a
+        // debug build), and we'll probably crash.
         DetailedGlyph* Get(PRUint32 aOffset) {
             NS_ASSERTION(mOffsetToIndex.Length() > 0,
                          "no detailed glyph records!");
             DetailedGlyph* details = mDetails.Elements();
             // check common cases (fwd iteration, initial entry, etc) first
             if (mLastUsed < mOffsetToIndex.Length() - 1 &&
                 aOffset == mOffsetToIndex[mLastUsed + 1].mOffset) {
                 ++mLastUsed;
--- a/layout/generic/nsTextRunTransformations.cpp
+++ b/layout/generic/nsTextRunTransformations.cpp
@@ -171,17 +171,19 @@ MergeCharactersInTextRun(gfxTextRun* aDe
           details.mYOffset = 0;
           glyphs.AppendElement(details);
         }
       } else {
         if (g.IsMissing()) {
           anyMissing = PR_TRUE;
           glyphs.Clear();
         }
-        glyphs.AppendElements(aSrc->GetDetailedGlyphs(k), g.GetGlyphCount());
+        if (g.GetGlyphCount() > 0) {
+          glyphs.AppendElements(aSrc->GetDetailedGlyphs(k), g.GetGlyphCount());
+        }
       }
 
       // We could teach this method to handle merging of characters that aren't
       // cluster starts or ligature group starts, but this is really only used
       // to merge S's (uppercase &szlig;), so it's not worth it.
 
       if (k + 1 < iter.GetStringEnd() && aCharsToMerge[k + 1]) {
         NS_ASSERTION(g.IsClusterStart() && g.IsLigatureGroupStart(),