Skip to content

fix: unbounded DictionarySlim growth when creating many IHandlebars instances (issue #541) - #625

Merged
rexm merged 3 commits into
masterfrom
worktree-agent-aca625122869d49d1
Jun 20, 2026
Merged

fix: unbounded DictionarySlim growth when creating many IHandlebars instances (issue #541)#625
rexm merged 3 commits into
masterfrom
worktree-agent-aca625122869d49d1

Conversation

@rexm

@rexmrexm commented Jun 20, 2026

Copy link
Copy Markdown
Member

Fixes#541

Root Cause

DictionarySlim<TKey, TValue, TComparer>.AddOrReplace was missing a return statement after updating the value for an existing key. This meant the method always fell through to AddValue, unconditionally inserting a new (duplicate) entry for every call — even when the key was already present.

Under sustained load — e.g. a DI-resolved service creating a new Handlebars.Create() instance and calling RegisterHelper on each request — the internal dictionary grew without bound, eventually exhausting memory and throwing OutOfMemoryException from DictionarySlim.Resize.

Fix

Added the missing return after the value-update path in AddOrReplace (one-line change in source/Handlebars/Collections/DictionarySlim.cs):

if(_comparer.Equals(key,entries[i].Key)){entries[i].Value=value;return;// <-- was missing}

Tests

Two new regression tests added to IssueTests.cs:

  • RegisterHelperRepeatedly_ShouldNotCauseUnboundedGrowth — creates 1 000 IHandlebars instances, each registering the same helper name twice, and compiles/runs the template to verify correct output.
  • RegisterHelper_SameNameRepeatedly_ShouldNotGrowHelpersCount — registers the same helper name 100 times on a single instance and asserts Configuration.Helpers has exactly 1 entry (would be 100 with the bug).

All 1 748 existing tests continue to pass.

🤖 Generated with Claude Code

rexmand others added 3 commits June 19, 2026 20:57
…keys (issue #541)
DictionarySlim.AddOrReplace was missing a `return` after updating the value
for an existing key, causing it to always fall through to AddValue and insert
a duplicate entry. Under sustained load (e.g. many IHandlebars instances each
calling RegisterHelper with the same name), the dictionary grew without bound
and eventually threw OutOfMemoryException from Resize.
Added two regression tests in IssueTests: one verifying the helpers count
stays at 1 after 100 repeated registrations of the same name, and one
confirming correct behaviour when creating 1000 IHandlebars instances.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rexm
rexm enabled auto-merge June 20, 2026 02:05
@sonarqubecloud

Copy link
Copy Markdown

@rexm
rexm merged commit 3f97922 into masterJun 20, 2026
7 checks passed
@rexm
rexm deleted the worktree-agent-aca625122869d49d1 branch June 20, 2026 02:16
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exception of type 'System.OutOfMemoryException' was thrown.

1 participant

@rexm