Skip to content

Commit

Permalink
Adding range validation for all int / uint types
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfranblanco committed Jun 18, 2018
1 parent 561cab1 commit 62f605d
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 18 deletions.
41 changes: 25 additions & 16 deletions src/Nethereum.ABI/Encoders/IntTypeEncoder.cs
Expand Up @@ -10,15 +10,17 @@ public class IntTypeEncoder : ITypeEncoder
{
private readonly IntTypeDecoder intTypeDecoder;
private readonly bool _signed;

private readonly uint _size;


public IntTypeEncoder(bool signed)
public IntTypeEncoder(bool signed, uint size)
{
intTypeDecoder = new IntTypeDecoder();
_signed = signed;
_size = size;
}

public IntTypeEncoder() : this(false)
public IntTypeEncoder() : this(false, 256)
{

}
Expand Down Expand Up @@ -47,19 +49,7 @@ public byte[] EncodeInt(int value)

public byte[] EncodeInt(BigInteger value)
{

if(_signed && value > IntType.MAX_INT256_VALUE) throw new ArgumentOutOfRangeException(nameof(value),
$"Signed SmartContract integer must not exceed maximum value for int256: {IntType.MAX_INT256_VALUE.ToString()}. Current value is: {value}");

if (_signed && value < IntType.MIN_INT256_VALUE) throw new ArgumentOutOfRangeException(nameof(value),
$"Signed SmartContract integer must not be less than the minimum value for int256: {IntType.MIN_INT256_VALUE.ToString()}. Current value is: {value}");

if (!_signed && value > IntType.MAX_UINT256_VALUE) throw new ArgumentOutOfRangeException(nameof(value),
$"Unsigned SmartContract integer must not exceed maximum value for uint256: {IntType.MAX_UINT256_VALUE.ToString()}. Current value is: {value}");

if (!_signed && value < IntType.MIN_UINT_VALUE) throw new ArgumentOutOfRangeException(nameof(value),
$"Unsigned SmartContract integer must not be less than the minimum value of uint: {IntType.MIN_UINT_VALUE.ToString()}. Current value is: {value}");

ValidateValue(value);
//It should always be Big Endian.
var bytes = BitConverter.IsLittleEndian
? value.ToByteArray().Reverse().ToArray()
Expand Down Expand Up @@ -92,5 +82,24 @@ public byte[] EncodeInt(BigInteger value)

return ret;
}


public void ValidateValue(BigInteger value)
{
if (_signed && value > IntType.GetMaxSignedValue(_size)) throw new ArgumentOutOfRangeException(nameof(value),
$"Signed SmartContract integer must not exceed maximum value for int{_size}: {IntType.GetMaxSignedValue(_size).ToString()}. Current value is: {value}");

if (_signed && value < IntType.GetMinSignedValue(_size)) throw new ArgumentOutOfRangeException(nameof(value),
$"Signed SmartContract integer must not be less than the minimum value for int{_size}: {IntType.GetMinSignedValue(_size)}. Current value is: {value}");

if (!_signed && value > IntType.GetMaxUnSignedValue(_size)) throw new ArgumentOutOfRangeException(nameof(value),
$"Unsigned SmartContract integer must not exceed maximum value for uint{_size}: {IntType.GetMaxUnSignedValue(_size)}. Current value is: {value}");

if (!_signed && value < IntType.MIN_UINT_VALUE) throw new ArgumentOutOfRangeException(nameof(value),
$"Unsigned SmartContract integer must not be less than the minimum value of uint: {IntType.MIN_UINT_VALUE.ToString()}. Current value is: {value}");

}


}
}
47 changes: 45 additions & 2 deletions src/Nethereum.ABI/IntType.cs
@@ -1,3 +1,4 @@
using System;
using System.Numerics;
using Nethereum.ABI.Decoders;
using Nethereum.ABI.Encoders;
Expand All @@ -13,15 +14,57 @@ public class IntType : ABIType

public IntType(string name) : base(name)
{
Decoder = new IntTypeDecoder(IsSigned(name));
Encoder = new IntTypeEncoder(IsSigned(name));
Decoder = new IntTypeDecoder(IsSigned(CanonicalName));
Encoder = new IntTypeEncoder(IsSigned(CanonicalName), GetSize(CanonicalName));
}

private static bool IsSigned(string name)
{
return !name.ToLower().StartsWith("u");
}

public static BigInteger GetMaxSignedValue(uint size)
{
CheckIsValidAndThrow(size);
return BigInteger.Pow(2, (int)size - 1) - 1;
}

public static BigInteger GetMinSignedValue(uint size)
{
CheckIsValidAndThrow(size);
return BigInteger.Pow(-2, (int)size - 1);
}

public static BigInteger GetMaxUnSignedValue(uint size)
{
CheckIsValidAndThrow(size);
return BigInteger.Pow(2, (int)size) -1;
}

private static void CheckIsValidAndThrow(uint size)
{
if (!IsValidSize(size)) throw new ArgumentException("Invalid size for type int :" + size);
}

public static bool IsValidSize(uint size)
{
var divisible = (size % 8 == 0);
return divisible && size <= 256 && size >= 8;
}

private static uint GetSize(string name)
{
if (IsSigned(name))
{
return uint.Parse(name.Substring(3));
}
else
{
return uint.Parse(name.Substring(4));
}

}

public override string CanonicalName
{
get
Expand Down

0 comments on commit 62f605d

Please sign in to comment.