Skip to content

Commit f645ffa

Browse files
authored
ARROW-17223: [C#] DecimalArray incorrectly appends values greater than Decimal.MaxValue / 2 and less than Decimal.MinValue / 2 (apache#13732)
Authored-by: asmirnov82 <tlalok@inbox.ru> Signed-off-by: Eric Erhardt <eric.erhardt@microsoft.com>
1 parent 9a00777 commit f645ffa

3 files changed

Lines changed: 61 additions & 21 deletions

File tree

csharp/src/Apache.Arrow/DecimalUtility.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,33 +83,33 @@ internal static void GetBytes(decimal value, int precision, int scale, int byteW
8383
int[] decimalBits = decimal.GetBits(value);
8484
int decScale = (decimalBits[3] >> 16) & 0x7F;
8585
#if NETCOREAPP
86-
Span<byte> bigIntBytes = stackalloc byte[12];
86+
Span<byte> bigIntBytes = stackalloc byte[13];
8787

88-
for (int i = 0; i < 3; i++)
88+
Span<byte> intBytes = stackalloc byte[4];
89+
for (int i = 0; i < 3; i++)
90+
{
91+
int bit = decimalBits[i];
92+
if (!BitConverter.TryWriteBytes(intBytes, bit))
93+
throw new OverflowException($"Could not extract bytes from int {bit}");
94+
95+
for (int j = 0; j < 4; j++)
8996
{
90-
int bit = decimalBits[i];
91-
Span<byte> intBytes = stackalloc byte[4];
92-
if (!BitConverter.TryWriteBytes(intBytes, bit))
93-
throw new OverflowException($"Could not extract bytes from int {bit}");
94-
95-
for (int j = 0; j < 4; j++)
96-
{
97-
bigIntBytes[4 * i + j] = intBytes[j];
98-
}
97+
bigIntBytes[4 * i + j] = intBytes[j];
9998
}
100-
bigInt = new BigInteger(bigIntBytes);
99+
}
100+
bigInt = new BigInteger(bigIntBytes);
101101
#else
102-
byte[] bigIntBytes = new byte[12];
103-
for (int i = 0; i < 3; i++)
102+
byte[] bigIntBytes = new byte[13];
103+
for (int i = 0; i < 3; i++)
104+
{
105+
int bit = decimalBits[i];
106+
byte[] intBytes = BitConverter.GetBytes(bit);
107+
for (int j = 0; j < intBytes.Length; j++)
104108
{
105-
int bit = decimalBits[i];
106-
byte[] intBytes = BitConverter.GetBytes(bit);
107-
for (int j = 0; j < intBytes.Length; j++)
108-
{
109-
bigIntBytes[4 * i + j] = intBytes[j];
110-
}
109+
bigIntBytes[4 * i + j] = intBytes[j];
111110
}
112-
bigInt = new BigInteger(bigIntBytes);
111+
}
112+
bigInt = new BigInteger(bigIntBytes);
113113
#endif
114114

115115
if (value < 0)

csharp/test/Apache.Arrow.Tests/Decimal128ArrayTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,26 @@ public void AppendLargeDecimal()
9797
Assert.Equal(-large, array.GetValue(1));
9898
}
9999

100+
[Fact]
101+
public void AppendMaxAndMinDecimal()
102+
{
103+
// Arrange
104+
var builder = new Decimal128Array.Builder(new Decimal128Type(29, 0));
105+
106+
// Act
107+
builder.Append(Decimal.MaxValue);
108+
builder.Append(Decimal.MinValue);
109+
builder.Append(Decimal.MaxValue - 10);
110+
builder.Append(Decimal.MinValue + 10);
111+
112+
// Assert
113+
var array = builder.Build();
114+
Assert.Equal(Decimal.MaxValue, array.GetValue(0));
115+
Assert.Equal(Decimal.MinValue, array.GetValue(1));
116+
Assert.Equal(Decimal.MaxValue - 10, array.GetValue(2));
117+
Assert.Equal(Decimal.MinValue + 10, array.GetValue(3));
118+
}
119+
100120
[Fact]
101121
public void AppendFractionalDecimal()
102122
{

csharp/test/Apache.Arrow.Tests/Decimal256ArrayTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,26 @@ public void AppendLargeDecimal()
9797
Assert.Equal(-large, array.GetValue(1));
9898
}
9999

100+
[Fact]
101+
public void AppendMaxAndMinDecimal()
102+
{
103+
// Arrange
104+
var builder = new Decimal256Array.Builder(new Decimal256Type(29, 0));
105+
106+
// Act
107+
builder.Append(Decimal.MaxValue);
108+
builder.Append(Decimal.MinValue);
109+
builder.Append(Decimal.MaxValue - 10);
110+
builder.Append(Decimal.MinValue + 10);
111+
112+
// Assert
113+
var array = builder.Build();
114+
Assert.Equal(Decimal.MaxValue, array.GetValue(0));
115+
Assert.Equal(Decimal.MinValue, array.GetValue(1));
116+
Assert.Equal(Decimal.MaxValue - 10, array.GetValue(2));
117+
Assert.Equal(Decimal.MinValue + 10, array.GetValue(3));
118+
}
119+
100120
[Fact]
101121
public void AppendFractionalDecimal()
102122
{

0 commit comments

Comments
 (0)