From 7e74b898bd80524674a152dbb496399bc0914bff Mon Sep 17 00:00:00 2001 From: "Ricardo Bossan (BEYONDSOFT CONSULTING INC) (from Dev Box)" Date: Tue, 28 Jan 2025 01:47:18 -0300 Subject: [PATCH] Prevents runtime crashes when the `DataGridView` or `CurrentCell` are null. Fixes #12752 ## Root Cause - The issue occurs because the `NotifyMSAAClient` method is called without checking if the `DataGridView` instance is `null`. This leads to a potential `NullReferenceException`. ## Proposed changes - Add a `null` check for the `DataGridView` instance before calling the `NotifyMSAAClient` method. - Adds another `null` check for the `CurrentCell` property before calling the `PaintGrid` method. - Add further checks for DataGridView in paint events ## Customer Impact - Prevents runtime crashes when the `DataGridView` or `CurrentCell` are null. ## Regression? - No ## Risk - Minimal ## Screenshots ### Before ### After ## Test methodology - Manual testing ## Test environment(s) - `10.0.100-alpha.1.25064.3` --- .../Controls/DataGridView/DataGridViewCell.cs | 4 +++- .../DataGridView/DataGridViewCheckBoxCell.cs | 17 ++++++++++++----- .../Controls/DataGridView/DataGridViewRow.cs | 6 +++++- .../DataGridView/DataGridViewRowHeaderCell.cs | 6 ++++++ .../DataGridView/DataGridViewTextBoxCell.cs | 5 +++++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCell.cs index cd57a0c1252..6740bed8c97 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCell.cs @@ -3671,7 +3671,9 @@ internal void PaintWork(Graphics graphics, cellStyle, advancedBorderStyle, paintParts); - dataGridView.OnCellPainting(dgvcpe); + + dataGridView?.OnCellPainting(dgvcpe); + if (dgvcpe.Handled) { return; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCheckBoxCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCheckBoxCell.cs index cee95b9b3d1..33b0299b22f 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCheckBoxCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewCheckBoxCell.cs @@ -839,9 +839,9 @@ protected override void OnKeyUp(KeyEventArgs e, int rowIndex) e.Handled = true; } - NotifyMSAAClient(ColumnIndex, rowIndex); + NotifyMSAAClient(ColumnIndex, rowIndex); + } } - } protected override void OnLeave(int rowIndex, bool throughMouseClick) { @@ -967,9 +967,12 @@ private void NotifyUiaClient() private void NotifyMSAAClient(int columnIndex, int rowIndex) { - Debug.Assert(DataGridView is not null); - Debug.Assert((columnIndex >= 0) && (columnIndex < DataGridView.Columns.Count)); - Debug.Assert((rowIndex >= 0) && (rowIndex < DataGridView.Rows.Count)); + if (DataGridView is null || + columnIndex < 0 || columnIndex >= DataGridView.Columns.Count || + rowIndex < 0 || rowIndex >= DataGridView.Rows.Count) + { + return; + } int visibleRowIndex = DataGridView.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, rowIndex); int visibleColumnIndex = DataGridView.Columns.ColumnIndexToActualDisplayIndex(columnIndex, DataGridViewElementStates.Visible); @@ -1043,7 +1046,11 @@ private Rectangle PaintPrivate( bool computeErrorIconBounds, bool paint) { + if(DataGridView is null) // Parameter checking. + { + return Rectangle.Empty; + } // One bit and one bit only should be turned on Debug.Assert(paint || computeContentBounds || computeErrorIconBounds); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRow.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRow.cs index 6927fe09346..e0ae66ee494 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRow.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRow.cs @@ -786,9 +786,13 @@ private void BuildInheritedRowHeaderCellStyle(DataGridViewCellStyle inheritedCel private void BuildInheritedRowStyle(int rowIndex, DataGridViewCellStyle inheritedRowStyle) { + if (DataGridView is null) + { + return; + } + Debug.Assert(inheritedRowStyle is not null); Debug.Assert(rowIndex >= 0); - Debug.Assert(DataGridView is not null); DataGridViewCellStyle? rowStyle = null; if (HasDefaultCellStyle) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRowHeaderCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRowHeaderCell.cs index 761e85955f8..8c35562b399 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRowHeaderCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewRowHeaderCell.cs @@ -653,6 +653,12 @@ private Rectangle PaintPrivate( bool cellSelected = (dataGridViewElementState & DataGridViewElementStates.Selected) != 0; Debug.Assert(DataGridView is not null); + + if (DataGridView is null) + { + return Rectangle.Empty; + } + if (DataGridView.ApplyVisualStylesToHeaderCells) { if (cellStyle.Padding != Padding.Empty) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewTextBoxCell.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewTextBoxCell.cs index a26d3844f00..f89cc52511e 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewTextBoxCell.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/DataGridView/DataGridViewTextBoxCell.cs @@ -649,6 +649,11 @@ private Rectangle PaintPrivate( bool computeErrorIconBounds, bool paint) { + if (DataGridView is null) + { + return Rectangle.Empty; + } + // Parameter checking. One bit and one bit only should be turned on. Debug.Assert(paint || computeContentBounds || computeErrorIconBounds); Debug.Assert(!paint || !computeContentBounds || !computeErrorIconBounds);