From 39f96d7188a75e96af7875f16b02b6a0b7facfe3 Mon Sep 17 00:00:00 2001 From: Dragolone <160818051+Dragolone@users.noreply.github.com> Date: Wed, 14 Oct 2026 06:05:34 +1100 Subject: [PATCH] fix(qlog): list a hidden stream's records without spreading call arguments (#2860) * fix(qlog): list a hidden stream's records without spreading call arguments When an explicit declaration matched a stream's derived total, the decoder pushed every contribution ordinal with a spread call. A stream with more than ~125k STREAM frames exceeded the engine's argument limit, so a valid capture within the input budget failed with RangeError instead of listing the records as incomplete. Push the ordinals in a loop. * fix(comparison): recheck historical calls-only changes (#2223) * fix(comparison): preserve incomplete function call evidence Keep missing, unknown, partial and unresolved call relationships unknown in function comparisons and reconstruction claims. Aggregate IDA caller and callee coverage without overwriting uncertainty. Validate with 144 focused tests, typecheck/lint, docs checks and test discovery. Real providers were not verified; the full headless IDA session suite requires unavailable Windows native controls. * fix(comparison): recheck historical calls-only changes --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> * fix(ci): isolate Linux Hopper process fixture inventory * fix(android): make DEX descriptor pattern portable --------- Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> --- src/browser/history/QlogCapture.test.ts | 15 +++++++++++++++ src/browser/history/QlogCapture.ts | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/browser/history/QlogCapture.test.ts b/src/browser/history/QlogCapture.test.ts index bd67d4e807..fb4e100729 100644 --- a/src/browser/history/QlogCapture.test.ts +++ b/src/browser/history/QlogCapture.test.ts @@ -186,6 +186,21 @@ it("excludes structural auth material and explicit normalized values without gue expect(traces[0]?.incomplete_fact_records).toContain(2); }); +it("omits a hidden derived total for a stream with more contributions than call arguments allow", () => { + const events = Array.from({ length: 130 }, (_, index) => + event( + Array.from({ length: 1_000 }, (_, offset) => + frame(index * 1_000 + offset, 1), + ), + ), + ); + const { traces } = facts(capture(events), ["130000"]); + expect(traces[0]?.streams).toEqual([]); + expect(traces[0]?.incomplete_fact_records).toEqual( + Array.from({ length: 130 }, (_, ordinal) => ordinal), + ); +}); + it("hides marked ancestor keys and safe derived sums while still validating hidden subtrees", () => { const text = capture([event([frame(0, 3), frame(3, 4)])]); expect(facts(text, ["7"]).traces[0]?.streams).toEqual([]); diff --git a/src/browser/history/QlogCapture.ts b/src/browser/history/QlogCapture.ts index 2e8a1f7906..8d19fc64fb 100644 --- a/src/browser/history/QlogCapture.ts +++ b/src/browser/history/QlogCapture.ts @@ -95,10 +95,10 @@ export const decodeQlogCapture = ( ...stream.reported_final_sizes, ...stream.covered_ranges.flatMap((r) => [r.start, r.end]), ]; + // A stream can have more contributions than call arguments allow. if (numericValues.some(excluded)) - fact.incomplete_fact_records.push( - ...stream.contributions.map((c) => c.record_ordinal), - ); + for (const contribution of stream.contributions) + fact.incomplete_fact_records.push(contribution.record_ordinal); else fact.streams.push(stream); } fact.incomplete_fact_records = [...new Set(fact.incomplete_fact_records)];