From 0a8e2f03059c3343cb7fc3e2e9096ba06447a062 Mon Sep 17 00:00:00 2001 From: Gabriele Ciech Date: Fri, 13 Nov 2026 17:12:02 +0100 Subject: [PATCH] Fix crash on NULL bcb_bdb in loops not covered by CORE-6509 After a failed expand_buffers() bcb_count still includes uninitialised (NULL) descriptors. CORE-6509 added the check to flushAll() only; add it to CCH_down_grade_dbb(), CCH_flush_ast(), CCH_shutdown() and get_prec_walk_mark() as well. Refs #9289 --- src/jrd/cch.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp index 82a7d3bc8d5..cd48fdabb18 100644 --- a/src/jrd/cch.cpp +++ b/src/jrd/cch.cpp @@ -356,6 +356,8 @@ int CCH_down_grade_dbb(void* ast_object) for (const bcb_repeat* const end = tail + bcb->bcb_count; tail < end; ++tail) { BufferDesc* bdb = tail->bcb_bdb; + if (!bdb) // first non-initialized BDB, abandon following checks + break; // Acquire EX latch to avoid races with LCK_release (called by CCH_release) // or LCK_lock (by lock_buffer) in main thread. Take extra care to avoid @@ -1226,6 +1228,9 @@ void CCH_flush_ast(thread_db* tdbb) for (ULONG i = 0; (bcb = dbb->dbb_bcb) && i < bcb->bcb_count; i++) { BufferDesc* bdb = bcb->bcb_rpt[i].bcb_bdb; + if (!bdb) // first non-initialized BDB, abandon following checks + break; + if (bdb->bdb_flags & (BDB_dirty | BDB_db_dirty)) down_grade(tdbb, bdb, 1); } @@ -2162,6 +2167,8 @@ void CCH_shutdown(thread_db* tdbb) for (; tail < end; tail++) { BufferDesc* const bdb = tail->bcb_bdb; + if (!bdb) // first non-initialized BDB, abandon following checks + break; if (dbb->dbb_flags & DBB_bugcheck) { @@ -4065,7 +4072,13 @@ static ULONG get_prec_walk_mark(BufferControl* bcb) if (++bcb->bcb_prec_walk_mark == 0) { for (ULONG i = 0; i < bcb->bcb_count; i++) - bcb->bcb_rpt[i].bcb_bdb->bdb_prec_walk_mark = 0; + { + BufferDesc* bdb = bcb->bcb_rpt[i].bcb_bdb; + if (!bdb) // first non-initialized BDB, abandon following checks + break; + + bdb->bdb_prec_walk_mark = 0; + } bcb->bcb_prec_walk_mark = 1; }