rainwolf / FGInt

Fast Gigantic Integers (FreePascal, Delphi)
13 stars 10 forks source link

Example of FGInt hang #1

Closed maalchemist closed 5 years ago

maalchemist commented 5 years ago

procedure FGInt_Hang; const S_x64 : string = #0#0#0'??a?°'#$A'??QYo?l'#7'???Epa?'#$00AD'nu??'#$16';@&?qE~'' u??I'#$C'R-ay?AIA±I_5U5w?'#3#$1B'xM??;«'; S_x32 : string = #0#0#0#0'Ku'#$16#$17'o-?u 9'#5#$11'e-a???a%'#$E'¶'#$14'BE1E'#$10'na'#$19' '; var gi_x64 : TFGInt; gi_x32 : TFGInt; gi_div : TFGInt; gi_mod : TFGInt; begin Base256StringToFGInt (S_x64, gi_x64); Base256StringToFGInt (S_x32, gi_x32); FGIntDivMod (gi_x64, gi_x32, gi_div, gi_mod); end;

rainwolf commented 5 years ago

The zero bytes at the front seem to be causing the problem, remove 1 from S_x32 and the hang doesn't occur. I could add some sanitization to Base256StringToFGInt and remove unnecessary null bytes first as a solution. Is that desirable?

maalchemist commented 5 years ago

This procedure hangs without strings and Base256StringToFGInt.

procedure FGInt_Hang; var gi_x64 : TFGInt; gi_x32 : TFGInt; gi_div : TFGInt; gi_mod : TFGInt; begin gi_x64.Sign := positive; SetLength (gi_x64.Number, 18); gi_x64.Number[0] := 17; gi_x64.Number[1] := 1061108651; gi_x64.Number[2] := 52131917; gi_x64.Number[3] := 1429567295; gi_x64.Number[4] := 2974375733; gi_x64.Number[5] := 1061243201; gi_x64.Number[6] := 1378705785; gi_x64.Number[7] := 1061112076; gi_x64.Number[8] := 2116493429; gi_x64.Number[9] := 641691973; gi_x64.Number[10] := 1058421568; gi_x64.Number[11] := 2909697343; gi_x64.Number[12] := 1164992831; gi_x64.Number[13] := 121585471; gi_x64.Number[14] := 1500462956; gi_x64.Number[15] := 171917137; gi_x64.Number[16] := 1063337904; gi_x64.Number[17] := 63;

gi_x32.Sign := positive; SetLength (gi_x32.Number, 9); gi_x32.Number[0] := 9; gi_x32.Number[1] := 1851857184; gi_x32.Number[2] := 1160856848; gi_x32.Number[3] := 246813762; gi_x32.Number[4] := 1061118245; gi_x32.Number[5] := 1697472831; gi_x32.Number[6] := 2688091409; gi_x32.Number[7] := 1865236341; gi_x32.Number[8] := 1265964567;

FGIntDivMod (gi_x64, gi_x32, gi_div, gi_mod); end;

rainwolf commented 5 years ago

This should be gi_x32.Number[0] := 8; I can't reproduce a hang in this case.

maalchemist commented 5 years ago

It seems upper zeroes cause hanging.

procedure FGInt_Hang; var gi_a : TFGInt; gi_b : TFGInt; gi_div : TFGInt; gi_mod : TFGInt; begin gi_a.Sign := positive; SetLength (gi_a.Number, 3); gi_a.Number[0] := 2; gi_a.Number[1] := 22222222; gi_a.Number[2] := 44444444;

gi_b.Sign := positive; SetLength (gi_b.Number, 3); gi_b.Number[0] := 2; gi_b.Number[1] := 11111111; gi_b.Number[2] := 0;

FGIntDivMod (gi_a, gi_b, gi_div, gi_mod); end;

rainwolf commented 5 years ago

I've tried to capture this by doing some sanitization after almost all operations so that this doesn't happen. Adding this check before an operation brings more overhead and reduces performance.

Does this state occur for you in a calculation or only when you convert base256 strings with leading null bytes?

maalchemist commented 5 years ago

I found this effect only while converting random strings to TFGInt.

rainwolf commented 5 years ago

You're fuzzing this? Cool.

I added extra sanitization to base256 conversions https://github.com/rainwolf/FGInt/commit/8b1a7fc48f87f61a2bf8aae50c80f2c5488e9160 Feel free to close this issue if this resolves it.

maalchemist commented 5 years ago

I've got compilation error at line #618.

This variant is better: while (length(temp) > 4) and (temp[1] = chr(0)) do delete(temp, 1, 1);

rainwolf commented 5 years ago

I should have tested before committing, sorry for wasting your time. It's fixed now.

maalchemist commented 5 years ago

OK