From 5b6da3a5ae83820ba5dc97dd7b7fe6bb3af36fa6 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Wed, 30 Sep 2026 08:03:07 -0400 Subject: [PATCH] Secret-leak checks look for a sentinel that a timestamp, id or hash can't contain The deadlock drill-down tests planted 4721 and 9034 and then searched whole JSON responses for those digits. A wall-clock timestamp such as 11:20:24.4721267 holds them in its fractional seconds, so one run failed with nothing leaking. The planted literals are now qx4721 and qx9034 (letters outside a-f), which no timestamp, decimal id or hex hash can contain. Every assertion is kept. --- .../PgTargetDeadlockDrillDownTests.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Darling/Darling.Tests/PgTargetDeadlockDrillDownTests.cs b/Darling/Darling.Tests/PgTargetDeadlockDrillDownTests.cs index 0dcc4a8dd..4dac1df9e 100644 --- a/Darling/Darling.Tests/PgTargetDeadlockDrillDownTests.cs +++ b/Darling/Darling.Tests/PgTargetDeadlockDrillDownTests.cs @@ -118,8 +118,9 @@ public void TheDrillDown_AttachesOnEitherDeadlockRoot_ReusesTheRootFactCounter_A [Fact] public void AStoredFindingsExemplars_ReadBackNormalized_AndNameTheirReportByTimeAndPid() { - const string rawStatement = "UPDATE accounts SET pin = '4721' WHERE card = 4111111111111111"; - const string rawGraph = "Process 11 waits for ShareLock on transaction 900; blocked by process 12.\nProcess 12 waits for ShareLock on transaction 901; blocked by process 11.\nProcess 11: UPDATE accounts SET pin = '4721' WHERE card = 4111111111111111\nProcess 12: UPDATE accounts SET pin = '9034' WHERE card = 5500005555555559"; + /* The planted literals are sentinels: their letters lie outside a-f, so a timestamp, an id or a hash can't contain them. */ + const string rawStatement = "UPDATE accounts SET pin = 'qx4721' WHERE card = 4111111111111111"; + const string rawGraph = "Process 11 waits for ShareLock on transaction 900; blocked by process 12.\nProcess 12 waits for ShareLock on transaction 901; blocked by process 11.\nProcess 11: UPDATE accounts SET pin = 'qx4721' WHERE card = 4111111111111111\nProcess 12: UPDATE accounts SET pin = 'qx9034' WHERE card = 5500005555555559"; var rawHash = PgDeadlockLogParser.HashOf(rawGraph); var lastSeen = new DateTime(2026, 9, 1, 12, 30, 15, 250); var sentence = $"Exemplars: 1 report captured. The most frequent 2-participant shape involves ShareLock on transaction with the victim `{rawStatement}`, seen 1 time."; @@ -164,7 +165,7 @@ public void AStoredFindingsExemplars_ReadBackNormalized_AndNameTheirReportByTime foreach (var text in new[] { once.Item1, finding.StoryText }) { - foreach (var secret in new[] { "4721", "9034", "4111111111111111", "5500005555555559", rawHash }) + foreach (var secret in new[] { "qx4721", "qx9034", "4111111111111111", "5500005555555559", rawHash }) Assert.DoesNotContain(secret, text, StringComparison.Ordinal); } @@ -368,7 +369,7 @@ public async Task APlantedCounterDeltaBesideFourCapturedRows_CarriesTheExemplarD const string resourcesA = "relation orders, tuple orders"; /* The later report of shape A as a build before #4005 stored it: a literal in the graph, and a hash over that raw graph. The exemplar carries neither (#4005). */ - var graphA = "Process 11 waits for ShareLock on transaction 900; blocked by process 12.\nProcess 12 waits for ShareLock on transaction 901; blocked by process 11.\nProcess 11: UPDATE orders SET status = $1 WHERE id = $2\nProcess 12: UPDATE orders SET status = 'held-4721' WHERE id = 7"; + var graphA = "Process 11 waits for ShareLock on transaction 900; blocked by process 12.\nProcess 12 waits for ShareLock on transaction 901; blocked by process 11.\nProcess 11: UPDATE orders SET status = $1 WHERE id = $2\nProcess 12: UPDATE orders SET status = 'held-qx4721' WHERE id = 7"; var rawHashA2 = PgDeadlockLogParser.HashOf(graphA); await PlantDeadlockAsync(connection, windowStart.AddMinutes(10), "hash-a1", 2, modesA, resourcesA, "UPDATE orders SET status = $1 WHERE id = $2", graphA, ct); await PlantDeadlockAsync(connection, windowStart.AddMinutes(45), rawHashA2, 2, modesA, resourcesA, "UPDATE orders\n SET status = $1 WHERE id = $2", graphA, ct); @@ -418,9 +419,9 @@ twice under ONE hash (the overlapping tail re-read). */ Assert.False(a.GetProperty("victim_statement_may_be_truncated").GetBoolean()); Assert.Equal(4, a.GetProperty("graph_text_lines_total").GetInt32()); Assert.False(a.GetProperty("graph_text_truncated").GetBoolean()); - Assert.Equal(graphA.Replace("'held-4721' WHERE id = 7", "'?' WHERE id = ?", StringComparison.Ordinal), a.GetProperty("graph_text").GetString()); + Assert.Equal(graphA.Replace("'held-qx4721' WHERE id = 7", "'?' WHERE id = ?", StringComparison.Ordinal), a.GetProperty("graph_text").GetString()); Assert.DoesNotContain(rawHashA2, analysis, StringComparison.Ordinal); - Assert.DoesNotContain("4721", analysis, StringComparison.Ordinal); + Assert.DoesNotContain("qx4721", analysis, StringComparison.Ordinal); /* Shape B: one report seen twice; both bounds cut and both say so. */ var b = shapes[1]; @@ -457,7 +458,7 @@ same drill-down from the OTHER counter spelling and this read's own row total. * /* #4005: a finding a build before #4005 stored (an anchored run like the one above persists nothing) reads back through PgFindingStore, get_analysis_findings' read, normalized and naming its report by timestamp and pid, never by the stored hash. */ - var rawStatement = "UPDATE orders SET status = 'held-4721' WHERE id = 7"; + var rawStatement = "UPDATE orders SET status = 'held-qx4721' WHERE id = 7"; var preFix = new AnalysisFinding { FindingId = CollectionIdGenerator.Next(), @@ -497,7 +498,7 @@ same drill-down from the OTHER counter spelling and this read's own row total. * var stored = await DarlingMcpTools.GetAnalysisFindings(service, postgres, ServerName, 24, include_drilldown: true); Assert.Contains("4005-pre-fix-exemplar", stored, StringComparison.Ordinal); - Assert.DoesNotContain("4721", stored, StringComparison.Ordinal); + Assert.DoesNotContain("qx4721", stored, StringComparison.Ordinal); Assert.DoesNotContain(rawHashA2, stored, StringComparison.Ordinal); Assert.Contains(PgDeadlockLogParser.ReportIdentity(windowStart.AddMinutes(45), 4242), stored, StringComparison.Ordinal);