Skip to content
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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NRBF] More bug fixes #107682

Merged
merged 15 commits into from
Sep 12, 2024
Merged

[NRBF] More bug fixes #107682

merged 15 commits into from
Sep 12, 2024

Conversation

adamsitnik
Copy link
Member

Fixes issues discovered offline by @GrabYourPitchforks

@adamsitnik
Copy link
Member Author

@MihuBot fuzz NrbfDecoder

@MihuBot
Copy link

MihuBot commented Sep 11, 2024

// NrbfDecoderFuzzer
WARNING: Failed to find function "__sanitizer_acquire_crash_state".
WARNING: Failed to find function "__sanitizer_print_stack_trace".
WARNING: Failed to find function "__sanitizer_set_death_callback".

D:\runner-dir>D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\deployment\NrbfDecoderFuzzer\/libfuzzer-dotnet.exe --target_path=D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\deployment\NrbfDecoderFuzzer\/DotnetFuzzing.exe --target_arg=NrbfDecoderFuzzer -dict=D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\deployment\NrbfDecoderFuzzer\dictionary -timeout=60 -max_total_time=3600 NrbfDecoderFuzzer-inputs -exact_artifact_path=NrbfDecoderFuzzer-artifact-3 -print_final_stats=1 
INFO: libFuzzer ignores flags that start with '--'
Dictionary: 8 entries
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 153171003
INFO: Loaded 1 modules   (82 inline 8-bit counters): 82 [00007FF7BAC53008, 00007FF7BAC5305A), 
INFO: Loaded 1 PC tables (82 PCs): 82 [00007FF7BAC236F8,00007FF7BAC23C18), 
INFO: 65536 Extra Counters
INFO:     9724 files found in NrbfDecoderFuzzer-inputs
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: seed corpus: files: 9724 min: 1b max: 1585b total: 1149642b rss: 30Mb
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Formats.Nrbf.NrbfDecoder.DecodeMemberPrimitiveTypedRecord(BinaryReader reader)
   at System.Formats.Nrbf.NrbfDecoder.DecodeNext(BinaryReader reader, RecordMap recordMap, AllowedRecordTypes allowed, PayloadOptions options, SerializationRecordType& recordType)
   at System.Formats.Nrbf.NrbfDecoder.Decode(BinaryReader reader, PayloadOptions options, IReadOnlyDictionary`2& readOnlyRecordMap)
   at System.Formats.Nrbf.NrbfDecoder.Decode(Stream payload, IReadOnlyDictionary`2& recordMap, PayloadOptions options, Boolean leaveOpen)
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(Span`1 testSpan, Stream stream) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 43
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(ReadOnlySpan`1 bytes, PoisonPagePlacement poisonPagePlacement) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 30
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.FuzzTarget(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 21
   at DotnetFuzzing.Program.<>c__DisplayClass1_0.<RunFuzzer>b__0(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Program.cs:line 91
   at SharpFuzz.Fuzzer.LibFuzzer.Run(ReadOnlySpanAction action, Boolean ignoreExceptions)
==2996== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x0,0x1,0x0,0x0,0xff,0x0,0x30,0xff,0xff,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x12,
\000\001\000\000\377\0000\377\377\001\000\000\000\000\000\000\000\010\022
artifact_prefix='./'; Test unit written to NrbfDecoderFuzzer-artifact-3
Base64: AAEAAP8AMP//AQAAAAAAAAAIEg==

@@ -13,7 +13,7 @@ namespace System.Formats.Nrbf;
/// <remarks>
/// ArrayInfo structures are described in <see href="https://learn.microsoft.com/openspecs/windows_protocols/ms-nrbf/8fac763f-e46d-43a1-b360-80eb83d2c5fb">[MS-NRBF] 2.4.2.1</see>.
/// </remarks>
[DebuggerDisplay("Length={Length}, {ArrayType}, rank={Rank}")]
Copy link
Member Author

Choose a reason for hiding this comment

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

This type no longer provides Length property.


values.Add(value);
}
#else
Copy link
Member Author

Choose a reason for hiding this comment

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

this perf optimization was wrong because it was not checking if given string input is a valid utf8 string

@adamsitnik
Copy link
Member Author

@MihuBot fuzz NrbfDecoder

if (read == 0)
throw new EndOfStreamException();
offset += read;
return false;
Copy link
Member Author

Choose a reason for hiding this comment

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

the goal of this change is to simply return false rather than throw EOSE

Copy link
Member

Choose a reason for hiding this comment

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

Do we need to set the stream position back to the beginning before we return here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Do we need to set the stream position back to the beginning before we return here?

Great catch!

: new LinkedList<object>();
#endif

// ArrayInfo.GetSZArrayLength ensures to return a value <= Array.MaxLength
Copy link
Member Author

Choose a reason for hiding this comment

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

Since now we don't allow for any MD array with number of elements > Array.MaxLength, we don't need to use LinkedList anymore

@@ -176,7 +170,11 @@ internal static RectangularArrayRecord Create(BinaryReader reader, ArrayInfo arr
PrimitiveType.Int64 => sizeof(long),
PrimitiveType.UInt64 => sizeof(ulong),
PrimitiveType.Double => sizeof(double),
_ => -1
PrimitiveType.TimeSpan => sizeof(ulong),
PrimitiveType.DateTime => sizeof(ulong),
Copy link
Member Author

Choose a reason for hiding this comment

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

this is an improvement that I got into when I was making all the switch statements throw in the default case, we were not handling TimeSpan and DateTime properly before

@@ -15,6 +16,7 @@ namespace System.Formats.Nrbf;
/// <summary>
/// The ID of <see cref="SerializationRecord" />.
/// </summary>
[DebuggerDisplay("{_id}")]
Copy link
Member Author

Choose a reason for hiding this comment

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

It's just user experience improvement

@MihuBot
Copy link

MihuBot commented Sep 11, 2024

// NrbfDecoderFuzzer
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Formats.Nrbf.Utils.BinaryReaderExtensions.ReadPrimitiveValue(BinaryReader reader, PrimitiveType primitiveType)
   at System.Formats.Nrbf.NrbfDecoder.Decode(BinaryReader reader, PayloadOptions options, IReadOnlyDictionary`2& readOnlyRecordMap)
   at System.Formats.Nrbf.NrbfDecoder.Decode(Stream payload, IReadOnlyDictionary`2& recordMap, PayloadOptions options, Boolean leaveOpen)
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(Span`1 testSpan, Stream stream) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 43
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(ReadOnlySpan`1 bytes, PoisonPagePlacement poisonPagePlacement) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 30
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.FuzzTarget(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 21
   at DotnetFuzzing.Program.<>c__DisplayClass1_0.<RunFuzzer>b__0(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Program.cs:line 91
   at SharpFuzz.Fuzzer.LibFuzzer.Run(ReadOnlySpanAction action, Boolean ignoreExceptions)
==5792== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x0,0x1,0x0,0x0,0x41,0xfe,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x1,0x17,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xff,0x0,0x0,0x0,0x0,0x12,
\000\001\000\000A\376\377\377\377\001\000\000\000\000\000\000\000\007\001\027\000\000\000\001\000\000\000\377\000\000\000\000\022
artifact_prefix='./'; Test unit written to NrbfDecoderFuzzer-artifact-1
Base64: AAEAAEH+////AQAAAAAAAAAHARcAAAABAAAA/wAAAAAS

… complete, but increases the amount of code that needs to be reviewed
@adamsitnik
Copy link
Member Author

@MihuBot fuzz NrbfDecoder

@adamsitnik
Copy link
Member Author

@MihuBot fuzz NrbfDecoder

@MihuBot
Copy link

MihuBot commented Sep 11, 2024

// NrbfDecoderFuzzer
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Formats.Nrbf.RectangularArrayRecord.MapPrimitive(PrimitiveType primitiveType)
   at System.Formats.Nrbf.RectangularArrayRecord.Create(BinaryReader reader, ArrayInfo arrayInfo, MemberTypeInfo memberTypeInfo, Int32[] lengths)
   at System.Formats.Nrbf.BinaryArrayRecord.Decode(BinaryReader reader, RecordMap recordMap, PayloadOptions options)
   at System.Formats.Nrbf.NrbfDecoder.DecodeNext(BinaryReader reader, RecordMap recordMap, AllowedRecordTypes allowed, PayloadOptions options, SerializationRecordType& recordType)
   at System.Formats.Nrbf.NrbfDecoder.Decode(BinaryReader reader, PayloadOptions options, IReadOnlyDictionary`2& readOnlyRecordMap)
   at System.Formats.Nrbf.NrbfDecoder.Decode(Stream payload, IReadOnlyDictionary`2& recordMap, PayloadOptions options, Boolean leaveOpen)
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(Span`1 testSpan, Stream stream) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 43
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(ReadOnlySpan`1 bytes, PoisonPagePlacement poisonPagePlacement) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 30
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.FuzzTarget(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 21
   at DotnetFuzzing.Program.<>c__DisplayClass1_0.<RunFuzzer>b__0(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Program.cs:line 91
   at SharpFuzz.Fuzzer.LibFuzzer.Run(ReadOnlySpanAction action, Boolean ignoreExceptions)
==8688== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x0,0x9,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x1,0x17,0x0,0x0,0x2,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x7,0xfa,0x0,0x7,0x7,0x7,0x7,0x7,0x7,0x6,0x0,0x0,0x0,0x0,0x12,
\000\011\000\000\000\377\377\377\377\001\000\000\000\000\000\000\000\007\001\027\000\000\002\010\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\007\000\000\007\372\000\007\007\007\007\007\007\006\000\000\000\000\022
artifact_prefix='./'; Test unit written to NrbfDecoderFuzzer-artifact-1
Base64: AAkAAAD/////AQAAAAAAAAAHARcAAAIIAAAAAAAAAAAABAAAAAAAAAAAAAcAAAf6AAcHBwcHBwYAAAAAEg==

@MihuBot
Copy link

MihuBot commented Sep 11, 2024

// NrbfDecoderFuzzer
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Formats.Nrbf.RectangularArrayRecord.MapPrimitive(PrimitiveType primitiveType)
   at System.Formats.Nrbf.RectangularArrayRecord.Create(BinaryReader reader, ArrayInfo arrayInfo, MemberTypeInfo memberTypeInfo, Int32[] lengths)
   at System.Formats.Nrbf.BinaryArrayRecord.Decode(BinaryReader reader, RecordMap recordMap, PayloadOptions options)
   at System.Formats.Nrbf.NrbfDecoder.DecodeNext(BinaryReader reader, RecordMap recordMap, AllowedRecordTypes allowed, PayloadOptions options, SerializationRecordType& recordType)
   at System.Formats.Nrbf.NrbfDecoder.Decode(BinaryReader reader, PayloadOptions options, IReadOnlyDictionary`2& readOnlyRecordMap)
   at System.Formats.Nrbf.NrbfDecoder.Decode(Stream payload, IReadOnlyDictionary`2& recordMap, PayloadOptions options, Boolean leaveOpen)
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(Span`1 testSpan, Stream stream) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 43
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.Test(ReadOnlySpan`1 bytes, PoisonPagePlacement poisonPagePlacement) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 30
   at DotnetFuzzing.Fuzzers.NrbfDecoderFuzzer.FuzzTarget(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Fuzzers\NrbfDecoderFuzzer.cs:line 21
   at DotnetFuzzing.Program.<>c__DisplayClass1_0.<RunFuzzer>b__0(ReadOnlySpan`1 bytes) in D:\runner-dir\runtime\src\libraries\Fuzzing\DotnetFuzzing\Program.cs:line 91
   at SharpFuzz.Fuzzer.LibFuzzer.Run(ReadOnlySpanAction action, Boolean ignoreExceptions)
==8536== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x0,0x9,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x1,0x17,0x0,0x0,0x2,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x7,0xfa,0x0,0x7,0x7,0x7,0x7,0x7,0x7,0x6,0x0,0x0,0x0,0x0,0x12,
\000\011\000\000\000\377\377\377\377\001\000\000\000\000\000\000\000\007\001\027\000\000\002\010\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\007\000\000\007\372\000\007\007\007\007\007\007\006\000\000\000\000\022
artifact_prefix='./'; Test unit written to NrbfDecoderFuzzer-artifact-1
Base64: AAkAAAD/////AQAAAAAAAAAHARcAAAIIAAAAAAAAAAAABAAAAAAAAAAAAAcAAAf6AAcHBwcHBwYAAAAAEg==

break;
default:
throw new InvalidOperationException();
Copy link
Member

Choose a reason for hiding this comment

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

FWIW, InvalidOperationException is for when a method is invoked on an object and the object has state that doesn't support it. For example, calling Stream.Read when Stream.CanRead says false. The object is not in a state where you can call the method.

Many of yours are probably more likely InvalidDataException, where the default message is "Found invalid data while decoding."

Copy link
Member

Choose a reason for hiding this comment

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

Immo corrected me. Stream.Read when Stream.CanRead is false is NotSupportedException (you should have checked the property on the stream). InvalidOperationException is for controllable state that was controlled wrong, like an object where you have to set 3 properties before calling "DoStuff", and you called DoStuff without setting all 3.

But this is still most likely InvalidDataException, because the operation made sense to do, just the data that it read back was not internally consistent.

Copy link
Member Author

Choose a reason for hiding this comment

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

What I wanted to achieve is:

  • ensure all methods that parse enums throw SerializationException when they encounter invalid value (out of range, not in the spec)
  • assume that the above is not true and always handle all enum values in switch statements in explicit way, throw in the default case (so if there is a bug in parsing logic, we don't get undefined behavior but just an exception)

My initial idea was to use UnreachableException, but it's not part of NS2.0. I decided to use InvalidOperationException and I am open to changing it.

It's being tested by the Fuzzer which does not catch InvalidOperationException and treats it as a bug:

}
catch (SerializationException) { /* Reading from the stream encountered invalid NRBF data.*/ }
catch (NotSupportedException) { /* Reading from the stream encountered unsupported records */ }
catch (DecoderFallbackException) { /* Reading from the stream encountered an invalid UTF8 sequence. */ }
catch (EndOfStreamException) { /* The end of the stream was reached before reading SerializationRecordType.MessageEnd record. */ }
catch (IOException) { /* An I/O error occurred. */ }
}

(as shown in the fuzzer comments in this PR that has discovered places where it was missing)

… is always illegal to parse it and every switch needed to take this into account.

Now we reject those values at parse time and don't need to handle them later.

- In case of BinaryArray (NRBF 2.4.3.1):
 "If the BinaryTypeEnum value is Primitive, the PrimitiveTypeEnumeration
 value in AdditionalTypeInfo MUST NOT be Null (17) or String (18)."
- In case of MemberPrimitiveTyped (NRBF 2.5.1):
 "PrimitiveTypeEnum (1 byte): A PrimitiveTypeEnumeration
 value that specifies the Primitive Type of data that is being transmitted.
 This field MUST NOT contain a value of 17 (Null) or 18 (String)."
- In case of ArraySinglePrimitive (NRBF 2.4.3.3):
 "A PrimitiveTypeEnumeration value that identifies the Primitive Type
 of the items of the Array. The value MUST NOT be 17 (Null) or 18 (String)."
- In case of MemberTypeInfo (NRBF 2.3.1.2):
 "When the BinaryTypeEnum value is Primitive, the PrimitiveTypeEnumeration
 value in AdditionalInfo MUST NOT be Null (17) or String (18)."
@adamsitnik
Copy link
Member Author

@MihuBot fuzz NrbfDecoder

@adamsitnik adamsitnik merged commit 4cdbfdc into dotnet:main Sep 12, 2024
83 of 85 checks passed
adamsitnik added a commit to adamsitnik/runtime that referenced this pull request Sep 13, 2024
- Don't use `Debug.Fail` not followed by an exception (it may cause problems for apps deployed in Debug)
- avoid Int32 overflow
- throw for unexpected enum values just in case parsing has not rejected them
- validate the number of chars read by BinaryReader.ReadChars
- pass serialization record id to ex message
- return false rather than throw EndOfStreamException when provided Stream has not enough data
- don't restore the position in finally 
- limit max SZ and MD array length to Array.MaxLength, stop using LinkedList<T> as List<T> will be able to hold all elements now
- remove internal enum values that were always illegal, but needed to be handled everywhere
- Fix DebuggerDisplay
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
- Don't use `Debug.Fail` not followed by an exception (it may cause problems for apps deployed in Debug)
- avoid Int32 overflow
- throw for unexpected enum values just in case parsing has not rejected them
- validate the number of chars read by BinaryReader.ReadChars
- pass serialization record id to ex message
- return false rather than throw EndOfStreamException when provided Stream has not enough data
- don't restore the position in finally 
- limit max SZ and MD array length to Array.MaxLength, stop using LinkedList<T> as List<T> will be able to hold all elements now
- remove internal enum values that were always illegal, but needed to be handled everywhere
- Fix DebuggerDisplay
carlossanlop pushed a commit that referenced this pull request Sep 17, 2024
* [NRBF] Don't use Unsafe.As when decoding DateTime(s) (#105749)

* Add NrbfDecoder Fuzzer (#107385)

* [NRBF] Fix bugs discovered by the fuzzer (#107368)

* bug #1: don't allow for values out of the SerializationRecordType enum range

* bug #2: throw SerializationException rather than KeyNotFoundException when the referenced record is missing or it points to a record of different type

* bug #3: throw SerializationException rather than FormatException when it's being thrown by BinaryReader (or sth else that we use)

* bug #4: document the fact that IOException can be thrown

* bug #5: throw SerializationException rather than OverflowException when parsing the decimal fails

* bug #6: 0 and 17 are illegal values for PrimitiveType enum

* bug #7: throw SerializationException when a surrogate character is read (so far an ArgumentException was thrown)
# Conflicts:
#	src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs

* [NRBF] throw SerializationException when a surrogate character is read (#107532)

 (so far an ArgumentException was thrown)

* [NRBF] Fuzzing non-seekable stream input (#107605)

* [NRBF] More bug fixes (#107682)

- Don't use `Debug.Fail` not followed by an exception (it may cause problems for apps deployed in Debug)
- avoid Int32 overflow
- throw for unexpected enum values just in case parsing has not rejected them
- validate the number of chars read by BinaryReader.ReadChars
- pass serialization record id to ex message
- return false rather than throw EndOfStreamException when provided Stream has not enough data
- don't restore the position in finally 
- limit max SZ and MD array length to Array.MaxLength, stop using LinkedList<T> as List<T> will be able to hold all elements now
- remove internal enum values that were always illegal, but needed to be handled everywhere
- Fix DebuggerDisplay

* [NRBF] Comments and bug fixes from internal code review (#107735)

* copy comments and asserts from Levis internal code review

* apply Levis suggestion: don't store Array.MaxLength as a const, as it may change in the future

* add missing and fix some of the existing comments

* first bug fix: SerializationRecord.TypeNameMatches should throw ArgumentNullException for null Type argument

* second bug fix: SerializationRecord.TypeNameMatches should know the difference between SZArray and single-dimension, non-zero offset arrays (example: int[] and int[*])

* third bug fix: don't cast bytes to booleans

* fourth bug fix: don't cast bytes to DateTimes

* add one test case that I've forgot in previous PR
# Conflicts:
#	src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs

* [NRBF] Address issues discovered by Threat Model  (#106629)

* introduce ArrayRecord.FlattenedLength

* do not include invalid Type or Assembly names in the exception messages, as it's most likely corrupted/tampered/malicious data and could be used as a vector of attack.

* It is possible to have binary array records have an element type of array without being marked as jagged

---------

Co-authored-by: Buyaa Namnan <bunamnan@microsoft.com>
sirntar pushed a commit to sirntar/runtime that referenced this pull request Sep 30, 2024
- Don't use `Debug.Fail` not followed by an exception (it may cause problems for apps deployed in Debug)
- avoid Int32 overflow
- throw for unexpected enum values just in case parsing has not rejected them
- validate the number of chars read by BinaryReader.ReadChars
- pass serialization record id to ex message
- return false rather than throw EndOfStreamException when provided Stream has not enough data
- don't restore the position in finally 
- limit max SZ and MD array length to Array.MaxLength, stop using LinkedList<T> as List<T> will be able to hold all elements now
- remove internal enum values that were always illegal, but needed to be handled everywhere
- Fix DebuggerDisplay
@github-actions github-actions bot locked and limited conversation to collaborators Oct 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants