Browse Source

Fixed an FPC Bug on ARM

Ugochukwu Mmaduekwe 7 years ago
parent
commit
4eeb5fbe66

+ 0 - 1
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -34,7 +34,6 @@ uses
   TestFramework,
 {$ENDIF FPC}
   Generics.Collections,
-  ClpArrayUtils,
   ClpECNamedCurveTable,
   ClpCryptoLibTypes,
   ClpSecureRandom,

+ 8 - 8
CryptoLib/src/Math/Raw/ClpNat.pas

@@ -1268,10 +1268,10 @@ begin
   while (I >= 0) do
   begin
     next := x[xOff + I];
-    z[zOff + I] := (next shr (bits)) or (c shl (-bits));
+    z[zOff + I] := (next shr (bits)) or (TBits.NegativeLeftShift32(c, -bits));
     c := next;
   end;
-  Result := c shl (-bits);
+  Result := TBits.NegativeLeftShift32(c, -bits);
 end;
 
 class function TNat.ShiftDownBits(len: Int32; z: TCryptoLibUInt32Array;
@@ -1288,11 +1288,11 @@ begin
   while (I >= 0) do
   begin
     next := z[I];
-    z[I] := (next shr bits) or (c shl (-bits));
+    z[I] := (next shr bits) or (TBits.NegativeLeftShift32(c, -bits));
     c := next;
     System.Dec(I);
   end;
-  Result := c shl (-bits);
+  Result := TBits.NegativeLeftShift32(c, -bits);
 end;
 
 class function TNat.ShiftDownBits(len: Int32; x: TCryptoLibUInt32Array;
@@ -1309,11 +1309,11 @@ begin
   while (I >= 0) do
   begin
     next := x[I];
-    z[I] := (next shr bits) or (c shl (-bits));
+    z[I] := (next shr bits) or (TBits.NegativeLeftShift32(c, -bits));
     c := next;
     System.Dec(I);
   end;
-  Result := c shl (-bits);
+  Result := TBits.NegativeLeftShift32(c, -bits);
 end;
 
 class function TNat.ShiftDownBits(len: Int32; z: TCryptoLibUInt32Array;
@@ -1330,11 +1330,11 @@ begin
   while (I >= 0) do
   begin
     next := z[zOff + I];
-    z[zOff + I] := (next shr bits) or (c shl (-bits));
+    z[zOff + I] := (next shr bits) or (TBits.NegativeLeftShift32(c, -bits));
     c := next;
     System.Dec(I);
   end;
-  Result := c shl (-bits);
+  Result := TBits.NegativeLeftShift32(c, -bits);
 end;
 
 class function TNat.ShiftDownWord(len: Int32; z: TCryptoLibUInt32Array;

+ 27 - 0
CryptoLib/src/Utils/ClpBits.pas

@@ -62,6 +62,27 @@ type
 
     class function Asr64(Value: int64; ShiftBits: Int32): int64; static; inline;
 
+    /// <summary>
+    /// Calculates Negative Left Shift. This was implemented to circumvent a
+    /// bug in FPC ARM when performing Shift Left on certain values with a
+    /// Negative Shift Bits. For example UInt32(1948415963) shl Int32(-2)
+    /// should give "3221225472" but in FPC ARM, It gives "0". In some C
+    /// Compilers, this is "Undefined"
+    /// </summary>
+    /// <param name="ShiftBits">
+    /// Integer, number of bits to shift value to. This Number <b>Must be
+    /// Negative</b>
+    /// </param>
+    /// <param name="value">
+    /// UInt32 value to compute 'NLS' on.
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
+
+    class function NegativeLeftShift32(Value: UInt32; ShiftBits: Int32): UInt32;
+      static; inline;
+
     class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32; overload;
       static; inline;
     class function RotateLeft64(a_value: UInt64; a_n: Int32): UInt64; overload;
@@ -191,6 +212,12 @@ begin
 {$ENDIF FPC}
 end;
 
+class function TBits.NegativeLeftShift32(Value: UInt32;
+  ShiftBits: Int32): UInt32;
+begin
+  Result := Value shl (32 + ShiftBits);
+end;
+
 class function TBits.RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
 begin
 {$IFDEF DEBUG}