summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-08-24 17:31:24 +0200
committerCaolán McNamara <caolanm@redhat.com>2015-08-25 15:07:19 +0000
commitdb39370e91c68910daf1f5959f6494b4891e7ba2 (patch)
tree084df408d4168f2b661ae59771e67dbb23555127 /sw
parent3a0ca27411f37b86a56737d89349ac629863af00 (diff)
Handle non-aligned FFNs
...as found by UBSan in CppunitTest_sw_filters_test (see below), and at the same time limit reads within the pA array to its bounds. > Testing file:///.../sw/qa/core/data/ww6/pass/crash-2.doc: > sw/source/filter/ww8/ww8scan.cxx:6473:32: runtime error: upcast of misaligned address 0x6200000e70e7 for type 'WW8_FFN_Ver6', which requires 2 byte alignment > 0x6200000e70e7: note: pointer points here > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0e 00 00 6a 00 00 00 00 0e 00 00 6a 00 00 00 6a > ^ > WW8Fonts::WW8Fonts(SvStream&, WW8Fib&) sw/source/filter/ww8/ww8scan.cxx:6473:32 > SwWW8ImplReader::CoreLoad(WW8Glossary*, SwPosition const&) sw/source/filter/ww8/ww8par.cxx:4961:20 > SwWW8ImplReader::LoadThroughDecryption(SwPaM&, WW8Glossary*) sw/source/filter/ww8/ww8par.cxx:5767:19 > SwWW8ImplReader::LoadDoc(SwPaM&, WW8Glossary*) sw/source/filter/ww8/ww8par.cxx:6039:19 > WW8Reader::Read(SwDoc&, rtl::OUString const&, SwPaM&, rtl::OUString const&) sw/source/filter/ww8/ww8par.cxx:6157:20 > SwReader::Read(Reader const&) sw/source/filter/basflt/shellio.cxx:175:18 > SwDocShell::ConvertFrom(SfxMedium&) sw/source/uibase/app/docsh.cxx:258:22 > SfxObjectShell::DoLoad(SfxMedium*) sfx2/source/doc/objstor.cxx:790:23 > SwFiltersTest::filter(rtl::OUString const&, rtl::OUString const&, rtl::OUString const&, SfxFilterFlags, SotClipboardFormatId, unsigned int, bool) sw/qa/core/filters-test.cxx:112:20 > SwFiltersTest::load(rtl::OUString const&, rtl::OUString const&, rtl::OUString const&, SfxFilterFlags, SotClipboardFormatId, unsigned int) sw/qa/core/filters-test.cxx:71:12 > test::FiltersTest::recursiveScan(test::filterStatus, rtl::OUString const&, rtl::OUString const&, rtl::OUString const&, SfxFilterFlags, SotClipboardFormatId, unsigned int, bool) unotest/source/cpp/filters-test.cxx:129:20 > test::FiltersTest::testDir(rtl::OUString const&, rtl::OUString const&, rtl::OUString const&, SfxFilterFlags, SotClipboardFormatId, unsigned int, bool) unotest/source/cpp/filters-test.cxx:154:5 > SwFiltersTest::testCVEs() sw/qa/core/filters-test.cxx:154:5 (cherry picked from commit 6373886870503a981b65f204f9113aebff540ab8) Change-Id: I31ac8dc11d985745785c9dda1cec8a11a41098bb Reviewed-on: https://gerrit.libreoffice.org/17985 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/source/filter/ww8/ww8scan.cxx147
1 files changed, 123 insertions, 24 deletions
diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
index 1f7f52626189..47cdde944baa 100644
--- a/sw/source/filter/ww8/ww8scan.cxx
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -20,10 +20,12 @@
#include "ww8scan.hxx"
#include "ww8par.hxx"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
#include <functional>
#include <algorithm>
-#include <string.h>
#include <i18nlangtag/mslangid.hxx>
#include <sprmids.hxx>
#include <rtl/tencinfo.h>
@@ -6357,10 +6359,15 @@ WW8_STD* WW8Style::Read1Style( short& rSkip, OUString* pString, short* pcbStd )
return pStd;
}
-struct WW8_FFN_Ver6 : public WW8_FFN_BASE
+namespace {
+const sal_uInt16 maxStrSize = 65;
+}
+
+struct WW8_FFN_Ver6
{
- // ab Ver6
- sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
+ WW8_FFN_BASE base;
+ // from Ver6
+ sal_Char szFfn[maxStrSize]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
// records name of font.
// Maximal size of szFfn is 65 characters.
// Vorsicht: Dieses Array kann auch kleiner sein!!!
@@ -6439,6 +6446,50 @@ namespace
}
return nMax;
}
+
+ template<typename T> bool readU8(
+ sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd,
+ T * value)
+ {
+ assert(p <= pEnd);
+ assert(value != nullptr);
+ if (offset >= static_cast<std::size_t>(pEnd - p)) {
+ return false;
+ }
+ *value = p[offset];
+ return true;
+ }
+
+ bool readS16(
+ sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd,
+ short * value)
+ {
+ assert(p <= pEnd);
+ assert(value != nullptr);
+ if (offset > static_cast<std::size_t>(pEnd - p)
+ || static_cast<std::size_t>(pEnd - p) - offset < 2)
+ {
+ return false;
+ }
+ *value = unsigned(p[offset]) + (unsigned(p[offset + 1]) << 8);
+ return true;
+ }
+
+ sal_Int32 getStringLength(
+ sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd)
+ {
+ assert(p <= pEnd);
+ assert(pEnd - p <= SAL_MAX_INT32);
+ if (offset >= static_cast<std::size_t>(pEnd - p)) {
+ return -1;
+ }
+ void const * p2 = std::memchr(
+ p + offset, 0, static_cast<std::size_t>(pEnd - p) - offset);
+ if (p2 == nullptr) {
+ return -1;
+ }
+ return static_cast<sal_uInt8 const *>(p2) - (p + offset);
+ }
}
WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
@@ -6476,6 +6527,7 @@ WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
// read all font information
nFFn = rSt.Read(pA, nFFn);
+ sal_uInt8 * const pEnd = pA + nFFn;
const sal_uInt16 nCalcMax = calcMaxFonts(pA, nFFn);
if (eVersion < ww::eWW8)
@@ -6495,17 +6547,26 @@ WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
if( eVersion <= ww::eWW2 )
{
- WW8_FFN_BASE* pVer2 = reinterpret_cast<WW8_FFN_BASE*>(pA);
- for(sal_uInt16 i=0; i<nMax; ++i, ++p)
+ sal_uInt8 const * pVer2 = pA;
+ sal_uInt16 i = 0;
+ for(; i<nMax; ++i, ++p)
{
- p->cbFfnM1 = pVer2->cbFfnM1;
+ if (!readU8(
+ pVer2, offsetof(WW8_FFN_BASE, cbFfnM1), pEnd,
+ &p->cbFfnM1))
+ {
+ break;
+ }
p->prg = 0;
p->fTrueType = 0;
p->ff = 0;
- p->wWeight = ( *(reinterpret_cast<sal_uInt8*>(pVer2) + 1) );
- p->chs = ( *(reinterpret_cast<sal_uInt8*>(pVer2) + 2) );
+ if (!(readU8(pVer2, 1, pEnd, &p->wWeight)
+ && readU8(pVer2, 2, pEnd, &p->chs)))
+ {
+ break;
+ }
/*
#i8726# 7- seems to encode the name in the same encoding as
the font, e.g load the doc in 97 and save to see the unicode
@@ -6515,27 +6576,49 @@ WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
eEnc = RTL_TEXTENCODING_MS_1252;
- p->sFontname = OUString ( (reinterpret_cast<char*>(pVer2) + 1 + 2), strlen((reinterpret_cast<char*>(pVer2) + 1 + 2)), eEnc);
- pVer2 = reinterpret_cast<WW8_FFN_BASE*>( reinterpret_cast<sal_uInt8*>(pVer2) + pVer2->cbFfnM1 + 1 );
+ sal_Int32 n = getStringLength(pVer2, 1 + 2, pEnd);
+ if (n == -1) {
+ break;
+ }
+ p->sFontname = OUString(
+ reinterpret_cast<char const *>(pVer2 + 1 + 2), n, eEnc);
+ pVer2 = pVer2 + p->cbFfnM1 + 1;
}
+ nMax = i;
}
else if( eVersion < ww::eWW8 )
{
- WW8_FFN_Ver6* pVer6 = reinterpret_cast<WW8_FFN_Ver6*>(pA);
- sal_uInt8 c2;
- for(sal_uInt16 i=0; i<nMax; ++i, ++p)
+ sal_uInt8 const * pVer6 = pA;
+ sal_uInt16 i = 0;
+ for(; i<nMax; ++i, ++p)
{
- p->cbFfnM1 = pVer6->cbFfnM1;
- c2 = *(reinterpret_cast<sal_uInt8*>(pVer6) + 1);
+ if (!readU8(
+ pVer6, offsetof(WW8_FFN_BASE, cbFfnM1), pEnd,
+ &p->cbFfnM1))
+ {
+ break;
+ }
+ sal_uInt8 c2;
+ if (!readU8(pVer6, 1, pEnd, &c2)) {
+ break;
+ }
p->prg = c2 & 0x02;
p->fTrueType = (c2 & 0x04) >> 2;
// ein Reserve-Bit ueberspringen
p->ff = (c2 & 0x70) >> 4;
- p->wWeight = SVBT16ToShort( *reinterpret_cast<SVBT16*>(&pVer6->wWeight) );
- p->chs = pVer6->chs;
- p->ibszAlt = pVer6->ibszAlt;
+ if (!(readS16(
+ pVer6, offsetof(WW8_FFN_BASE, wWeight), pEnd,
+ &p->wWeight)
+ && readU8(
+ pVer6, offsetof(WW8_FFN_BASE, chs), pEnd, &p->chs)
+ && readU8(
+ pVer6, offsetof(WW8_FFN_BASE, ibszAlt), pEnd,
+ &p->ibszAlt)))
+ {
+ break;
+ }
/*
#i8726# 7- seems to encode the name in the same encoding as
the font, e.g load the doc in 97 and save to see the unicode
@@ -6544,12 +6627,27 @@ WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs, rFib.lid);
if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
eEnc = RTL_TEXTENCODING_MS_1252;
- p->sFontname = OUString(pVer6->szFfn, rtl_str_getLength(pVer6->szFfn), eEnc);
- const sal_uInt16 maxStrSize = sizeof (pVer6->szFfn) / sizeof (pVer6->szFfn[0]);
+ sal_Int32 n = getStringLength(
+ pVer6, offsetof(WW8_FFN_Ver6, szFfn), pEnd);
+ if (n == -1) {
+ break;
+ }
+ p->sFontname = OUString(
+ reinterpret_cast<char const *>(
+ pVer6 + offsetof(WW8_FFN_Ver6, szFfn)),
+ n, eEnc);
if (p->ibszAlt && p->ibszAlt < maxStrSize) //don't start after end of string
{
- const sal_Char *pAlt = pVer6->szFfn+p->ibszAlt;
- p->sFontname += ";" + OUString(pAlt, rtl_str_getLength(pAlt), eEnc);
+ n = getStringLength(
+ pVer6, offsetof(WW8_FFN_Ver6, szFfn) + p->ibszAlt,
+ pEnd);
+ if (n == -1) {
+ break;
+ }
+ p->sFontname += ";" + OUString(
+ reinterpret_cast<char const *>(
+ pVer6 + offsetof(WW8_FFN_Ver6, szFfn) + p->ibszAlt),
+ n, eEnc);
}
else
{
@@ -6562,8 +6660,9 @@ WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
p->sFontname += ";Symbol";
}
}
- pVer6 = reinterpret_cast<WW8_FFN_Ver6*>( reinterpret_cast<sal_uInt8*>(pVer6) + pVer6->cbFfnM1 + 1 );
+ pVer6 = pVer6 + p->cbFfnM1 + 1;
}
+ nMax = i;
}
else
{