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

Add StrictUTF8 #1710

Merged
merged 5 commits into from
Jun 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions src/neo/IO/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace Neo.IO
{
Expand All @@ -15,7 +14,7 @@ public static class Helper
public static T AsSerializable<T>(this byte[] value, int start = 0) where T : ISerializable, new()
{
using (MemoryStream ms = new MemoryStream(value, start, value.Length - start, false))
using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
using (BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8))
{
return reader.ReadSerializable<T>();
}
Expand All @@ -27,7 +26,7 @@ public static class Helper
fixed (byte* pointer = value)
{
using UnmanagedMemoryStream ms = new UnmanagedMemoryStream(pointer, value.Length);
using BinaryReader reader = new BinaryReader(ms, Encoding.UTF8);
using BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8);
return reader.ReadSerializable<T>();
}
}
Expand All @@ -38,7 +37,7 @@ public static ISerializable AsSerializable(this byte[] value, Type type)
throw new InvalidCastException();
ISerializable serializable = (ISerializable)Activator.CreateInstance(type);
using (MemoryStream ms = new MemoryStream(value, false))
using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
using (BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8))
{
serializable.Deserialize(reader);
}
Expand All @@ -48,7 +47,7 @@ public static ISerializable AsSerializable(this byte[] value, Type type)
public static T[] AsSerializableArray<T>(this byte[] value, int max = 0x1000000) where T : ISerializable, new()
{
using (MemoryStream ms = new MemoryStream(value, false))
using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
using (BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8))
{
return reader.ReadSerializableArray<T>(max);
}
Expand All @@ -60,7 +59,7 @@ public static ISerializable AsSerializable(this byte[] value, Type type)
fixed (byte* pointer = value)
{
using UnmanagedMemoryStream ms = new UnmanagedMemoryStream(pointer, value.Length);
using BinaryReader reader = new BinaryReader(ms, Encoding.UTF8);
using BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8);
return reader.ReadSerializableArray<T>(max);
}
}
Expand Down Expand Up @@ -138,7 +137,7 @@ public static int GetVarSize<T>(this IReadOnlyCollection<T> value)

public static int GetVarSize(this string value)
{
int size = Encoding.UTF8.GetByteCount(value);
int size = Utility.StrictUTF8.GetByteCount(value);
return GetVarSize(size) + size;
}

Expand Down Expand Up @@ -166,7 +165,7 @@ public static byte[] ReadFixedBytes(this BinaryReader reader, int size)
public static string ReadFixedString(this BinaryReader reader, int length)
{
byte[] data = reader.ReadFixedBytes(length);
return Encoding.UTF8.GetString(data.TakeWhile(p => p != 0).ToArray());
return Utility.StrictUTF8.GetString(data.TakeWhile(p => p != 0).ToArray());
}

public static T[] ReadNullableArray<T>(this BinaryReader reader, int max = 0x1000000) where T : class, ISerializable, new()
Expand Down Expand Up @@ -218,13 +217,13 @@ public static ulong ReadVarInt(this BinaryReader reader, ulong max = ulong.MaxVa

public static string ReadVarString(this BinaryReader reader, int max = 0x1000000)
{
return Encoding.UTF8.GetString(reader.ReadVarBytes(max));
return Utility.StrictUTF8.GetString(reader.ReadVarBytes(max));
}

public static byte[] ToArray(this ISerializable value)
{
using (MemoryStream ms = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8))
using (BinaryWriter writer = new BinaryWriter(ms, Utility.StrictUTF8))
{
value.Serialize(writer);
writer.Flush();
Expand All @@ -235,7 +234,7 @@ public static byte[] ToArray(this ISerializable value)
public static byte[] ToByteArray<T>(this IReadOnlyCollection<T> value) where T : ISerializable
{
using (MemoryStream ms = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8))
using (BinaryWriter writer = new BinaryWriter(ms, Utility.StrictUTF8))
{
writer.Write(value);
writer.Flush();
Expand Down Expand Up @@ -263,7 +262,7 @@ public static void WriteFixedString(this BinaryWriter writer, string value, int
throw new ArgumentNullException(nameof(value));
if (value.Length > length)
throw new ArgumentException();
byte[] bytes = Encoding.UTF8.GetBytes(value);
byte[] bytes = Utility.StrictUTF8.GetBytes(value);
if (bytes.Length > length)
throw new ArgumentException();
writer.Write(bytes);
Expand Down Expand Up @@ -316,7 +315,7 @@ public static void WriteVarInt(this BinaryWriter writer, long value)

public static void WriteVarString(this BinaryWriter writer, string value)
{
writer.WriteVarBytes(Encoding.UTF8.GetBytes(value));
writer.WriteVarBytes(Utility.StrictUTF8.GetBytes(value));
}
}
}
4 changes: 2 additions & 2 deletions src/neo/IO/Json/JObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public static JObject Parse(ReadOnlySpan<byte> value, int max_nest = 100)

public static JObject Parse(string value, int max_nest = 100)
{
return Parse(Encoding.UTF8.GetBytes(value), max_nest);
return Parse(Utility.StrictUTF8.GetBytes(value), max_nest);
}

private static JObject Read(ref Utf8JsonReader reader, bool skipReading = false)
Expand Down Expand Up @@ -158,7 +158,7 @@ public override string ToString()

public string ToString(bool indented)
{
return Encoding.UTF8.GetString(ToByteArray(indented));
return Utility.StrictUTF8.GetString(ToByteArray(indented));
}

public virtual T TryGetEnum<T>(T defaultValue = default, bool ignoreCase = false) where T : Enum
Expand Down
4 changes: 2 additions & 2 deletions src/neo/SmartContract/ApplicationEngine.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ internal int GetInvocationCounter()
internal void RuntimeLog(byte[] state)
{
if (state.Length > MaxNotificationSize) throw new ArgumentException();
string message = Encoding.UTF8.GetString(state);
string message = Utility.StrictUTF8.GetString(state);
Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message));
}

internal void RuntimeNotify(byte[] eventName, Array state)
{
if (eventName.Length > MaxEventName) throw new ArgumentException();
if (!CheckItemForNotification(state)) throw new ArgumentException();
SendNotification(CurrentScriptHash, Encoding.UTF8.GetString(eventName), state);
SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state);
}

internal void SendNotification(UInt160 hash, string eventName, Array state)
Expand Down
4 changes: 2 additions & 2 deletions src/neo/SmartContract/ContractParametersContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public static ContractParametersContext FromJson(JObject json)

var verifiable = (IVerifiable)Activator.CreateInstance(type);
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(json["hex"].AsString()), false))
using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
using (BinaryReader reader = new BinaryReader(ms, Utility.StrictUTF8))
{
verifiable.DeserializeUnsigned(reader);
}
Expand Down Expand Up @@ -262,7 +262,7 @@ public JObject ToJson()
JObject json = new JObject();
json["type"] = Verifiable.GetType().FullName;
using (MemoryStream ms = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8))
using (BinaryWriter writer = new BinaryWriter(ms, Utility.StrictUTF8))
{
Verifiable.SerializeUnsigned(writer);
writer.Flush();
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize)
writer.WriteEndObject();
break;
case JsonTokenType.PropertyName:
writer.WritePropertyName(((ByteString)stack.Pop()).GetSpan());
writer.WritePropertyName(((ByteString)stack.Pop()).GetString());
break;
case Null _:
writer.WriteNullValue();
Expand Down
10 changes: 10 additions & 0 deletions src/neo/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.IO;
using System.Reflection;
using System.Text;

namespace Neo
{
Expand All @@ -19,6 +20,15 @@ public Logger()
}
}

public static Encoding StrictUTF8 { get; }

static Utility()
{
StrictUTF8 = (Encoding)Encoding.UTF8.Clone();
StrictUTF8.DecoderFallback = DecoderFallback.ExceptionFallback;
StrictUTF8.EncoderFallback = EncoderFallback.ExceptionFallback;
}

/// <summary>
/// Load configuration with different Environment Variable
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/neo/VM/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public static ReadOnlySpan<byte> GetSpan(this StackItem item)

public static string GetString(this StackItem item)
{
return Encoding.UTF8.GetString(item.GetSpan());
return Utility.StrictUTF8.GetString(item.GetSpan());
}

/// <summary>
Expand Down
12 changes: 12 additions & 0 deletions tests/neo.UnitTests/SmartContract/UT_JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Linq;
using System.Numerics;
using System.Text;

namespace Neo.UnitTests.SmartContract
{
Expand Down Expand Up @@ -48,6 +49,17 @@ public void JsonTest_Array()
Assert.AreEqual("[1,\"a==\",-1.3,null]", parsed.ToString());
}

[TestMethod]
public void JsonTest_Serialize_Map_Test()
{
var entry = new Map
{
[new byte[] { 0xC1 }] = 1,
[new byte[] { 0xC2 }] = 2,
};
Assert.ThrowsException<DecoderFallbackException>(() => JsonSerializer.Serialize(entry));
}

[TestMethod]
public void JsonTest_Bool()
{
Expand Down