Skip to content

assert,util: fix TypeError on Maps with null keys#64441

Open
bitpshr wants to merge 1 commit into
nodejs:mainfrom
bitpshr:fix/deepequal-map-null-key
Open

assert,util: fix TypeError on Maps with null keys#64441
bitpshr wants to merge 1 commit into
nodejs:mainfrom
bitpshr:fix/deepequal-map-null-key

Conversation

@bitpshr

@bitpshr bitpshr commented Jul 12, 2026

Copy link
Copy Markdown

Fixes #64433.

assert.deepStrictEqual, assert.notDeepStrictEqual, and util.isDeepStrictEqual throw a TypeError on Maps with a null key in a specific shape: one map has a null key with an object value, the other has an object key with a deeply-equal value but no null key, and both maps are the same size.

It comes from mapObjectEquiv in lib/internal/util/comparisons.js, which only resolved primitive and null keys directly against the other map when array.length !== a.size. When the sizes match, the null key skipped that and reached the object comparator, which reads key.constructor with no null guard (and typeof null is 'object'). It only affects strict mode; loose already handled it and partial uses a different path.

The fix handles primitive and null keys unconditionally. I added a regression to test-assert-deep.js covering both the crashing case and the equal case.

`assert.deepStrictEqual`, `assert.notDeepStrictEqual`, and
`util.isDeepStrictEqual` threw a `TypeError` instead of returning a
result when one Map had a `null` key with an object value, the other
had an object key with a deeply-equal value but no `null` key, and
both maps were the same size.

In that case `mapObjectEquiv` skipped its primitive and `null` key
handling, which was gated on `array.length !== a.size`, and passed
the `null` key (which is `typeof 'object'`) to the object comparator.
That comparator reads `key.constructor` without a null guard, so it
threw. Handle primitive and `null` keys unconditionally, resolving
them directly against the other map.

Fixes: nodejs#64433
Signed-off-by: Paul Bouchon <mail@bitpshr.net>
@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. util Issues and PRs related to the built-in util module. labels Jul 12, 2026
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.25%. Comparing base (abe2545) to head (484a3ff).
⚠️ Report is 13 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #64441   +/-   ##
=======================================
  Coverage   90.25%   90.25%           
=======================================
  Files         741      741           
  Lines      241376   241379    +3     
  Branches    45478    45486    +8     
=======================================
+ Hits       217843   217855   +12     
+ Misses      15087    15085    -2     
+ Partials     8446     8439    -7     
Files with missing lines Coverage Δ
lib/internal/util/comparisons.js 99.71% <100.00%> (+<0.01%) ⬆️

... and 23 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. util Issues and PRs related to the built-in util module.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

assert.deepStrictEqual / util.isDeepStrictEqual throw TypeError on Maps with null keys

4 participants