PosSetEx bug lazarus / 64-FPC development ---------------------------------------------------------------------- dje · 2022-12-09 04:15 Im using FPC 3.2.2. The code for PosSetEx doesn't quite match the code for PosEx I checked the code for PosSetEx which is identical to my installed version: https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/rtl- objpas/src/inc/strutils.pp So, the issue is the following two lines "should" return the same value: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   WriteLn(PosEx('p', 'freepascal', -1000));  WriteLn(PosSetEx(['p'], 'freepascal', -1000)); Except I get: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 0-891 The PosEx function includes this code which returns 0 for an Offset outside the string length: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if (Offset < 1) or (Offset > SizeUInt(Length(S))) then exit(0);   While the PosSetEx function only checks the upper bounds: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i    i:=length(s); j:=count;   if j>i then begin result:=0; exit; end; I would think the PosSetEx should also check the lower bounds. ie: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  if (j < 1) or (j>i) then begin result:=0; exit; end; ---------------------------------------------------------------------- marcov · 2022-12-09 10:32 I wonder if it really useful to spend the two cycles for obvious wrong input. ---------------------------------------------------------------------- Bart · 2022-12-09 14:37 If I understand the code correctlyt then, if count < 0 then j will become count (negative) and s[j] will be accessed, but the index (j) is out of bounds. That may potentially be dangerous. Bart ---------------------------------------------------------------------- KodeZwerg · 2022-12-09 14:52 Quote from: marcov on December 09, 2022, 11:32:59 amI wonder if it really useful to spend the two cycles for obvious wrong input. But it is a bug, I agree to OP. Wrong input or not. When I do read the documentation it should return 0. QuoteDescription PosSetEx returns the position in s of the first found character which is in the set c, and starts searching at character position Count. If none of the characters in c is found in s, then 0 is returned. Errors None.In his example it returns a very strange result, dont you think that too? I mean it find something but probably not at that negative adress ---------------------------------------------------------------------- marcov · 2022-12-09 15:25 Quote from: KodeZwerg on December 09, 2022, 03:52:04 pmQuote from: marcov on December 09, 2022, 11:32:59 amI wonder if it really useful to spend the two cycles for obvious wrong input. But it is a bug, However, is it a code or a documentation bug ? When I wrote it, I definitely didn't consider negative input logical, as it serves no purpose whatsoever. ---------------------------------------------------------------------- Bart · 2022-12-09 15:41 If you consider it a documentation issue, then it should be stated that the behavoiur is undefined with values for count <= 0. To me it would make more sense to have it behave lik PosEx with invalid count parameters. Bart ---------------------------------------------------------------------- dje · 2022-12-09 15:57 RPosEx is interesting. It handles negitive offsets, but in a strange way. Offsets are cardinal, so, neg values are treated as positive, and discarded with the max bound check. But, zero offset are converted to pointers: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i      p:=@s[offs];     p2:=@s[1]; And then discarded via this code since @s[0] < @s[1] Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i while (p2<=p) So, that means PosEx and RPosEx handle zero and neg numbers by returning zero. Although, RPosEx looks more like an accidental side effect. ---------------------------------------------------------------------- marcov · 2022-12-09 16:30 It is. RPos and the set variant are based on older Modula2 routines, where the main type (Cardinal) is unsigned. Maybe posex got fixed for some Delphi compatibility measure, but for non delphi compat routines, I think it is wiser to simply adapt the documentation. ---------------------------------------------------------------------- KodeZwerg · 2022-12-09 16:40 Quote from: marcov on December 09, 2022, 04:25:00 pmI definitely didn't consider negative input logicalAlways await the unexpected else we wouldn't have this thread  Quote from: marcov on December 09, 2022, 04:25:00 pmas it serves no purpose whatsoever.Just because I say my opinion, it is a bug, does not mean that I am not on your side, I fully agree to you that it is ill to call it that way. About where that bug might be, I am clueless since I am not the inventor of that routine. Whatever he/she might have thought it should do, it should be in balance with it's documentation. So one of them is wrong, my personal opinion, it is the method since negative index for a string can never be good. ---------------------------------------------------------------------- dje · 2022-12-09 16:59 The Delphi doc's for PosEx state: QuoteIf SubStr is not found or Offset is invalid (greater than the length of S or less than 1), then the result is 0. https://docwiki.emb arcadero.com/Libraries/Sydney/en/System.StrUtils.PosEx I understand that PosSetEx is not in Delphi, but shouldn't it follow the same logic as PosEx?. On, a side note, I was hoping one day the function RPosSetEx would be added to match the RPosEx ---------------------------------------------------------------------- dje · 2022-12-09 17:06 O, BTW. This thread was started while I'm re-coding some of these routines for HighSpeed Pascal on the Atari ST. I wanted my routines to be the same as FPC,  hence why I'm looking at these boundary cases. Another interesting note is: HighSpeed Pascal returns 1 for Pos(EmptyStr, 'Pascal') Ie: Its opinion is an empty string can be found at the start of all strings. Wow. I guess standards matter. ---------------------------------------------------------------------- Bart · 2022-12-09 17:41 Quote from: marcov on December 09, 2022, 05:30:26 pmMaybe posex got fixed for some Delphi compatibility measure, but for non delphi compat routines, I think it is wiser to simply adapt the documentation. So, we really want this? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode objfpc}{$h+}uses  StrUtils;var  Res: SizeInt;begin  Res := PosSetEx(['1'], '2', Low(Integer));  writeln('Res = ',Res);end. Code: [Select]C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas Free Pascal Compiler version 3.3.1 [2022/10/11] for i386 Copyright (c) 1993-2022 by Florian Klaempfl and others Target OS: Win32 for i386 Compiling test.pas Linking test.exe 10 lines compiled, 0.5 sec, 69808 bytes code, 4420 bytes data C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test An unhandled exception occurred at $0040D7FF: EAccessViolation: Access violation   $0040D7FF Bart