summaryrefslogtreecommitdiff
path: root/xfa/fxfa/app/cxfa_textlayout.cpp
diff options
context:
space:
mode:
authortsepez <tsepez@chromium.org>2017-01-17 11:05:57 -0800
committerCommit bot <commit-bot@chromium.org>2017-01-17 11:05:57 -0800
commit783a7e048c677d26aaf3884304627bbe27cff546 (patch)
treeb03feaa32114472f54855c1b702e5bfda28d2be1 /xfa/fxfa/app/cxfa_textlayout.cpp
parentb9fbe6e9af590a91ab030d2523a147e972816b32 (diff)
downloadpdfium-783a7e048c677d26aaf3884304627bbe27cff546.tar.xz
Avoid endless loop deleting CFGAS_GEFont.
It's a ref-counted class, so if we're in the destructor, the ref count has hit zero. We can't make a new ref pointer to itself here, as it will re-invoke the destructor when it goes out of scope. This should have been an obvious anti-pattern in hindsight. The object in question can't be in the m_pFontManager, since the font manager retains a reference, and we wouldn't get to this destructor while that is present. So the cleanup isn't required. Fixing this revealed a free-delete mismatch in cxfa_textlayout.cpp. I also converted to use unique_ptrs in a few places near this issue. Fixing this revealed a UAF in CFGAS_GEFont, memcpy'ing a RetainPtr is not a good idea as it doesn't bump the ref count. Also protect and friend the CFGAS_GEFont destructor, to make sure random deletes don't happen. Also kill off a const cast, and remove unnecessary conversion to retain_ptr when we already have one. TEST=look for absence of -11 in XFA corpus test logs, bots not currently noticing the segv. Argh. Review-Url: https://codereview.chromium.org/2631703003
Diffstat (limited to 'xfa/fxfa/app/cxfa_textlayout.cpp')
-rw-r--r--xfa/fxfa/app/cxfa_textlayout.cpp107
1 files changed, 41 insertions, 66 deletions
diff --git a/xfa/fxfa/app/cxfa_textlayout.cpp b/xfa/fxfa/app/cxfa_textlayout.cpp
index 3f3058bf4e..d831b600dc 100644
--- a/xfa/fxfa/app/cxfa_textlayout.cpp
+++ b/xfa/fxfa/app/cxfa_textlayout.cpp
@@ -7,6 +7,7 @@
#include "xfa/fxfa/app/cxfa_textlayout.h"
#include <algorithm>
+#include <utility>
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
@@ -46,28 +47,10 @@ CXFA_TextLayout::~CXFA_TextLayout() {
}
void CXFA_TextLayout::Unload() {
- for (int32_t i = 0; i < m_pieceLines.GetSize(); i++) {
- CXFA_PieceLine* pLine = m_pieceLines.GetAt(i);
- for (int32_t i = 0; i < pLine->m_textPieces.GetSize(); i++) {
- XFA_TextPiece* pPiece = pLine->m_textPieces.GetAt(i);
- // Release text and widths in a text piece.
- delete pPiece->pszText;
- delete pPiece->pWidths;
- // Release text piece.
- delete pPiece;
- }
- pLine->m_textPieces.RemoveAll();
- // Release line.
- delete pLine;
- }
- m_pieceLines.RemoveAll();
+ m_pieceLines.clear();
m_pBreak.reset();
}
-const CFX_ArrayTemplate<CXFA_PieceLine*>* CXFA_TextLayout::GetPieceLines() {
- return &m_pieceLines;
-}
-
void CXFA_TextLayout::GetTextDataNode() {
if (!m_pTextProvider)
return;
@@ -586,7 +569,7 @@ bool CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice,
auto pSolidBrush = pdfium::MakeUnique<CFDE_Brush>();
auto pPen = pdfium::MakeUnique<CFDE_Pen>();
- if (m_pieceLines.GetSize() == 0) {
+ if (m_pieceLines.empty()) {
int32_t iBlockCount = CountBlocks();
for (int32_t i = 0; i < iBlockCount; i++)
Layout(i);
@@ -595,7 +578,7 @@ bool CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice,
FXTEXT_CHARPOS* pCharPos = nullptr;
int32_t iCharCount = 0;
int32_t iLineStart = 0;
- int32_t iPieceLines = m_pieceLines.GetSize();
+ int32_t iPieceLines = pdfium::CollectionSize<int32_t>(m_pieceLines);
int32_t iCount = m_Blocks.GetSize();
if (iCount > 0) {
iBlock *= 2;
@@ -608,14 +591,14 @@ bool CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice,
}
for (int32_t i = 0; i < iPieceLines; i++) {
- if (i + iLineStart >= m_pieceLines.GetSize())
+ if (i + iLineStart >= pdfium::CollectionSize<int32_t>(m_pieceLines))
break;
- CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i + iLineStart);
- int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+ CXFA_PieceLine* pPieceLine = m_pieceLines[i + iLineStart].get();
+ int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces);
int32_t j = 0;
for (j = 0; j < iPieces; j++) {
- const XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j);
+ const XFA_TextPiece* pPiece = pPieceLine->m_textPieces[j].get();
int32_t iChars = pPiece->iChars;
if (iCharCount < iChars) {
FX_Free(pCharPos);
@@ -651,15 +634,9 @@ void CXFA_TextLayout::UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom) {
return;
}
- int32_t iCount = m_pieceLines.GetSize();
- for (int32_t i = 0; i < iCount; i++) {
- CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i);
- int32_t iPieces = pPieceLine->m_textPieces.GetSize();
- for (int32_t j = 0; j < iPieces; j++) {
- XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j);
- CFX_RectF& rect = pPiece->rtPiece;
- rect.top += fHeight;
- }
+ for (const auto& pPieceLine : m_pieceLines) {
+ for (const auto& pPiece : pPieceLine->m_textPieces)
+ pPiece->rtPiece.top += fHeight;
}
}
@@ -1004,11 +981,11 @@ void CXFA_TextLayout::DoTabstops(CFDE_CSSComputedStyle* pStyle,
if (!pStyle || !pPieceLine)
return;
- int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+ int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces);
if (iPieces == 0)
return;
- XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1);
+ XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPieces - 1].get();
int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex;
int32_t iCount = m_textParser.CountTabs(pStyle);
if (iTabstopsIndex > m_pTabstopContext->m_iTabCount - 1)
@@ -1019,7 +996,7 @@ void CXFA_TextLayout::DoTabstops(CFDE_CSSComputedStyle* pStyle,
m_pTabstopContext->m_bTabstops = true;
FX_FLOAT fRight = 0;
if (iPieces > 1) {
- XFA_TextPiece* p = pPieceLine->m_textPieces.GetAt(iPieces - 2);
+ XFA_TextPiece* p = pPieceLine->m_textPieces[iPieces - 2].get();
fRight = p->rtPiece.right();
}
m_pTabstopContext->m_fTabWidth =
@@ -1063,8 +1040,9 @@ void CXFA_TextLayout::AppendTextLine(uint32_t dwStatus,
CFDE_CSSComputedStyle* pStyle = nullptr;
if (bSavePieces) {
- CXFA_PieceLine* pPieceLine = new CXFA_PieceLine;
- m_pieceLines.Add(pPieceLine);
+ auto pNew = pdfium::MakeUnique<CXFA_PieceLine>();
+ CXFA_PieceLine* pPieceLine = pNew.get();
+ m_pieceLines.push_back(std::move(pNew));
if (m_pTabstopContext)
m_pTabstopContext->Reset();
@@ -1077,11 +1055,9 @@ void CXFA_TextLayout::AppendTextLine(uint32_t dwStatus,
pStyle = pUserData->m_pStyle;
FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f;
- XFA_TextPiece* pTP = new XFA_TextPiece();
- pTP->pszText =
- (FX_WCHAR*)FX_Alloc(uint8_t, pPiece->m_iChars * sizeof(FX_WCHAR));
- pTP->pWidths =
- (int32_t*)FX_Alloc(uint8_t, pPiece->m_iChars * sizeof(int32_t));
+ auto pTP = pdfium::MakeUnique<XFA_TextPiece>();
+ pTP->pszText = FX_Alloc(FX_WCHAR, pPiece->m_iChars);
+ pTP->pWidths = FX_Alloc(int32_t, pPiece->m_iChars);
pTP->iChars = pPiece->m_iChars;
pPiece->GetString(pTP->pszText);
pPiece->GetWidths(pTP->pWidths);
@@ -1100,7 +1076,6 @@ void CXFA_TextLayout::AppendTextLine(uint32_t dwStatus,
FX_FLOAT fBaseLineTemp =
m_textParser.GetBaseline(m_pTextProvider, pStyle);
pTP->rtPiece.top = fBaseLineTemp;
- pPieceLine->m_textPieces.Add(pTP);
FX_FLOAT fLineHeight = m_textParser.GetLineHeight(
m_pTextProvider, pStyle, m_iLines == 0, fVerScale);
@@ -1120,10 +1095,10 @@ void CXFA_TextLayout::AppendTextLine(uint32_t dwStatus,
} else {
pTP->pLinkData = nullptr;
}
+ pPieceLine->m_textPieces.push_back(std::move(pTP));
DoTabstops(pStyle, pPieceLine);
}
- for (i = 0; i < iPieces; i++) {
- XFA_TextPiece* pTP = pPieceLine->m_textPieces.GetAt(i);
+ for (const auto& pTP : pPieceLine->m_textPieces) {
FX_FLOAT& fTop = pTP->rtPiece.top;
FX_FLOAT fBaseLineTemp = fTop;
fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp;
@@ -1206,7 +1181,7 @@ void CXFA_TextLayout::RenderString(CFDE_RenderDevice* pDevice,
int32_t iPiece,
FXTEXT_CHARPOS* pCharPos,
const CFX_Matrix& tmDoc2Device) {
- const XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+ const XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get();
int32_t iCount = GetDisplayPos(pPiece, pCharPos);
if (iCount > 0) {
pBrush->SetColor(pPiece->dwColor);
@@ -1222,7 +1197,7 @@ void CXFA_TextLayout::RenderPath(CFDE_RenderDevice* pDevice,
int32_t iPiece,
FXTEXT_CHARPOS* pCharPos,
const CFX_Matrix& tmDoc2Device) {
- XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+ XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get();
bool bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2;
bool bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2;
if (bNoUnderline && bNoLineThrough)
@@ -1282,7 +1257,7 @@ void CXFA_TextLayout::RenderPath(CFDE_RenderDevice* pDevice,
return;
iCharsTmp = 0;
- int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+ int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces);
while (iPieceNext < iPieces - 1) {
iPieceNext++;
iCharsTmp = pPieceLine->m_charCounts.GetAt(iPieceNext);
@@ -1294,14 +1269,14 @@ void CXFA_TextLayout::RenderPath(CFDE_RenderDevice* pDevice,
FX_FLOAT fOrgX = 0.0f;
FX_FLOAT fEndX = 0.0f;
- pPiece = pPieceLine->m_textPieces.GetAt(iPiecePrev);
+ pPiece = pPieceLine->m_textPieces[iPiecePrev].get();
iChars = GetDisplayPos(pPiece, pCharPos);
if (iChars < 1)
return;
fOrgX = pCharPos[iChars - 1].m_OriginX +
pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
- pPiece = pPieceLine->m_textPieces.GetAt(iPieceNext);
+ pPiece = pPieceLine->m_textPieces[iPieceNext].get();
iChars = GetDisplayPos(pPiece, pCharPos);
if (iChars < 1)
return;
@@ -1332,27 +1307,27 @@ int32_t CXFA_TextLayout::GetDisplayPos(const XFA_TextPiece* pPiece,
return 0;
FX_RTFTEXTOBJ tr;
- if (!ToRun(pPiece, tr))
+ if (!ToRun(pPiece, &tr))
return 0;
return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode);
}
-bool CXFA_TextLayout::ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ& tr) {
+bool CXFA_TextLayout::ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ* tr) {
int32_t iLength = pPiece->iChars;
if (iLength < 1)
return false;
- tr.pStr = pPiece->pszText;
- tr.pFont = pPiece->pFont;
- tr.pRect = &pPiece->rtPiece;
- tr.pWidths = pPiece->pWidths;
- tr.iLength = iLength;
- tr.fFontSize = pPiece->fFontSize;
- tr.iBidiLevel = pPiece->iBidiLevel;
- tr.iCharRotation = 0;
- tr.wLineBreakChar = L'\n';
- tr.iVerticalScale = pPiece->iVerScale;
- tr.dwLayoutStyles = FX_RTFLAYOUTSTYLE_ExpandTab;
- tr.iHorizontalScale = pPiece->iHorScale;
+ tr->pStr = pPiece->pszText;
+ tr->pFont = pPiece->pFont;
+ tr->pRect = &pPiece->rtPiece;
+ tr->pWidths = pPiece->pWidths;
+ tr->iLength = iLength;
+ tr->fFontSize = pPiece->fFontSize;
+ tr->iBidiLevel = pPiece->iBidiLevel;
+ tr->iCharRotation = 0;
+ tr->wLineBreakChar = L'\n';
+ tr->iVerticalScale = pPiece->iVerScale;
+ tr->dwLayoutStyles = FX_RTFLAYOUTSTYLE_ExpandTab;
+ tr->iHorizontalScale = pPiece->iHorScale;
return true;
}