View Issue Details

IDProjectCategoryView StatusLast Update
0036141FPCPackagespublic2019-10-06 18:26
ReporterwpAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product VersionProduct Build 
Target VersionFixed in Version3.3.1 
Summary0036141: GetVal() in HTMLUtils returning wrong attribute value when '=' is surrounded by spaces
DescriptionThe function GetVal() in unit HTMLUtils (folder packages/chm/src) is a useful helper to extract the value of attributes in html tags. For example, when the tag is '<div id="1">' then GetVal(tag, 'id') should return the string '1' which is the value of the attribute 'id'.

However, this works only when no spaces are used around the '=' character.

  
Steps To ReproduceRun this program:

program Project1;
uses HtmlUtil;

begin
  WriteLn('"', GetVal('<div id="1">', 'id'), '"');
  WriteLn('"', GetVal('<div id ="2">', 'id'), '"'); // space before '='
  WriteLn('"', GetVal('<div id= "3">', 'id'), '"'); // space after '='
  WriteLn('"', GetVal('<div id = "4">', 'id'), '"'); // space before and after '='
end.

It will output
"1"
"1"
""
""

The first "1" is correct. The "" in the third and forth line demonstrate the issue that the attribute value is not detected when the '=' is surrounded by at least one space. The second "1" should be "", too - this is due to the fact that the function GetValFromNameVal() does not provide a valid return value when S = nil:

function GetValFromNameVal(namevalpair: string): string;
var
  P: Pchar;
  S: Pchar;
  C: Char;
begin
  P:= Pchar(namevalpair);
  S:= StrPos(P, '=');

  if S <> nil then
  begin
    ....
  end;
end;
      
The attached patch fixes this undefined return value issue as well as the main issue of this report, the spaces around the '=' character.

After application of the patch the output of above demo is as expected:
"1"
"2"
"3"
"4"

TagsNo tags attached.
Fixed in Revision43141
FPCOldBugId
FPCTarget3.2.0
Attached Files
  • htmlutil.pas.patch (1,060 bytes)
    Index: htmlutil.pas
    ===================================================================
    --- htmlutil.pas	(revision 43138)
    +++ htmlutil.pas	(working copy)
    @@ -119,11 +119,13 @@
         inc(S); // skip space
         P:= S;
     
    -    // Skip 
    +    // Skip tag name
         while not (P^ in ['=', ' ', '>', #0]) do
           inc(P);
     
    -    if (P^ = '=') then inc(P);
    +    // Skip spaces and '='
    +    while (P^ in ['=', ' ']) do
    +      inc(P);
         
         while not (P^ in [' ','>',#0]) do
         begin
    @@ -161,6 +163,8 @@
       S: Pchar;
       C: Char;
     begin
    +  Result := '';
    +
       P:= Pchar(namevalpair);
       S:= StrPos(P, '=');
     
    @@ -167,6 +171,7 @@
       if S <> nil then     
       begin
         inc(S); // skip equal
    +    while S^ = ' ' do inc(S);  // skip any spaces after =
         P:= S;  // set P to a character after =
     
         if (P^ in ['"','''']) then
    @@ -181,9 +186,7 @@
           inc(P);
     
         if (P <> S) then { Thanks to Dave Keighan (keighand@yahoo.com) }
    -      Result:= CopyBuffer(S, P - S) 
    -    else
    -      Result:= '';
    +      Result:= CopyBuffer(S, P - S); 
       end;
     end;
     
    
    htmlutil.pas.patch (1,060 bytes)

Activities

wp

2019-10-06 13:01

reporter  

htmlutil.pas.patch (1,060 bytes)
Index: htmlutil.pas
===================================================================
--- htmlutil.pas	(revision 43138)
+++ htmlutil.pas	(working copy)
@@ -119,11 +119,13 @@
     inc(S); // skip space
     P:= S;
 
-    // Skip 
+    // Skip tag name
     while not (P^ in ['=', ' ', '>', #0]) do
       inc(P);
 
-    if (P^ = '=') then inc(P);
+    // Skip spaces and '='
+    while (P^ in ['=', ' ']) do
+      inc(P);
     
     while not (P^ in [' ','>',#0]) do
     begin
@@ -161,6 +163,8 @@
   S: Pchar;
   C: Char;
 begin
+  Result := '';
+
   P:= Pchar(namevalpair);
   S:= StrPos(P, '=');
 
@@ -167,6 +171,7 @@
   if S <> nil then     
   begin
     inc(S); // skip equal
+    while S^ = ' ' do inc(S);  // skip any spaces after =
     P:= S;  // set P to a character after =
 
     if (P^ in ['"','''']) then
@@ -181,9 +186,7 @@
       inc(P);
 
     if (P <> S) then { Thanks to Dave Keighan (keighand@yahoo.com) }
-      Result:= CopyBuffer(S, P - S) 
-    else
-      Result:= '';
+      Result:= CopyBuffer(S, P - S); 
   end;
 end;
 
htmlutil.pas.patch (1,060 bytes)

wp

2019-10-06 13:03

reporter   ~0118373

Additional information: https://forum.lazarus.freepascal.org/index.php/topic,46971.msg335534.html#msg335534

Michael Van Canneyt

2019-10-06 13:33

administrator   ~0118375

Checked & applied, thank you very much !

wp

2019-10-06 18:26

reporter   ~0118383

Thank you, looks good. This report ranks high on the list of "fastest fixes ever"!

Issue History

Date Modified Username Field Change
2019-10-06 13:01 wp New Issue
2019-10-06 13:01 wp File Added: htmlutil.pas.patch
2019-10-06 13:03 wp Note Added: 0118373
2019-10-06 13:33 Michael Van Canneyt Assigned To => Michael Van Canneyt
2019-10-06 13:33 Michael Van Canneyt Status new => resolved
2019-10-06 13:33 Michael Van Canneyt Resolution open => fixed
2019-10-06 13:33 Michael Van Canneyt Fixed in Version => 3.3.1
2019-10-06 13:33 Michael Van Canneyt Fixed in Revision => 43141
2019-10-06 13:33 Michael Van Canneyt FPCTarget => 3.2.0
2019-10-06 13:33 Michael Van Canneyt Note Added: 0118375
2019-10-06 18:26 wp Status resolved => closed
2019-10-06 18:26 wp Note Added: 0118383