Recent

Author Topic: Possible bug with range checking in StrUtils.IfThen function  (Read 2945 times)

BSaidus

  • Hero Member
  • *****
  • Posts: 600
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Possible bug with range checking in StrUtils.IfThen function
« on: December 07, 2023, 11:12:27 pm »
Hello.
Testing the following code in attached project raise an exception as shown in the screenshot.
The code
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     cbParentIfs: TComboBox;
  17.     Edit1: TEdit;
  18.     procedure Button1Click(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. uses
  31.   StrUtils
  32.   ;
  33.  
  34. CONST
  35.  CEth: array[0..4] of string = ('01','02','03','04','05');
  36.  
  37. {$R *.lfm}
  38.  
  39. { TForm1 }
  40.  
  41. procedure TForm1.Button1Click(Sender: TObject);
  42. var
  43.   lIndex: Integer;
  44. begin
  45.   lIndex := cbParentIfs.ItemIndex;
  46.   Edit1.Text := IfThen( lIndex>=1, CEth[lIndex-1], 'tralllla');
  47. end;
  48.  
  49. end.
  50.  
  51.  


PS: fpc 3.2.3 fixes, lazarus 2.2.7 fixes
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Bart

  • Hero Member
  • *****
  • Posts: 5469
    • Bart en Mariska's Webstek
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #1 on: December 07, 2023, 11:22:59 pm »
IIRC then all parameters of a function call will be evaluated.
So the expression CEth[lIndex-1] will be evaluated wether or not lIndex >= 1.

The fact that the function is called IfThen does not imply that boolean shortcutting is applied to it's parameter evaluation...

Bart

BSaidus

  • Hero Member
  • *****
  • Posts: 600
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #2 on: December 07, 2023, 11:25:59 pm »
IIRC then all parameters of a function call will be evaluated.
So the expression CEth[lIndex-1] will be evaluated wether or not lIndex >= 1.

The fact that the function is called IfThen does not imply that boolean shortcutting is applied to it's parameter evaluation...

Bart
Thanks for your answer.
Looking inside the code of IfThen in StrUtils, it do not looks (evaluate) the ATrue value if the condition is not sitisfied.
Code: Pascal  [Select][+][-]
  1. function IfThen(AValue: Boolean; const ATrue: string; const AFalse: string): string;
  2.  
  3. begin
  4.   if avalue then
  5.     result:=atrue
  6.   else
  7.     result:=afalse;
  8. end;  
  9.  

lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Fibonacci

  • Hero Member
  • *****
  • Posts: 612
  • Internal Error Hunter
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #3 on: December 07, 2023, 11:30:44 pm »
Your code didnt work for me, I had to use specialize:

Code: Pascal  [Select][+][-]
  1. Edit1.Text := specialize IfThen<String>(lIndex>=1, CEth[lIndex-1], 'tralllla');

FPC trunk, no problems, no range errors

BSaidus

  • Hero Member
  • *****
  • Posts: 600
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #4 on: December 07, 2023, 11:32:00 pm »
Your code didnt work for me, I had to use specialize:

Code: Pascal  [Select][+][-]
  1. Edit1.Text := specialize IfThen<String>(lIndex>=1, CEth[lIndex-1], 'tralllla');

FPC trunk, no problems, no range errors
Did you try to compile it in full debug mode ??
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Fibonacci

  • Hero Member
  • *****
  • Posts: 612
  • Internal Error Hunter
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #5 on: December 07, 2023, 11:32:56 pm »
Yes

Also managed to run your code this way

Code: Pascal  [Select][+][-]
  1. Edit1.Text := StrUtils.IfThen( lIndex>=1, CEth[lIndex-1], 'tralllla')

No errors, no crashes, TRUNK

BSaidus

  • Hero Member
  • *****
  • Posts: 600
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #6 on: December 07, 2023, 11:37:24 pm »
Strange, same problem with : Lazarus 3.0RC1 (rev fe49fef4) FPC 3.3.1 i386-win32-win32/win64
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Fibonacci

  • Hero Member
  • *****
  • Posts: 612
  • Internal Error Hunter
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #7 on: December 08, 2023, 12:01:17 am »
I compiled your project (.zip file) and well, there is range check error.

Ok, so both strings are known before the boolean is checked. Proof:

Code: Pascal  [Select][+][-]
  1. function nono: string;
  2. begin
  3.   showmessage('hello');
  4.   result := 'false';
  5. end;
  6.  
  7. procedure TForm1.Button1Click(Sender: TObject);
  8. begin
  9.   Edit1.Text := IfThen(false, nono, 'hi');
  10. end;

I guess since this is an array, or in case above a function, it cant be passed by ref.

Somehow when I created my form and just copy-pasted ur code there wasnt this error.

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #8 on: December 08, 2023, 01:08:06 am »
Hello.
Testing the following code in attached project raise an exception as shown in the screenshot.
The code
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     cbParentIfs: TComboBox;
  17.     Edit1: TEdit;
  18.     procedure Button1Click(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. uses
  31.   StrUtils
  32.   ;
  33.  
  34. CONST
  35.  CEth: array[0..4] of string = ('01','02','03','04','05');
  36.  
  37. {$R *.lfm}
  38.  
  39. { TForm1 }
  40.  
  41. procedure TForm1.Button1Click(Sender: TObject);
  42. var
  43.   lIndex: Integer;
  44. begin
  45.   lIndex := cbParentIfs.ItemIndex;
  46.   Edit1.Text := IfThen( lIndex>=1, CEth[lIndex-1], 'tralllla');
  47. end;
  48.  
  49. end.
  50.  
  51.  


PS: fpc 3.2.3 fixes, lazarus 2.2.7 fixes

The error is not inside the IfThen, but is before it is called, during the preparation of the stack for the function call.

https://forum.lazarus.freepascal.org/index.php/topic,59197.0.html
« Last Edit: December 08, 2023, 01:10:17 am by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Bart

  • Hero Member
  • *****
  • Posts: 5469
    • Bart en Mariska's Webstek
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #9 on: December 08, 2023, 10:00:46 am »
Looking inside the code of IfThen in StrUtils, it do not looks (evaluate) the ATrue value if the condition is not sitisfied.

That has nothing to do with it.
The parameters are evaluated at the time you call the function.
Say you have a function like this:
Code: Pascal  [Select][+][-]
  1. function foo(x,y: integer): integer;
Then you call it like
Code: Pascal  [Select][+][-]
  1. z := foo(1 div 0, 100);
Now, you would not be surprised that you get an exception (div by zero).
Suppose you also have a function like this:
Code: Pascal  [Select][+][-]
  1. function bar(a,b: integer): integer;
  2. begin
  3.   result := a div b;
  4. end;

And then you do this:
Code: Pascal  [Select][+][-]
  1.   z := foo(1, bar(1,0));
This will of course also raise an exception

Now this
Code: Pascal  [Select][+][-]
  1. function foo(b: boolean; x,y: integer): integer;
  2. ...
  3.   z:= foo(False, 1, bar(1,0));

This will crash regardless of the implementation of foo (so even if the imeplementation of foo is completely empty).

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 16194
  • Censorship about opinions does not belong here.
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #10 on: December 08, 2023, 10:18:29 am »
Your code didnt work for me, I had to use specialize:

Code: Pascal  [Select][+][-]
  1. Edit1.Text := specialize IfThen<String>(lIndex>=1, CEth[lIndex-1], 'tralllla');

FPC trunk, no problems, no range errors
That is because the generic ifthen is in sysutils not in strutils. I wrote the generic version.
If I smell bad code it usually is bad code and that includes my own code.

BSaidus

  • Hero Member
  • *****
  • Posts: 600
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #11 on: December 08, 2023, 02:13:39 pm »
Thank you for all the answers,
I'll use the
   IF ... THEN ... ELSE
Better for me.
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #12 on: December 08, 2023, 06:11:19 pm »
Thank you for all the answers,
I'll use the
   IF ... THEN ... ELSE
Better for me.

The difference is that if then else end works differently: first you evaluate the condition and then you jump to the true or the false branch, and execute only the one you jump to.

The ifthen instead evaluates all the 3 values supplied to it, then you enter into the function and return the true or the false one depending on the condition.

Except for the name which is similar, the two processes have nothing in common.
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Paolo

  • Hero Member
  • *****
  • Posts: 538
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #13 on: December 08, 2023, 07:48:46 pm »
So, the question mow is : "Ifthen" is useful for what ?

Bart

  • Hero Member
  • *****
  • Posts: 5469
    • Bart en Mariska's Webstek
Re: Possible bug with range checking in StrUtils.IfThen function
« Reply #14 on: December 08, 2023, 10:58:39 pm »
So, the question mow is : "Ifthen" is useful for what ?

So you can do something like
Code: Pascal  [Select][+][-]
  1. x := ifthen(a>b,c,d)
which requires less typing then the conventional
Code: Pascal  [Select][+][-]
  1.   if a>b then
  2.     x:=c
  3.   else
  4.     x:=d;

IMO it's for NARGS.
Make it less readable, so you, the programmer, look more like a wizard.

Bart

 

TinyPortal © 2005-2018