richedit: Prevent copying PARAFORMAT2 fields from PARAFORMAT struct.

Dylan Smith dylan.ah.smith at gmail.com
Thu Jan 15 22:07:15 CST 2009


If a EM_SETPARAFORMAT message is sent to the richedit control with bits
in the dwMask field that correspond to PARAFORMAT2 fields, then these
fields should be ignored.  Instead data was copied from outside of the
structure.

This bug affects native wordpad (version included with Windows XP at
least) when using builtin msftedit.dll (mfc42u.dll is also needed).  It
ended up having a very large value for dySpaceBefore, since it was
copied from outside of the structure.

This change prevents it from masking the given mask based on the cbSize
field, which prevents PARAFORMAT2 fields to be copied from a PARAFORMAT
structure.
---
 dlls/riched20/para.c |   77 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 46 insertions(+), 31 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index 23d17f4..a118d7d 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -126,56 +126,71 @@ static void ME_UpdateTableFlags(ME_DisplayItem *para)
 static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt)
 {
   PARAFORMAT2 copy;
-  assert(sizeof(*para->member.para.pFmt) == sizeof(PARAFORMAT2));
+  DWORD dwMask;
+
+  assert(para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
+  dwMask = pFmt->dwMask;
+  if (pFmt->cbSize < sizeof(PARAFORMAT))
+    return FALSE;
+  else if (pFmt->cbSize < sizeof(PARAFORMAT2))
+    dwMask &= PFM_ALL;
+  else
+    dwMask &= PFM_ALL2;
+
   ME_AddUndoItem(editor, diUndoSetParagraphFormat, para);
 
   copy = *para->member.para.pFmt;
 
 #define COPY_FIELD(m, f) \
-  if (pFmt->dwMask & (m)) {                     \
+  if (dwMask & (m)) {                           \
     para->member.para.pFmt->dwMask |= m;        \
     para->member.para.pFmt->f = pFmt->f;        \
   }
 
   COPY_FIELD(PFM_NUMBERING, wNumbering);
-#define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \
-                      PFM_NOLINENUMBER|PFM_NOWIDOWCONTROL|PFM_DONOTHYPHEN|PFM_SIDEBYSIDE| \
-                      PFM_TABLE)
-  /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */
-  if (pFmt->dwMask & EFFECTS_MASK) {
-    para->member.para.pFmt->dwMask |= pFmt->dwMask & EFFECTS_MASK;
-    para->member.para.pFmt->wEffects &= ~HIWORD(pFmt->dwMask);
-    para->member.para.pFmt->wEffects |= pFmt->wEffects & HIWORD(pFmt->dwMask);
-  }
-#undef EFFECTS_MASK
-
   COPY_FIELD(PFM_STARTINDENT, dxStartIndent);
-  if (pFmt->dwMask & PFM_OFFSETINDENT)
+  if (dwMask & PFM_OFFSETINDENT)
     para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent;
   COPY_FIELD(PFM_RIGHTINDENT, dxRightIndent);
   COPY_FIELD(PFM_OFFSET, dxOffset);
   COPY_FIELD(PFM_ALIGNMENT, wAlignment);
-
-  if (pFmt->dwMask & PFM_TABSTOPS)
+  if (dwMask & PFM_TABSTOPS)
   {
     para->member.para.pFmt->cTabCount = pFmt->cTabCount;
     memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG));
   }
-  COPY_FIELD(PFM_SPACEBEFORE, dySpaceBefore);
-  COPY_FIELD(PFM_SPACEAFTER, dySpaceAfter);
-  COPY_FIELD(PFM_LINESPACING, dyLineSpacing);
-  COPY_FIELD(PFM_STYLE, sStyle);
-  COPY_FIELD(PFM_LINESPACING, bLineSpacingRule);
-  COPY_FIELD(PFM_SHADING, wShadingWeight);
-  COPY_FIELD(PFM_SHADING, wShadingStyle);
-  COPY_FIELD(PFM_NUMBERINGSTART, wNumberingStart);
-  COPY_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle);
-  COPY_FIELD(PFM_NUMBERINGTAB, wNumberingTab);
-  COPY_FIELD(PFM_BORDER, wBorderSpace);
-  COPY_FIELD(PFM_BORDER, wBorderWidth);
-  COPY_FIELD(PFM_BORDER, wBorders);
-
-  para->member.para.pFmt->dwMask |= pFmt->dwMask;
+
+  if (dwMask & (PFM_ALL2 & ~PFM_ALL))
+  {
+    /* PARAFORMAT2 fields */
+
+#define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \
+                      PFM_NOLINENUMBER|PFM_NOWIDOWCONTROL|PFM_DONOTHYPHEN|PFM_SIDEBYSIDE| \
+                      PFM_TABLE)
+    /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */
+    if (dwMask & EFFECTS_MASK) {
+      para->member.para.pFmt->dwMask |= dwMask & EFFECTS_MASK;
+      para->member.para.pFmt->wEffects &= ~HIWORD(dwMask);
+      para->member.para.pFmt->wEffects |= pFmt->wEffects & HIWORD(dwMask);
+    }
+#undef EFFECTS_MASK
+
+    COPY_FIELD(PFM_SPACEBEFORE, dySpaceBefore);
+    COPY_FIELD(PFM_SPACEAFTER, dySpaceAfter);
+    COPY_FIELD(PFM_LINESPACING, dyLineSpacing);
+    COPY_FIELD(PFM_STYLE, sStyle);
+    COPY_FIELD(PFM_LINESPACING, bLineSpacingRule);
+    COPY_FIELD(PFM_SHADING, wShadingWeight);
+    COPY_FIELD(PFM_SHADING, wShadingStyle);
+    COPY_FIELD(PFM_NUMBERINGSTART, wNumberingStart);
+    COPY_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle);
+    COPY_FIELD(PFM_NUMBERINGTAB, wNumberingTab);
+    COPY_FIELD(PFM_BORDER, wBorderSpace);
+    COPY_FIELD(PFM_BORDER, wBorderWidth);
+    COPY_FIELD(PFM_BORDER, wBorders);
+  }
+
+  para->member.para.pFmt->dwMask |= dwMask;
 #undef COPY_FIELD
 
   if (memcmp(&copy, para->member.para.pFmt, sizeof(PARAFORMAT2)))


More information about the wine-patches mailing list