https://bugs.documentfoundation.org/show_bug.cgi?id=173267

            Bug ID: 173267
           Summary: Crash when opening a PPTX containing a table whose
                    a:tableStyleId GUID is not a predefined table style
                    and is not defined in ppt/tableStyles.xml (Impress,
                    oox import, NULL dereference)
           Product: LibreOffice
           Version: 27.2.0.0 alpha0+ master
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: Base
          Assignee: [email protected]
          Reporter: [email protected]

Description:
Dear LibreOffice-Team,

A PPTX table whose `a:tableStyleId` is neither defined in the presentation's
own `ppt/tableStyles.xml` nor one of the 74 predefined style GUIDs crashes the
Impress import with a NULL dereference.
One wrong hex digit in an otherwise valid style id is enough, and the id does
not have to come from a mutation.

This bug was found with a new fuzzing approach via the `libreoffice` oss-fuzz
target `pptxfuzzer` using the `core` master branch at commit
`50ae505eb3ef23a3ff4a52a62d41a6f0fa6683ab`, built by OSS-Fuzz with ASan.

`CreateTableStyle` looks the style id up in `mStyleIdMap` and dereferences the
iterator without comparing it against `end()`,
`oox/source/drawingml/table/predefined-table-styles.cxx`:

```c++
427         auto it = mStyleIdMap.find(styleId);
428         OUString style_name = it->second.first;
429         OUString accent_name = it->second.second;
```

`mStyleIdMap` is a fixed table of the 74 GUIDs PowerPoint ships (declared at
line 37), and `styleId` comes straight out of the document.
When the id is unknown, `it` is `end()` and the `OUString` copy constructor
faults:

```
==42==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018
==42==The signal is caused by a READ memory access.
==42==Hint: address points to the zero page.
SCARINESS: 10 (null-deref)
    #0 in OUString include/rtl/ustring.hxx:199:21
    #1 in CreateTableStyle(rtl::OUString const&)
oox/source/drawingml/table/predefined-table-styles.cxx:428:27
    #2 in oox::drawingml::table::TableProperties::getUsedTableStyle(...)
oox/source/drawingml/table/tableproperties.cxx:112:35
    #3 in oox::drawingml::table::TableProperties::pushToPropSet(...)
oox/source/drawingml/table/tableproperties.cxx:137:35
    #4 in oox::drawingml::Shape::createAndInsert(...)
oox/source/drawingml/shape.cxx:1679:35
    #5 in oox::ppt::PPTShape::addShape(...) oox/source/ppt/pptshape.cxx:529:41
    #6 in oox::ppt::SlidePersist::createXShapes(...)
oox/source/ppt/slidepersist.cxx:201:28
```

The caller reaches it by design for exactly the case the document controls,
`oox/source/drawingml/table/tableproperties.cxx`:

```c++
109             //if the pptx just has table style id, but no table style
content, we will create the table style ourselves
110             if (!pTableStyle)
111             {
112                 rTableStyleToDelete = CreateTableStyle(aStyleId);
113                 pTableStyle = rTableStyleToDelete.get();
114             }
```

Line 427 is the first unchecked dereference, not the only one.
There are eleven more `mStyleIdMap.find(styleId)->second` dereferences at lines
460, 525, 576, 611, 648, 685, 733, 773, 800, 843 and 886, all of them inside
branches that are only entered after line 428 has set `style_name`.

The attached `minimal_unknown_tablestyleid.pptx` is a hand-built presentation
holding one single-cell table whose style id is
`{4C22544A-7EE6-4342-B048-85BDC9FD1C3A}`.
`control_known_tablestyleid.pptx` is the same presentation with
`{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}`, the real id of Medium-Style-2
Accent1.
The two presentations differ in exactly one byte of `ppt/slides/slide1.xml`,
the `4` against the `5`, and in no other part, and every part of both is
well-formed XML.

The fuzzer found it the same way, by flipping the leading hex digit of a style
id the seed already carried, in
`crash-1f341145db0fd98ad457589eb964c97f7472d5d6`.
That testcase still defines `{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}` in its
`ppt/tableStyles.xml` while its slide asks for
`{4C22544A-7EE6-4342-B048-85BDC9FD1C3A}`, so the search at line 101 finds
nothing and line 112 is reached.
`unzip -t` reports a bad CRC-32 on eleven of its thirty-five parts, because the
fuzzer rewrote them in place without fixing the checksums, so the hand-built
presentations are the artifacts to reproduce from.

Reaching `CreateTableStyle` needs the presentation to have a
`ppt/tableStyles.xml` part, since `getUsedTableStyle` only takes this path when
`rBase.getTableStyles()` is non-null (`tableproperties.cxx:96`), so both
attached presentations carry an empty `a:tblStyleLst`.

The same fuzz target produced a second, unrelated defect in the comment import,
reported separately as bug 164.

## Fix

We are not shipping a patch, but the suggested fix is to refuse an id the table
does not know, before any of the twelve dereferences:

```diff
 std::unique_ptr<TableStyle> CreateTableStyle(const OUString& styleId)
 {
+    // The style id comes straight from the document and need not be one of
the
+    // predefined ones; every mStyleIdMap.find(styleId) below assumes it is.
+    if (mStyleIdMap.find(styleId) == mStyleIdMap.end())
+        return nullptr;
+
     std::unique_ptr<TableStyle> pTableStyle;
```

Returning nothing needs no new handling at the call site: `getUsedTableStyle`
already tests `pTableStyle` right after the call and falls back to
`theDefaultTableStyle`, `tableproperties.cxx:117-121`.
That is the only call site of `CreateTableStyle` in the tree.

## Reproduce

The original fuzzer testcase, its CASR report and the two hand-built
presentations are attached.

```bash
export DOCKER_DEFAULT_PLATFORM=linux/amd64 # if on mac
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
python3 infra/helper.py build_image libreoffice
python3 infra/helper.py build_fuzzers --sanitizer address libreoffice
python3 infra/helper.py reproduce libreoffice pptxfuzzer
crash-1f341145db0fd98ad457589eb964c97f7472d5d6
python3 infra/helper.py reproduce libreoffice pptxfuzzer
minimal_unknown_tablestyleid.pptx
python3 infra/helper.py reproduce libreoffice pptxfuzzer
control_known_tablestyleid.pptx
```

We tested against OSS-Fuzz at commit
`a4df12d70b5420567d893b3f53e5818a74df5db7`, default `linux/amd64` containers,
and `core` master at commit `50ae505eb3ef23a3ff4a52a62d41a6f0fa6683ab`.

Found by the CISPA Fandango-Team while triaging OSS-Fuzz findings for
libreoffice.


Steps to Reproduce:
<-- Download and unzip the Reproduce.zip -->

export DOCKER_DEFAULT_PLATFORM=linux/amd64 # if on mac
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
python3 infra/helper.py build_image libreoffice
python3 infra/helper.py build_fuzzers --sanitizer address libreoffice
python3 infra/helper.py reproduce libreoffice pptxfuzzer
crash-1f341145db0fd98ad457589eb964c97f7472d5d6
python3 infra/helper.py reproduce libreoffice pptxfuzzer
minimal_unknown_tablestyleid.pptx
python3 infra/helper.py reproduce libreoffice pptxfuzzer
control_known_tablestyleid.pptx


Actual Results:
==42==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018
==42==The signal is caused by a READ memory access.
==42==Hint: address points to the zero page.
SCARINESS: 10 (null-deref)
    #0 in OUString include/rtl/ustring.hxx:199:21
    #1 in CreateTableStyle(rtl::OUString const&)
oox/source/drawingml/table/predefined-table-styles.cxx:428:27
    #2 in oox::drawingml::table::TableProperties::getUsedTableStyle(...)
oox/source/drawingml/table/tableproperties.cxx:112:35
    #3 in oox::drawingml::table::TableProperties::pushToPropSet(...)
oox/source/drawingml/table/tableproperties.cxx:137:35
    #4 in oox::drawingml::Shape::createAndInsert(...)
oox/source/drawingml/shape.cxx:1679:35
    #5 in oox::ppt::PPTShape::addShape(...) oox/source/ppt/pptshape.cxx:529:41
    #6 in oox::ppt::SlidePersist::createXShapes(...)
oox/source/ppt/slidepersist.cxx:201:28


Expected Results:
No crash


Reproducible: Always


User Profile Reset: No

Additional Info:
This bug was found with a new fuzzing approach via the `libreoffice` oss-fuzz
target `pptxfuzzer` using the `core` master branch at commit
`50ae505eb3ef23a3ff4a52a62d41a6f0fa6683ab`, built by OSS-Fuzz with ASan.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to