From bbcdde68dee541497e370aceab73b9c7df76c5fe Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 5 Jan 2024 09:59:55 +0100 Subject: [PATCH] Fix bad array access when an AFTER trigger raises an exception in SaveChanges (#3049) Fixes #3007 (cherry picked from commit 34e6242d56bdc77988e421e91e8e367ec042fff4) --- .../Update/Internal/NpgsqlModificationCommandBatch.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs b/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs index 09778a6bf..2bc592ff9 100644 --- a/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs +++ b/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs @@ -189,6 +189,16 @@ await ThrowAggregateUpdateConcurrencyExceptionAsync(reader, commandIndex, 1, 0, } catch (Exception ex) when (ex is not DbUpdateException and not OperationCanceledException) { + // If the commandIndex points after the last command, attribute the error to the last command. + // This can happen when an AFTER INSERT trigger raises an exception - the insertion itself is successful, and the error comes + // afterwards, as if belonging to the next command. When there's indeed a next command, there's no way to know whether the + // error indeed belongs to it or comes from a trigger on the previous (we assume the former), but when we're the last command, + // at least avoid indexing beyond the end of the array. See #3007. + if (commandIndex == ModificationCommands.Count) + { + commandIndex--; + } + throw new DbUpdateException( RelationalStrings.UpdateStoreException, ex,