diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs index bb0e6ee90f427b..7e810dae5e7bdd 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/PkcsHelpers.cs @@ -227,7 +227,20 @@ public static string OctetStringToUnicode(this byte[] octets) if (octets.Length < 2) return string.Empty; // .NET Framework compat: 0-length byte array maps to string.empty. 1-length byte array gets passed to Marshal.PtrToStringUni() with who knows what outcome. - string s = Encoding.Unicode.GetString(octets, 0, octets.Length - 2); + int end = octets.Length; + int endMinusOne = end - 1; + + // Truncate the string to before the first embedded \0 (probably the last two bytes). + for (int i = 0; i < endMinusOne; i += 2) + { + if (octets[i] == 0 && octets[i + 1] == 0) + { + end = i; + break; + } + } + + string s = Encoding.Unicode.GetString(octets, 0, end); return s; } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs index cf5fdba5960be1..07c192c0f7a855 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Pkcs9AttributeTests.cs @@ -177,6 +177,30 @@ public static void DocumentDescriptionFromRawData() Assert.Equal(s_OidDocumentDescription, oid); } + [Fact] + public static void DocumentDescriptionMissingTerminator() + { + byte[] rawData = "041e4d00790020004400650073006300720069007000740069006f006e002100".HexToByteArray(); + Pkcs9DocumentDescription p = new Pkcs9DocumentDescription(rawData); + Assert.Equal(rawData, p.RawData); + string cookedData = p.DocumentDescription; + Assert.Equal("My Description!", cookedData); + string oid = p.Oid.Value; + Assert.Equal(s_OidDocumentDescription, oid); + } + + [Fact] + public static void DocumentDescriptionEmbeddedTerminator() + { + byte[] rawData = "041e4d00790020004400650073006300720000007000740069006f006e000000".HexToByteArray(); + Pkcs9DocumentDescription p = new Pkcs9DocumentDescription(rawData); + Assert.Equal(rawData, p.RawData); + string cookedData = p.DocumentDescription; + Assert.Equal("My Descr", cookedData); + string oid = p.Oid.Value; + Assert.Equal(s_OidDocumentDescription, oid); + } + [Fact] public static void DocumentDescriptionFromCookedData() { @@ -226,6 +250,30 @@ public static void DocumentNameFromRawData() Assert.Equal(s_OidDocumentName, oid); } + [Fact] + public static void DocumentNameMissingTerminator() + { + byte[] rawData = "04104d00790020004e0061006d0065002100".HexToByteArray(); + Pkcs9DocumentName p = new Pkcs9DocumentName(rawData); + Assert.Equal(rawData, p.RawData); + string cookedData = p.DocumentName; + Assert.Equal("My Name!", cookedData); + string oid = p.Oid.Value; + Assert.Equal(s_OidDocumentName, oid); + } + + [Fact] + public static void DocumentNameEmbeddedTerminator() + { + byte[] rawData = "04104d00790020004e006100000065000000".HexToByteArray(); + Pkcs9DocumentName p = new Pkcs9DocumentName(rawData); + Assert.Equal(rawData, p.RawData); + string cookedData = p.DocumentName; + Assert.Equal("My Na", cookedData); + string oid = p.Oid.Value; + Assert.Equal(s_OidDocumentName, oid); + } + [Fact] public static void DocumentNameFromCookedData() {