Recent

Author Topic: StrToInt not raising an error when string overflowing Integer  (Read 1372 times)

BrunoK

  • Hero Member
  • *****
  • Posts: 684
  • Retired programmer
StrToInt not raising an error when string overflowing Integer
« on: February 05, 2025, 03:07:10 pm »
FPC 3.2.2

Given the following program :
Code: Pascal  [Select][+][-]
  1. program PgmStrToInt;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. const
  7.    cStr: string = '355685667191548007';
  8.  
  9. var
  10.   vStr: String;
  11.   vInt: integer;
  12.   vInt64: int64;
  13.  
  14. begin
  15.   vStr := cStr + '8';                  // Force vStr as a non const string
  16.  
  17.   vInt64 := StrToInt64(vStr);               // OK
  18.   WriteLn(vInt64, ' ', HexStr(vInt64, 16)); // OK
  19.  
  20.   vInt := StrToInt(vStr); // Doesnt raise an error. Is  it OK ?
  21.   WriteLn(vInt, ' ', HexStr(vInt, 8)); // Seems to take only the lower 4 bytes
  22.  
  23.   WriteLn(TryStrToInt(vStr, vInt));    // Returns true (Should be false)
  24.  
  25.   ReadLn;
  26. end.

is there something wrong in it that prevents raising an error or returning FALSE in the TryStrToInt ?

(Edited Subject after Zvoni's comment, was erroneously labeled
  IntToStr not raising an error when string overflowing Integer )
« Last Edit: February 05, 2025, 04:09:06 pm by BrunoK »

Thaddy

  • Hero Member
  • *****
  • Posts: 16653
  • Kallstadt seems a good place to evict Trump to.
Re: IntToStr not raising an error when string overflowing Integer
« Reply #1 on: February 05, 2025, 03:27:17 pm »
cStr is not constant but static. Typed const is on by default.
Remove the type, then it is really a const and does what you think it should do.
« Last Edit: February 05, 2025, 03:29:18 pm by Thaddy »
But I am sure they don't want the Trumps back...

BrunoK

  • Hero Member
  • *****
  • Posts: 684
  • Retired programmer
Re: IntToStr not raising an error when string overflowing Integer
« Reply #2 on: February 05, 2025, 03:45:30 pm »
cStr is not constant but static. Typed const is on by default.
Remove the type, then it is really a const and does what you think it should do.
Whatever cStr / vStr are, the subject is about overflowed string to integer type conversion in StrToInt or TryStrToInt.

ALLIGATOR

  • Full Member
  • ***
  • Posts: 136
Re: IntToStr not raising an error when string overflowing Integer
« Reply #3 on: February 05, 2025, 03:53:29 pm »
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. begin
  7.   WriteLn(TryStrToInt('355685667191548007', argc));
  8.  
  9.   ReadLn;
  10. end.                                                
  11.  

FALSEFPC[main] x64, Win✅ OK
TRUEFPC 3.2.2 x64, Win🐞 BUG
FALSEFPC 3.2.2 x32, Win✅ OK
« Last Edit: February 05, 2025, 04:06:03 pm by ALLIGATOR »

Zvoni

  • Hero Member
  • *****
  • Posts: 2914
Re: IntToStr not raising an error when string overflowing Integer
« Reply #4 on: February 05, 2025, 03:54:23 pm »
Both/All (Try)StrToXXX use the compiler-intrinsic Val-Function under the hood, which in the second argument is a typeless Var-Argument for the Result

https://www.freepascal.org/docs-html/rtl/sysutils/strtoint.html
https://www.freepascal.org/docs-html/rtl/sysutils/trystrtoint.html

But:
As far as i understood the doc's,
StrToXXX only fails if it encounters a "character" it can't convert. It doesn't check a Range-Overflow.
My Guess:
StrToInt: "Hey, here's a String, convert it to integer, and stuff it into the Integer-Result-Variable. Call out if something goes wrong"
Val-Func: "Ah well. The Result-Variable only had that much bytes available. Not my Problem"

TryStrToXXX does check the Range (explicit mention in the docs)


btw: Why does the Thread-Title say "IntToStr" when we're talking about StrToInt?!?!
« Last Edit: February 05, 2025, 03:57:17 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

ALLIGATOR

  • Full Member
  • ***
  • Posts: 136
Re: IntToStr not raising an error when string overflowing Integer
« Reply #5 on: February 05, 2025, 04:08:45 pm »
@BrunoK

Why aren't you using the latest version of the compiler and the latest version of Lazarus?
3.2.2 is already very old

With FPCUpDeluxe - everything installs very easily

And bugs in 3.2.2 are often already fixed in [main]

ASerge

  • Hero Member
  • *****
  • Posts: 2389
Re: IntToStr not raising an error when string overflowing Integer
« Reply #6 on: February 05, 2025, 05:09:15 pm »
Why aren't you using the latest version of the compiler and the latest version of Lazarus?
It's obvious. The latest version of Lazarus - 3.8, the latest version of FPC - 3.2.2.
Larger versions are in development.

ALLIGATOR

  • Full Member
  • ***
  • Posts: 136
Re: IntToStr not raising an error when string overflowing Integer
« Reply #7 on: February 05, 2025, 05:28:25 pm »
It's obvious.
But not me

And that these versions are in development?
From my point of view they are now even more stable than the old “stable” “release” versions.
This is more true for FPC than Lazarus - because they are released more often, but FPC is already outdated, it has old bugs, no optimizations that are in the development version.

In general, the git version has only pluses and no minuses.

What are the disadvantages of the git version? Try to find them and I will tell you why it is not )

dsiders

  • Hero Member
  • *****
  • Posts: 1377
Re: IntToStr not raising an error when string overflowing Integer
« Reply #8 on: February 05, 2025, 05:51:29 pm »
It's obvious.
But not me

And that these versions are in development?
From my point of view they are now even more stable than the old “stable” “release” versions.
This is more true for FPC than Lazarus - because they are released more often, but FPC is already outdated, it has old bugs, no optimizations that are in the development version.

In general, the git version has only pluses and no minuses.

What are the disadvantages of the git version? Try to find them and I will tell you why it is not )

Given that half the time the FPC trunk version will not even compile... I think the answer is obvious.
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

ALLIGATOR

  • Full Member
  • ***
  • Posts: 136
Re: IntToStr not raising an error when string overflowing Integer
« Reply #9 on: February 05, 2025, 06:11:23 pm »
Given that half the time the FPC trunk version will not even compile... I think the answer is obvious.

Again, I don't understand to whom the answer is obvious?
For example, everything compiles fine for two years since I switched to the version under development, and I don't regret it. And I recommend it to everyone! The answer is obvious :P - use the version under development

Bart

  • Hero Member
  • *****
  • Posts: 5538
    • Bart en Mariska's Webstek
Re: StrToInt not raising an error when string overflowing Integer
« Reply #10 on: February 05, 2025, 10:06:35 pm »
OK, the behaviour for X86_64 is inconsistent with that for i386 (at least on Windows).
Notice that the internal working of Val() has changed in fpc main, and AFAIK these changes are not merged into 3.2 fixes.

Consider this simple example:
Code: Pascal  [Select][+][-]
  1. uses
  2.   SysUtils;
  3.  
  4. procedure TestValSignedTooHigh;
  5. var
  6.   I8: Int8;
  7.   I16: Int16;
  8.   I32: Int32;
  9.   I64: Int64;
  10.   Err: Integer;
  11. begin
  12.   {$R+}
  13.   writeln('TestValSignedTooHigh: RangeCheck=ON');
  14.   try
  15.     Val('128',I8,Err);
  16.     if Err<>0 then writeln('128: Err=',Err) else writeln('128 -> ',I8,' [???]')
  17.   except
  18.     on E: ERangeError do writeln('128: RangeCheckError !!');
  19.   end;
  20.   try
  21.     Val('32768',I16,Err);
  22.     if Err<>0 then writeln('32768: Err=',Err) else writeln('32768 -> ',I16,' [???]')
  23.   except
  24.     on E: ERangeError do writeln('32768: RangeCheckError !!');
  25.   end;
  26.   try
  27.     Val('2147483648',I32,Err);
  28.     if Err<>0 then writeln('2147483648: Err=',Err) else writeln('2147483648 -> ',I32,' [???]')
  29.   except
  30.     on E: ERangeError do writeln('2147483648: RangeCheckError !!');
  31.   end;
  32.   try
  33.     Val('9223372036854775808',I64,Err);
  34.     if Err<>0 then writeln('128: Err=',Err) else writeln('9223372036854775808 -> ',I64,' [???]')
  35.   except
  36.     on E: ERangeError do writeln('9223372036854775808: RangeCheckError !!');
  37.   end;
  38.  
  39.  
  40.   {$R-}
  41.   writeln('TestValSignedTooHigh: RangeCheck=OFF');
  42.   try
  43.     Val('128',I8,Err);
  44.     if Err<>0 then writeln('128: Err=',Err) else writeln('128 -> ',I8,' [???]')
  45.   except
  46.     on E: ERangeError do writeln('128: RangeCheckError !!');
  47.   end;
  48.   try
  49.     Val('32768',I16,Err);
  50.     if Err<>0 then writeln('32768: Err=',Err) else writeln('32768 -> ',I16,' [???]')
  51.   except
  52.     on E: ERangeError do writeln('32768: RangeCheckError !!');
  53.   end;
  54.   try
  55.     Val('2147483648',I32,Err);
  56.     if Err<>0 then writeln('2147483648: Err=',Err) else writeln('2147483648 -> ',I32,' [???]')
  57.   except
  58.     on E: ERangeError do writeln('2147483648: RangeCheckError !!');
  59.   end;
  60.   try
  61.     Val('9223372036854775808',I64,Err);
  62.     if Err<>0 then writeln('128: Err=',Err) else writeln('9223372036854775808 -> ',I64,' [???]')
  63.   except
  64.     on E: ERangeError do writeln('9223372036854775808: RangeCheckError !!');
  65.   end;
  66. end;
  67.  
  68. procedure TestValSignedTooLow;
  69. var
  70.   I8: Int8;
  71.   I16: Int16;
  72.   I32: Int32;
  73.   I64: Int64;
  74.   Err: Integer;
  75. begin
  76.   {$R+}
  77.   writeln('TestValSignedTooLow: RangeCheck=ON');
  78.   try
  79.     Val('-129',I8,Err);
  80.     if Err<>0 then writeln('-129: Err=',Err) else writeln('129 -> ',I8,' [???]')
  81.   except
  82.     on E: ERangeError do writeln('-129: RangeCheckError !!');
  83.   end;
  84.   try
  85.     Val('-32769',I16,Err);
  86.     if Err<>0 then writeln('-32769: Err=',Err) else writeln('-32769 -> ',I16,' [???]')
  87.   except
  88.     on E: ERangeError do writeln('-32768: RangeCheckError !!');
  89.   end;
  90.   try
  91.     Val('-2147483649',I32,Err);
  92.     if Err<>0 then writeln('-2147483649: Err=',Err) else writeln('-2147483649 -> ',I32,' [???]')
  93.   except
  94.     on E: ERangeError do writeln('-2147483649: RangeCheckError !!');
  95.   end;
  96.   try
  97.     Val('-9223372036854775809',I64,Err);
  98.     if Err<>0 then writeln('-9223372036854775809: Err=',Err) else writeln('-9223372036854775809 -> ',I64,' [???]')
  99.   except
  100.     on E: ERangeError do writeln('-9223372036854775809: RangeCheckError !!');
  101.   end;
  102.  
  103.   {$R-}
  104.   writeln('TestValSignedTooLow: RangeCheck=OFF');
  105.   try
  106.     Val('-129',I8,Err);
  107.     if Err<>0 then writeln('-129: Err=',Err) else writeln('129 -> ',I8,' [???]')
  108.   except
  109.     on E: ERangeError do writeln('-129: RangeCheckError !!');
  110.   end;
  111.   try
  112.     Val('-32769',I16,Err);
  113.     if Err<>0 then writeln('-32769: Err=',Err) else writeln('-32769 -> ',I16,' [???]')
  114.   except
  115.     on E: ERangeError do writeln('-32768: RangeCheckError !!');
  116.   end;
  117.   try
  118.     Val('-2147483649',I32,Err);
  119.     if Err<>0 then writeln('-2147483649: Err=',Err) else writeln('-2147483649 -> ',I32,' [???]')
  120.   except
  121.     on E: ERangeError do writeln('-2147483649: RangeCheckError !!');
  122.   end;
  123.   try
  124.     Val('-9223372036854775809',I64,Err);
  125.     if Err<>0 then writeln('-9223372036854775809: Err=',Err) else writeln('-9223372036854775809 -> ',I64,' [???]')
  126.   except
  127.     on E: ERangeError do writeln('-9223372036854775809: RangeCheckError !!');
  128.   end;
  129. end;
  130.  
  131.  
  132. begin
  133.   {$ifdef cpu32}
  134.   writeln('32-bit CPU');
  135.   {$endif}
  136.   {$ifdef cpu64}
  137.   writeln('64-bit CPU');
  138.   {$endif}
  139.   TestValSignedTooHigh;
  140.   writeln;
  141.   TestValSignedTooLow;
  142.   writeln;
  143. end.

On 32-bit:
Code: [Select]
32-bit CPU
TestValSignedTooHigh: RangeCheck=ON
128: Err=3
32768: Err=5
2147483648: Err=10
128: Err=19
TestValSignedTooHigh: RangeCheck=OFF
128: Err=3
32768: Err=5
2147483648: Err=10
128: Err=19

TestValSignedTooLow: RangeCheck=ON
-129: Err=4
-32769: Err=6
-2147483649: Err=11
-9223372036854775809: Err=20
TestValSignedTooLow: RangeCheck=OFF
-129: Err=4
-32769: Err=6
-2147483649: Err=11
-9223372036854775809: Err=20

All this as was designed: Val() should fail and set the error variable if conversion fails.
See the associated bugreport and the suggestion in to improve the documentation after these changes.

On 64-bit however:
Code: [Select]
64-bit CPU
TestValSignedTooHigh: RangeCheck=ON
128: RangeCheckError !!
32768: RangeCheckError !!
2147483648: RangeCheckError !!
128: Err=19
TestValSignedTooHigh: RangeCheck=OFF
128 -> -128 [???]
32768 -> -32768 [???]
2147483648 -> -2147483648 [???]
128: Err=19

TestValSignedTooLow: RangeCheck=ON
-129: RangeCheckError !!
-32768: RangeCheckError !!
-2147483649: RangeCheckError !!
-9223372036854775809: Err=20
TestValSignedTooLow: RangeCheck=OFF
129 -> 127 [???]
-32769 -> 32767 [???]
-2147483649 -> 2147483647 [???]
-9223372036854775809: Err=20

IIRC then there are seperate intrinsics for 64-bit Val()...

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5538
    • Bart en Mariska's Webstek
Re: StrToInt not raising an error when string overflowing Integer
« Reply #11 on: February 05, 2025, 10:23:22 pm »
Reported as Issue #41136.

[ETA]Seems to be resolved in a more recent version of fpc main[/ETA]

Bart
« Last Edit: February 05, 2025, 11:54:05 pm by Bart »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5906
  • Compiler Developer
Re: IntToStr not raising an error when string overflowing Integer
« Reply #12 on: February 06, 2025, 10:31:39 pm »
In general, the git version has only pluses and no minuses.

FPC main has significant problems with unexpected recompilations in more complex unit scenarios since last summer and thus is not even remotely ready for a release.

ALLIGATOR

  • Full Member
  • ***
  • Posts: 136
Re: IntToStr not raising an error when string overflowing Integer
« Reply #13 on: February 07, 2025, 03:17:25 am »
FPC main has significant problems with unexpected recompilations in more complex unit scenarios since last summer and thus is not even remotely ready for a release.

I don't see a big problem)
I'm an amateur, not a professional programmer and I have very little software, it doesn't affect me - so I use FPC [main][head].
For those who are critical - they can use FPC[main][881eb0fab5bea2ca1cc283d2aa76d75a1904458e] - as a previous commit before introducing tasks (https://gitlab.com/freepascal.org/fpc/source/-/commit/5298e25c8420f43587d174c6d549f688f514a04a), as far as I understand - so far there is a problem with them.

Besides, if more people use [main][head] - they will find more bugs, there will be better testing, there will be more test cases and maybe even someone will find a suitable, convenient and minimal example that easily replicates the problem with tasks )
In other words, the more you use FPC[main] - the more you help the development of FPC and the release of the new long awaited version )

but again, if this problem bothers anyone, you can always use FPC[main][good commit] and it will be better than good old 3.2.2 )

« Last Edit: February 07, 2025, 03:19:43 am by ALLIGATOR »

 

TinyPortal © 2005-2018