Skip to content

Conversation

@techouse
Copy link
Owner

@techouse techouse commented Jan 11, 2026

This pull request introduces significant changes to how decoded lists and arrays are represented and handled when certain limits are reached, as well as updates to the test suite and dependency versions. The main focus is on converting lists to dictionaries (maps) when a specified ListLimit is exceeded, and on tracking this "overflow" state internally. The changes are thoroughly tested with new and updated unit tests.

Key changes include:

Core logic and data structure changes

  • Updated the logic in Decoder.cs and Utils.cs so that when a decoded list exceeds the configured ListLimit, it is converted from a List<object?> to a Dictionary<object, object?> (map), and an internal overflow state is tracked using a ConditionalWeakTable. This ensures consistent handling of oversized lists and allows for correct merging and combining of overflowed collections. [1] [2] [3] [4] [5]

Test suite updates

  • Updated numerous test cases in QsNet.Tests/DecodeTests.cs to expect dictionaries (maps) instead of lists when the ListLimit is exceeded or set to zero, ensuring the tests reflect the new overflow behavior. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

  • Added comprehensive new tests for overflow and limit behavior, including boundary conditions, implicit array limits, duplicate value handling, and correct merging/combining of overflowed collections. This ensures robust coverage of all edge cases related to list size limits. [1] [2]

Dependency update

  • Updated the qs JavaScript library dependency version from ^6.14.0 to ^6.14.1 in package.json.

These changes improve the reliability and predictability of list handling in the decoder, especially in edge cases involving large or complex query strings.


Relates to GHSA-6rw7-vpxm-498p

Summary by CodeRabbit

  • Improvements

    • Query string decoder now features refined list overflow handling with automatic conversion to indexed dictionaries when configured limits are exceeded, ensuring more predictable behavior in constraint scenarios.
  • Chores

    • Updated parser dependency.

✏️ Tip: You can customize this high-level summary in your review settings.

@techouse techouse self-assigned this Jan 11, 2026
@techouse techouse added the bug Something isn't working label Jan 11, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

This PR introduces overflow tracking for list limits in query string decoding. When values exceed ListLimit, lists are converted to index-keyed dictionaries with overflow state metadata. The decoder integrates new limit-aware merging logic, and test expectations are updated to reflect dictionary-based representations under constraint conditions.

Changes

Cohort / File(s) Summary
Dependency Update
QsNet.Comparison/js/package.json
Bumps "qs" dependency from ^6.14.0 to ^6.14.1
Core Overflow Logic
QsNet/Internal/Utils.cs
Introduces internal OverflowState tracking, OverflowTable per-object storage, and helper methods (IsOverflow, GetOverflowMaxIndex, SetOverflowMaxIndex, MarkOverflow, TryGetArrayIndex, GetMaxIndexFromMap). Extends Merge to honor overflow state when targets are dictionaries. Adds CombineWithLimit function that converts lists exceeding ListLimit to index-mapped dictionaries. Implements ListToIndexMap for list-to-dictionary conversion with numeric string keys
Decoder Integration
QsNet/Internal/Decoder.cs
Replaces Utils.Combine calls with Utils.CombineWithLimit to apply list-length constraints. Adds overflow guards in list handling to propagate overflow state without further wrapping
Test Updates: Decode Behavior
QsNet.Tests/DecodeTests.cs
Updates test expectations where lists previously asserted as List\<object?\> now expect Dictionary\<string, object?\> with numeric string keys when ListLimit is zero. Adds new tests for ListLimit boundary conditions and implicit array-to-map conversions
Test Coverage: Utils Utilities
QsNet.Tests/UtilsTests.cs
Adds extensive unit tests for Utils.CombineWithLimit and Utils.Merge overflow/limit handling, covering over-limit scenarios, zero ListLimit conversions, overflow indexing, and overflow-aware merging with primitives and mixed keys

Sequence Diagram(s)

sequenceDiagram
    participant Decoder
    participant CombineWithLimit
    participant Merge
    participant OverflowTable
    
    Decoder->>CombineWithLimit: CombineWithLimit(existingVal, value, options)
    activate CombineWithLimit
    CombineWithLimit->>CombineWithLimit: Check if combined size exceeds ListLimit
    alt Within Limit
        CombineWithLimit->>Merge: Merge values normally
    else Exceeds Limit
        CombineWithLimit->>CombineWithLimit: ListToIndexMap(result to Dict)
        CombineWithLimit->>OverflowTable: MarkOverflow(dict, maxIndex)
    end
    CombineWithLimit-->>Decoder: Return merged value (List or Dict with overflow)
    deactivate CombineWithLimit
    
    Decoder->>OverflowTable: Check IsOverflow(leaf)
    alt Overflow Detected
        Decoder-->>Decoder: Propagate leaf as-is
    else No Overflow
        Decoder->>CombineWithLimit: CombineWithLimit([], leaf, options)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Lists overflow? No fright!
Index keys map them just right,
Limits respected with care,
Overflow state tracked with flair,
Query strings merge, clean and bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description is comprehensive and covers key changes, testing updates, and dependency changes. All major sections are well-documented with clear explanations and references.
Title check ✅ Passed The title directly and clearly describes the main change: implementing DecodeOptions.ListLimit handling to prevent DoS via memory exhaustion, which aligns with the core objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@techouse techouse changed the title fix: implement array limit handling to prevent DoS via memory exhaustion fix: implement DecodeOptions.ListLimit handling to prevent DoS via memory exhaustion Jan 11, 2026
@codecov
Copy link

codecov bot commented Jan 11, 2026

Codecov Report

❌ Patch coverage is 88.99083% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.40%. Comparing base (fe5ea33) to head (26db1f9).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
QsNet/Internal/Utils.cs 88.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #44      +/-   ##
==========================================
- Coverage   98.14%   97.40%   -0.75%     
==========================================
  Files          15       15              
  Lines        1400     1500     +100     
  Branches      396      427      +31     
==========================================
+ Hits         1374     1461      +87     
- Misses         26       39      +13     
Flag Coverage Δ
unittests 97.40% <88.99%> (-0.75%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

@techouse techouse marked this pull request as ready for review January 11, 2026 23:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
QsNet.Tests/DecodeTests.cs (1)

2580-2590: Good coverage for implicit array limit overflow.

The test correctly verifies that when the number of elements (105) exceeds ListLimit (100), the result becomes an IDictionary with all values preserved.

💡 Optional: Consider using FluentAssertions' Which clause for cleaner assertions
 result.Should().ContainKey("a");
-result["a"].Should().BeAssignableTo<IDictionary>();
-((IDictionary)result["a"]!).Count.Should().Be(105);
+result["a"].Should().BeAssignableTo<IDictionary>()
+    .Which.Count.Should().Be(105);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe5ea33 and 8e54046.

📒 Files selected for processing (5)
  • QsNet.Comparison/js/package.json
  • QsNet.Tests/DecodeTests.cs
  • QsNet.Tests/UtilsTests.cs
  • QsNet/Internal/Decoder.cs
  • QsNet/Internal/Utils.cs
🧰 Additional context used
📓 Path-based instructions (4)
QsNet.Tests/**/*.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

QsNet.Tests/**/*.cs: Tests must use xUnit with FluentAssertions
Test method naming should follow Should style

Files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet.Tests/DecodeTests.cs
QsNet.Tests/**/DecodeTests.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When extending decode tests, clone analogous existing cases in DecodeTests.cs to ensure js-qs parity

Files:

  • QsNet.Tests/DecodeTests.cs
QsNet/{Internal,Models,Enums,Constants}/**/*.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All code under Internal/, Models/, Enums/, Constants/ is implementation detail and must not expose public surface

Files:

  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
QsNet/**/*.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add concise XML docs on new public members reflecting actual behavior for DocFX

Files:

  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Models/DecodeOptions.cs : Preserve Depth, ParameterLimit, and ListLimit guards; keep defaults protective and make extensions feature-gated
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet.Tests/**/DecodeTests.cs : When extending decode tests, clone analogous existing cases in DecodeTests.cs to ensure js-qs parity
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Decoder*.cs : Escalate large indices to dictionary when index exceeds ListLimit
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet.Tests/**/EncodeTests.cs : When extending encode tests, clone analogous existing cases in EncodeTests.cs to ensure js-qs parity
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/Utils*.cs : Minimize allocations in Utils.Merge and Utils.Encode/Decode hot paths; avoid LINQ in tight loops

Applied to files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/Utils*.cs : Utils.Compact and Utils.ToStringKeyDeepNonRecursive must avoid deep recursion; keep non-recursive approach

Applied to files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet.Tests/**/*.cs : Tests must use xUnit with FluentAssertions

Applied to files:

  • QsNet.Tests/UtilsTests.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Models/DecodeOptions.cs : Preserve Depth, ParameterLimit, and ListLimit guards; keep defaults protective and make extensions feature-gated

Applied to files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Decoder*.cs : Mixed list/dictionary notations must unify into a dictionary during decode

Applied to files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Decoder*.cs : Escalate large indices to dictionary when index exceeds ListLimit

Applied to files:

  • QsNet.Tests/UtilsTests.cs
  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Utils.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet.Tests/**/DecodeTests.cs : When extending decode tests, clone analogous existing cases in DecodeTests.cs to ensure js-qs parity

Applied to files:

  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet.Tests/**/EncodeTests.cs : When extending encode tests, clone analogous existing cases in EncodeTests.cs to ensure js-qs parity

Applied to files:

  • QsNet.Tests/DecodeTests.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/{Encoder,Decoder}*.cs : Minimize allocations in hot paths; prefer reusing lists and avoid LINQ in tight loops unless existing code already does so

Applied to files:

  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/{Encoder,Decoder}*.cs : Only encode dots in keys when EncodeDotInKeys is true; keep coherent with AllowDots/DecodeDotInKeys

Applied to files:

  • QsNet.Tests/DecodeTests.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to QsNet/**/*.cs : Add concise XML docs on new public members reflecting actual behavior for DocFX

Applied to files:

  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Utils.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/{Encoder,Decoder}*.cs : Honor strict null handling vs empty string differentiation

Applied to files:

  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Encoder*.cs : Use Internal/Encoder.Encode for recursive encode producing key=value parts; keep branches small and composable using structured switch/pattern matching

Applied to files:

  • QsNet.Tests/DecodeTests.cs
  • QsNet/Internal/Decoder.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Encoder*.cs : Support comma list format round-tripping via CommaRoundTrip by appending [] when needed

Applied to files:

  • QsNet.Tests/DecodeTests.cs
📚 Learning: 2025-10-07T20:35:41.523Z
Learnt from: CR
Repo: techouse/qs-net PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-07T20:35:41.523Z
Learning: Applies to Internal/**/Decoder*.cs : Decoder.ParseKeys should drive key path parsing; keep logic small and composable

Applied to files:

  • QsNet/Internal/Decoder.cs
🧬 Code graph analysis (2)
QsNet.Tests/DecodeTests.cs (3)
QsNet/Internal/Decoder.cs (2)
  • Dictionary (107-271)
  • List (581-698)
QsNet/Qs.cs (2)
  • Dictionary (30-117)
  • Qs (20-281)
QsNet/Models/DecodeOptions.cs (4)
  • Decode (203-214)
  • DecodeOptions (40-321)
  • DecodeOptions (49-63)
  • DecodeOptions (274-320)
QsNet/Internal/Decoder.cs (1)
QsNet/Internal/Utils.cs (4)
  • Utils (20-1397)
  • CombineWithLimit (867-885)
  • IsOverflow (813-816)
  • List (783-811)
🔇 Additional comments (21)
QsNet/Internal/Utils.cs (6)

30-35: LGTM! Appropriate use of ConditionalWeakTable for overflow tracking.

The OverflowState class and OverflowTable correctly implement metadata tracking without preventing garbage collection. The sealed class and thread-safe ConditionalWeakTable are appropriate design choices for this purpose.


834-856: LGTM! Robust numeric index detection.

The round-trip check (parsed.ToString(CultureInfo.InvariantCulture) == s) correctly rejects strings with leading zeros or whitespace (e.g., "007", " 7"), ensuring only canonical numeric representations are treated as array indices.


867-885: LGTM! Clean limit-aware combining logic.

The implementation correctly:

  1. Bypasses limit checks when ListLimit < 0
  2. Appends to existing overflow dictionaries at the next index
  3. Converts to an index-keyed map when the limit is exceeded

The cast to IDictionary on line 874 is safe because only dictionaries created via ListToIndexMap are marked as overflow.


186-219: LGTM! Overflow-aware merging for target dictionaries.

The overflow handling correctly:

  1. Propagates overflow state when copying to a mutable dictionary
  2. Appends source items at sequential indices starting from targetMaxIndex + 1
  3. Updates the overflow max index after processing

294-326: LGTM! Correct index shifting when merging overflow into primitives.

When the source is an overflow dictionary and the target is a primitive, the implementation correctly:

  1. Places the primitive at index "0"
  2. Shifts all numeric source indices by +1
  3. Preserves non-numeric keys unchanged
  4. Adjusts the overflow max index to account for the shift

887-893: LGTM! Efficient list-to-map conversion.

Pre-allocating dictionary capacity with list.Count minimizes allocations in this hot path, per coding guidelines.

QsNet/Internal/Decoder.cs (2)

256-256: LGTM! Correctly applies list limit when combining duplicate values.

Using CombineWithLimit ensures the ListLimit is enforced when merging duplicate key values, preventing unbounded list growth.


355-368: LGTM! Correct overflow propagation for array notation.

The implementation properly handles the "[]" key case:

  1. Propagates overflow dictionaries as-is to preserve their state
  2. Uses CombineWithLimit for non-overflow leaves to enforce the limit
  3. Preserves the empty-list special case for AllowEmptyLists
QsNet.Tests/UtilsTests.cs (5)

1236-1272: LGTM! Comprehensive boundary testing for list limits.

The test effectively covers the three key scenarios: under limit (List), at limit (List), and over limit (Dictionary with overflow tracking). The boundary at ListLimit = 3 is well tested.


1274-1284: LGTM! Zero-limit edge case coverage.

Correctly verifies that ListLimit = 0 immediately converts any list to an index-keyed dictionary, which is the expected behavior to prevent any list allocation.


1286-1307: LGTM! Validates overflow append semantics.

Correctly verifies that appending to an overflow object:

  1. Mutates the same dictionary instance
  2. Uses the next sequential index
  3. Maintains overflow state

1309-1317: LGTM! Validates non-overflow map handling.

Correctly verifies that a plain dictionary (not marked as overflow) is treated as a single value during combine, not as a container to append to. This distinction is crucial for correct merging semantics.


1319-1405: LGTM! Comprehensive merge behavior tests.

The tests correctly cover:

  1. Overflow object merging with append semantics
  2. Plain map merging with value-as-key behavior
  3. Index shifting when merging overflow into primitives
  4. Respecting existing numeric keys when calculating next index

The test at line 1383-1405 validates the important edge case where the target has existing high numeric keys that must be respected when appending.

QsNet.Comparison/js/package.json (1)

8-8: Version 6.14.1 correctly addresses the high-severity DoS vulnerability (GHSA-6rw7-vpxm-498p / CVE-2025-15284).

The fix enforces the arrayLimit option for bracket notation queries (e.g., a[]=...), preventing memory exhaustion attacks via large query arrays. This change resolves the vulnerability.

QsNet.Tests/DecodeTests.cs (7)

750-757: LGTM: Updated expectations for ListLimit=0 behavior.

The test expectations correctly reflect the new behavior where lists with ListLimit = 0 are converted to dictionaries with string numeric keys ("0", "1", etc.) instead of remaining as List<object?>.

Also applies to: 777-784


2592-2627: LGTM: Well-structured boundary condition tests.

The test correctly covers:

  • At-limit case (3 elements, limit 3): remains a List<object?>
  • Over-limit case (4 elements, limit 3): converts to Dictionary
  • Edge case (2 elements, limit 1): converts to Dictionary

This ensures proper escalation to dictionary when index exceeds ListLimit, as per the coding guidelines.


2629-2654: LGTM: Good coverage for duplicate value handling with limits.

The test properly verifies that duplicate key values (a=b&a=c&a=d) are:

  • Combined into a List<object?> when within ListLimit (20)
  • Converted to a Dictionary<string, object?> with sequential numeric keys when exceeding ListLimit (2)

This validates the limit-aware merging logic introduced in the PR.


1290-1336: LGTM: Consistent updates for ListLimit=0 with StrictNullHandling.

The test expectations correctly show that with ListLimit = 0, arrays are represented as dictionaries with string numeric keys, properly preserving null values and empty strings according to StrictNullHandling settings.


4271-4299: LGTM: Correct update for comma-split limit overflow behavior.

The test properly reflects that when comma-split values exceed ListLimit with ThrowOnLimitExceeded = false, the result converts to a dictionary while preserving all values. The comment on lines 4287-4288 accurately documents this behavior.


3000-3026: LGTM: Consistent with ListLimit=0 behavior.

Test expectations correctly updated to reflect dictionary representation when ListLimit = 0.


3509-3560: LGTM: Complete coverage for empty strings with ListLimit=0.

The updated expectations for ShouldAllowForEmptyStringsInArrays properly test the dictionary-based representation with:

  • Mixed null and empty string values
  • Correct sequential numeric keys
  • Proper handling under StrictNullHandling = true

@techouse techouse changed the title fix: implement DecodeOptions.ListLimit handling to prevent DoS via memory exhaustion 🐛 implement DecodeOptions.ListLimit handling to prevent DoS via memory exhaustion Jan 11, 2026
@techouse techouse merged commit 60f779f into main Jan 11, 2026
15 of 17 checks passed
@techouse techouse deleted the fix/arrayLimit-bypass-in-bracket-notation-allows-DoS-via-memory-exhaustion branch January 11, 2026 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant