Hi Peter
In my view bugfixes are always a top priority (only second to fixing regressions). Please do cherry pick it to trunk and then to 41X All the best, Pedro > On 06/15/2026 10:40 PM WEST [email protected] wrote: > > > Hi all, > > During debugging calc for missing parts of my migration, i came across > a bug in the code. > I separated the documentation from the code commit. Maybe it is worth > cherry picking it for trunk? > > Here is the relevant part: > > ## 14. Calc crash-on-open AV — latent UAF, debug-CRT-deterministic (NOT > a migration bug) > **Component:**`sc`view init — **stock AOO defect**, source > byte-identical to upstream. > **Root cause (CONFIRMED):**`ScViewData::ReadUserDataSequence` > ([viewdata.cxx:2821](main/sc/source/ui/view/viewdata.cxx#L2821)) does > `delete pTabData[nTab]; pTabData[nTab] = new ScViewDataTable;`per sheet > but **never > refreshes `pThisTab`** (which pointed at `pTabData[nTabNo]`). Back in > `ScTabView::SetTabNo`, line 1660 reads `aViewData.GetActivePart()`→ > `pThisTab->eWhichActive` > **before**line 1663 fixes `pThisTab`→ use-after-free → AV > `sc!ScTabView::SetTabNo``mov ecx,[eax+edx*4+0x664]`with **edx=0xDDDDDDDD** > (`pGridWin[0xdddddddd]`). > **Why it shows here but not in normal use — and why "release is fine" is > too strong.** > This is a genuine latent **UAF**(reading a dangling pointer is UB); it > is *masked*in > release by **unspecified allocator behaviour**, not made correct. The > `delete`and `new` > are same-thread, adjacent, same size class, with nothing between them (the > `ScViewDataTable`ctor runs *after*`operator new`). Mainstream allocators > keep per-size > free lists with MRU/LIFO reuse, so `new`almost always returns the > **just-freed block**— > and when it does, `pThisTab == pTabData[nTabNo]`again and points at the > *live, freshly > constructed* object (genuinely correct, not stale-luck). That is why it > has survived ~20 > years in the field. > But it is **not guaranteed**, and can surface non-deterministically even > in release: > -Windows **LFH randomizes**allocation slots (Win8+ exploit mitigation), > so `new`may > return a *different*slot. In release the freed block isn't poisoned, > so the immediate > read usually still sees plausible old bytes — but the window here is > **not**two > instructions: the rest of `ReadUserDataSequence`parses *all other > sheets*(lots of > allocation), any of which can reclaim that block and overwrite the > `eWhichActive`offset > with a large value → `pGridWin[garbage]`→ a **rare, timing-dependent > release crash**. > -Hardened/diagnostic allocators (PageHeap, Application Verifier, ASan, a > custom > `operator new`) don't do MRU reuse at all → they crash release too. > -The debug CRT (`MSVCR90D`) is just the *deterministic*trigger: it > poison-fills freed > blocks with `0xDD`and **delays**reuse, so `new`returns a different > block every time. > cdb proof (`.frame 0; dv /t`+ `?? &this->aViewData`): `eOldActive = > 0xDDDDDDDD`, but > `this`/`pDoc`/`pViewShell`all valid, and crucially > `pThisTab = 0x09a5f118`(old/low region, freed) **≠**`pTabData[nTabNo=0] > = 0x13deca08` > (fresh/valid) — the new table object is fine; only the stale pointer > dangles. > it's a latent UAF whose release manifestation is rare and > non-deterministic (the worst kind: invisible in testing, occasionally > lethal in the field), > so the 1-line upstream fix is warranted: `pThisTab = > pTabData[nTabNo];`at the end of > `ReadUserDataSequence`([viewdata.cxx:2955-2960](main/sc/source/ui/view/viewdata.cxx#L2955)), > mirroring `ScViewData::SetTabNo`line 1502 — it removes the dependence on > allocator luck > entirely. **Triage rule:**a debug-build `0xDD`/`0xFEEE`AV is a > *migration*bug only if an > upstream *failure*feeds it (a throw, a missing staged file/data, as in > §1); if every object > is valid and only one pointer dangles across a `delete`/`new`, it's a > debug-CRT-exposed > latent UAF. Reproducing in release tells you whether the allocator is > masking it — a *clean* > release run is **not**proof of correctness, only that MRU reuse held > that time. > all the best > peter --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
