← All issues

[18] Navigation API null-deref via reload() in pageswap handler

Severity: Medium | Component: WebCore Navigation API | 8e3ad95

Rated Medium because the diff fixes a renderer-reachable null deref via re-entrant navigation.reload() inside a pageswap handler. Pre-fix, the nested reload cleared the provisional DocumentLoader that HistoryController::updateForCommit() was about to dereference.

Source/WebCore/page/Navigation.cpp

- if (!protect(window->document())->isFullyActive() || window->document()->unloadCounter())
+ if (RefPtr document = window->document(); !document->isFullyActive() || frame()->loader().isDispatchingPageSwapEvent() || document->unloadCounter())
return createErrorResult(WTF::move(committed), WTF::move(finished), ExceptionCode::InvalidStateError, "Invalid state"_s);

Navigation::reload() now consults frame()->loader().isDispatchingPageSwapEvent() and rejects with InvalidStateError if true — the same guard already present in Navigation::navigate() per Bug 303364.

Missing re-entrancy guard on a Navigation API entry point invoked from inside a pageswap event handler, allowing nested code to invalidate provisional commit state the outer caller still depends on.

A reload reaching the committed phase fires pageswap; the handler synchronously calling navigation.reload() ran a sync policy check that cleared FrameLoader::m_provisionalDocumentLoader. When the handler returned, updateForCommit() dereferenced the now-null loader.

This is an explicit variant fix — the commit message names Bug 303364 (which applied the same guard to navigate()) and ports it to reload(). Variant fixes lagging the original by months is a recurring pattern in this subsystem.

This vulnerability weakens renderer process availability by allowing same-origin script to deterministically crash WebContent. Promotion beyond crash would require the dangling state to be reused for a memory-safety primitive, which is not directly evident from this diff.