-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
CBOR does not handle canonical NaN correctly #92080
Comments
Tagging subscribers to this area: @dotnet/area-system-formats-cbor, @bartonjs, @vcsjones Issue DetailsDescriptionSince System.Formats.Cbor adheres to RFC 7049, I don't believe The RFC states for canonical CBOR:
Similarly, Reproduction StepsTo reproduce the using System;
using System.Formats.Cbor;
CborWriter writer = new(CborConformanceMode.Canonical);
writer.WriteSingle(float.NaN);
Console.WriteLine(Convert.ToHexString(writer.Encode())); // Outputs F9FE00 To reproduce the byte[] canonical = Convert.FromHexString("F97E00");
byte[] nonCanonical = Convert.FromHexString("F9FE00");
CborReader canonicalReader = new CborReader(canonical, CborConformanceMode.Canonical);
CborReader nonCanonicalReader = new CborReader(nonCanonical, CborConformanceMode.Canonical);
Console.WriteLine(float.IsNaN(canonicalReader.ReadSingle()));
Console.WriteLine(float.IsNaN(nonCanonicalReader.ReadSingle())); Expected behavior
Actual behavior
Regression?No. Known WorkaroundsNo response ConfigurationHost: Using 7.0.0 of System.Formats.Cbor package. Other informationNo response
|
The issue with I would expect this to print the same thing: Half h = Half.Zero / Half.Zero;
Console.WriteLine(BitConverter.HalfToInt16Bits(h).ToString("X"));
Console.WriteLine(BitConverter.HalfToInt16Bits(Half.NaN).ToString("X")); But it prints
It seems that
|
@tannergooding do you have any thoughts on the NaN definition of |
Since I believe this is limited to System.Single/ |
@bartonjs I believe all of them are impacted since all of them get reduced to a 16-bit NaN, or Half. CborWriter writer = new(CborConformanceMode.Canonical);
writer.WriteHalf(Half.NaN);
Console.WriteLine(Convert.ToHexString(writer.Encode())); // Writes F9FE00
writer.Reset();
writer.WriteSingle(float.NaN);
Console.WriteLine(Convert.ToHexString(writer.Encode())); // Writes F9FE00
writer.Reset();
writer.WriteDouble(double.NaN);
Console.WriteLine(Convert.ToHexString(writer.Encode())); // Writes F9FE00
writer.Reset(); |
@vcsjones, the "canonical NaN" in hardware is implementation dependent. For xarch, it has historically been But, the represented value of |
Huh. I don't know of turning all three into Half.NaN is right. Maybe somewhere says it's allowed. But, https://www.rfc-editor.org/rfc/rfc7049#appendix-A says
One presumes those are for "when encoded as a half / float / double" |
I think it is for Canonical CBOR:
|
I ran into this issue when working on RISC-V CoreFX tests so I fixed it in PR #92934. Reviews welcome. |
RFC 7049 (CBOR) specifies "If NaN is an allowed value, it must always be represented as 0xf97e00". The only exception is when the user explicitly requests precision (FP size) is preserved. The problem occurred for x86, C# defines NaN as 0.0/0.0 which yields -NaN on x86 FP units, which gets encoded as 0xf9fe00. Fixes issue dotnet#92080
* Use canonical NaN representation for NaN values RFC 7049 (CBOR) specifies "If NaN is an allowed value, it must always be represented as 0xf97e00". The only exception is when the user explicitly requests precision (FP size) is preserved. The problem occurred for x86, C# defines NaN as 0.0/0.0 which yields -NaN on x86 FP units, which gets encoded as 0xf9fe00. Fixes issue #92080 * Use canonical CBOR (positive) NaN in WriteHalf * Put canonical CBOR NaNs into named constants * Add CborReader tests to verify the previously emitted negative NaN bit patterns are still readable as NaN. * Use only half-float canonical CBOR representation for NaNs NaNs only get written as 4 or 8 bytes only in CTAP2 mode, which requires to preserve all bits anyway. + review fixes
Description
Since System.Formats.Cbor adheres to RFC 7049, I don't believe
NaN
is handled correctly.The RFC states for canonical CBOR:
CborWriter
will encode it as 0xF9FE00.Similarly,
CborReader
will not throw for any non-canonically encodedNaN
.Reproduction Steps
To reproduce the
CborWriter
issue:To reproduce the
CborReader
issue:Expected behavior
CborWriter
encodesNaN
as 0xf97e00.CborReader
should throw when decoding aNaN
that is non-canonically encoded.Actual behavior
CborWriter
incorrectly encodesNaN
as 0xF9FE00 when in canonical encoding.CborReader
incorrectly permits all encodings ofNaN
when in canonical encoding.Regression?
No.
Known Workarounds
No response
Configuration
Host:
Version: 8.0.0-rc.1.23419.4
Architecture: arm64
Commit: 9295993
RID: osx-arm64
Using 7.0.0 of System.Formats.Cbor package.
Other information
No response
The text was updated successfully, but these errors were encountered: