Recent

Author Topic: Access Violation in MaskUtils.FormatMaskText  (Read 448 times)

dmitryb

  • Jr. Member
  • **
  • Posts: 55
Access Violation in MaskUtils.FormatMaskText
« on: October 04, 2022, 05:20:07 am »
Hello

Lazarus 2.2.2 (rev lazarus_2_2_2-0-g537f43754c) FPC 3.2.2 x86_64-win64-win32/win64

When I call the next code

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   EditMask: String;
  4.   Result: String;
  5. begin
  6.   EditMask := '#-###-###-##-##;0;_';
  7.   Result := MaskUtils.FormatMaskText(EditMask, '');
  8. end;

I got an Access Violation in
function TMaskUtils.ApplyMaskToText(AValue: String): String;

I can't figure out if this is a feature or a bug.
« Last Edit: October 04, 2022, 05:21:45 am by dmitryb »

dje

  • Full Member
  • ***
  • Posts: 124
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #1 on: October 04, 2022, 07:15:19 am »
Looks like a bug to me around line 791 (MaskUtils.pas)
Code in question is:
Code: Pascal  [Select][+][-]
  1.       //fill text from left to rigth, skipping MaskLiterals
  2.       j := 1;
  3.       for i := 1 to FMaskLength do
  4.       begin
  5.         if not IsLiteral(FMask[i]) then
  6.         begin
  7.           if (AValue[j] = #32) then S[i]:= FSpaceChar else S[i] := AValue[j];  // <<< ERROR HERE
  8.           Inc(j);
  9.           if j > Length(AValue) then Break;
  10.         end;
  11.       end;
There is no check to see if AValue has zero length. The only check comes after Inc(J), which then breaks out the loop. There is some code below this that also doesn't check AValue for an EmptyStr.

Adding a length check fixes the issue. (Near the start of the function TMaskUtils.ApplyMaskToText)

Code: Pascal  [Select][+][-]
  1.   for I := 1 To FMaskLength do  S := S + ClearChar(I);
  2.   if Length(AValue) > 0 then // <<<< New Code here
  3.   if FMaskSave then    
« Last Edit: October 04, 2022, 07:18:47 am by dje »

Bart

  • Hero Member
  • *****
  • Posts: 4827
    • Bart en Mariska's Webstek
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #2 on: October 04, 2022, 10:14:24 am »
FWIW: the similar function in Lazarus' MasEdit unit returns " -   -   -  -  " (without the quotes of course).

And that is because GetCodePoint() returns '' if index is out of bounds, so it kind of works by accident there.

Bart
« Last Edit: October 04, 2022, 10:34:29 am by Bart »

Bart

  • Hero Member
  • *****
  • Posts: 4827
    • Bart en Mariska's Webstek
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #3 on: October 04, 2022, 11:00:46 am »
Reported and attached a patch in the bugtracker.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 4827
    • Bart en Mariska's Webstek
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #4 on: October 04, 2022, 01:28:47 pm »
And applied in #e736011c.

Bart

Josh

  • Hero Member
  • *****
  • Posts: 1024
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #5 on: October 04, 2022, 01:39:33 pm »
@Bart

Just looked at diff code. Question
Quote
else
  begin//FMaskSave = False
    if FTrimType = metTrimRight then
    if Value<>'' then
    begin
      //fill text from left to rigth, skipping MaskLiterals
      j := 1;
      for i := 1 to FMaskLength do

Should that be AValue not Value
Also would the result be set? Maybe
Code: Pascal  [Select][+][-]
  1.  If AValue=EmptyStr then Exit(EmptyStr);
« Last Edit: October 04, 2022, 05:03:18 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Bart

  • Hero Member
  • *****
  • Posts: 4827
    • Bart en Mariska's Webstek
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #6 on: October 04, 2022, 05:54:38 pm »
Just looked at diff code. Question

Should that be AValue not Value
Well spotted.
I sent in a fix for the fix to the bugtracker, hope it gets applied soon.

Also would the result be set? Maybe
Code: Pascal  [Select][+][-]
  1.  If AValue=EmptyStr then Exit(EmptyStr);
I didn't think so.
MaskUtils is a bit odd. Delphi uses it to do stuff with TMaskEdit.
When I came to Lazarus, TMaskEdit was utterly broken.
The stuff in MaskUtils could not be applied to TMaskEdit.
Hence over time I fixed TMaskEdit on Lazarus side.
The release cycle of fpc is too slow to wait for that (and at the time I did not feel comfortable to suggest any patches to the fpc team).

At that time TMaskEdit did not support UTF-8, it only worked with (lower) ASCII characters.
Since some years now, it does work with UTF-8 (well, it might choke on surrogate pairs).

So, after a while fpc's MaskUtils implementation behaved rather different than similar functions in TMaskEdit (the latter being heavily "black-box" tested against Delphi's behaviour).
Once noticed, I rewrote large parts of the MaskUtils unit, so that it would act like TMaskEdit would.
And since FormatMaskText (in Lazarus) calls a TMaskEdit function to accomplish this, and in Lazarus this function must not return an empty sting in this case, it was implemented in MaskUtils in the same way.

"Backporting" this to fpc meant that I had to change all the UTF-8 related code back to directly accessing strings by index. (You cannot use MaskUtils with UTF-8 encoded strings.)
And that's where the bug was introduced.

In the mean time I have safeguarded this particular bug in Lazarus as well, since it should not depend on an implementation detail of a helper function.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 4827
    • Bart en Mariska's Webstek
Re: Access Violation in MaskUtils.FormatMaskText
« Reply #7 on: October 04, 2022, 05:56:08 pm »
OK, the fix-for-the-fix has been applied as well.

Bart

 

TinyPortal © 2005-2018