-
Notifications
You must be signed in to change notification settings - Fork 35
Bound decoder work to prevent a pointer fan-out DoS (STF-1572) #355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
e4ba0e3
Bound decoder work to prevent a pointer fan-out denial of service
oschwald 061a3cb
Bound decoder payload to prevent an amplification denial of service
oschwald 790cfa0
Report out-of-bounds data-section reads as a database error
oschwald 38d5e23
Bound netstandard2.0 buffer reads to the database length
oschwald 975dab6
Charge followed pointers once and test resource-limit boundaries
oschwald 6746edd
Test payload limits through memory loading and enumeration
oschwald fa6b4c2
Test that decode limits reject oversized headers before reading
oschwald ac0cc6d
Test pointer-chain depth and integer payload charging
oschwald 8ed36d6
Clarify pointer-target payload accounting
oschwald 1beee94
Correct the depth boundary and test inherited pointer depth
oschwald 403ecb3
Test container-depth and integer-payload boundaries
oschwald 0ac19c9
Test that repeated and concurrent lookups get separate budgets
oschwald 03f176d
Test 512-container decoding with different stack sizes
oschwald 1d76141
Test repeated follows of a shared pointer chain
oschwald ad847f9
Document why CheckContainer's subtraction cannot overflow
oschwald ff76604
Build the decoder's type-mismatch message out of line
oschwald b479813
Forward command-line options to benchmarks
oschwald 036bbaf
Separate scalar decode dispatch
oschwald 48be56d
Follow map-key pointers without recursive calls
oschwald 0c39ae5
Avoid boxed capacities in reflection collection factories
oschwald 9f6bec8
Reject oversized uint32, uint64, and uint128 encodings
oschwald bb8ee93
Decode pointer control bits before expanding value sizes
oschwald a4691cc
Format release notes
oschwald 7e897d2
Reject pointers to pointers during decoding
oschwald 53fbfa3
Test buffer bounds through each read path and Reader
oschwald 55d1b76
Test lookup recovery and map value boundaries
oschwald 78d70ee
Verify dictionary factories preserve requested capacity
oschwald d069622
Clarify decoder limits and testing guidance
oschwald File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| using System.Collections.Generic; | ||
| using Xunit; | ||
|
|
||
| namespace MaxMind.Db.Test | ||
| { | ||
| public static class CollectionActivatorTest | ||
| { | ||
| [Fact] | ||
| public static void ListFactoryUsesRequestedCapacity() | ||
| { | ||
| var factory = new ListActivatorCreator().GetActivator(typeof(ICollection<long>)); | ||
| var list = Assert.IsType<List<long>>(factory(123)); | ||
| Assert.Empty(list); | ||
| Assert.Equal(123, list.Capacity); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void ListFactoryPreservesCustomDefaultConstructor() | ||
| { | ||
| var factory = new ListActivatorCreator().GetActivator(typeof(DefaultList<long>)); | ||
| var list = Assert.IsType<DefaultList<long>>(factory(123)); | ||
| Assert.True(list.WasConstructed); | ||
| Assert.Equal(0, list.Capacity); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void DictionaryFactoryCreatesRequestedInterface() | ||
| { | ||
| var factory = new DictionaryActivatorCreator().GetActivator(typeof(IDictionary<string, long>)); | ||
| var dictionary = Assert.IsType<Dictionary<string, long>>(factory(123)); | ||
| Assert.Empty(dictionary); | ||
| #if NET8_0_OR_GREATER | ||
| Assert.True(dictionary.EnsureCapacity(0) >= 123); | ||
| #endif | ||
| dictionary.Add("value", 7); | ||
| Assert.Equal(7, dictionary["value"]); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void DictionaryFactoryPreservesCustomDefaultConstructor() | ||
| { | ||
| var factory = new DictionaryActivatorCreator().GetActivator(typeof(DefaultDictionary<string, long>)); | ||
| var dictionary = Assert.IsType<DefaultDictionary<string, long>>(factory(123)); | ||
| Assert.True(dictionary.WasConstructed); | ||
| Assert.Empty(dictionary); | ||
| } | ||
|
|
||
| private sealed class DefaultList<T> : List<T> | ||
| { | ||
| public DefaultList() | ||
| { | ||
| WasConstructed = true; | ||
| } | ||
|
|
||
| public bool WasConstructed { get; } | ||
| } | ||
|
|
||
| private sealed class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TKey : notnull | ||
| { | ||
| public DefaultDictionary() | ||
| { | ||
| WasConstructed = true; | ||
| } | ||
|
|
||
| public bool WasConstructed { get; } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reaches the dictionary capacity branch of
CreateCapacityActivatorbut only assertsEmptyplus an add/read round-trip, so a regression selectingDictionary's parameterless constructor would pass. The list equivalent above does assert capacity.EnsureCapacity(0)returns 131 for the current factory and 0 for a parameterless one, soAssert.True(dictionary.EnsureCapacity(0) >= 123)closes it on every test TFM.馃 Comment by Claude (Claude Code) on behalf of Will.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added EnsureCapacity(0) >= 123 in 78d70ee on .NET 8 and later. net481 does not expose that API, so it keeps the existing empty and add/read checks.
Codex, responding on Greg鈥檚 behalf.