* Patch from Sergei Gorelkin

* TXPathUnionNode.Evaluate: fixed two crashes. The object returned by
    TXPathVariable.AsNodeSet is owned by that TXPathVariable and should
    not be explicitly destroyed. Also TXPathVariable should not be
    released if its AsNodeSet result will be used later.

  * TXPathLocationPathNode.Evaluate/EvaluateStep:

    - fixed crash in axisFollowing case branch (caused by wrong variable
      being used in the loop).
    - rewrote axisPreceding branch so it builds the result node list in
      correct (document) order.
    - Fixed predicate match condition that was always evaluating as True.

  * TXPathScanner.ParseLocationPath: modified so it never returns nil.
    This fixes crash in cases when '/' or '//' are used otherwise than
    the whole expression (e.g. 'string(/)').

  * Replaced manual searching in TList by calls to IndexOf() in two
    places.

git-svn-id: trunk@12934 -
This commit is contained in:
michael 2009-03-20 20:09:55 +00:00
parent 36668a6ec5
commit 8cf5d9abf2

View File

@ -842,30 +842,25 @@ begin
try try
NodeSet := Op1Result.AsNodeSet; NodeSet := Op1Result.AsNodeSet;
NodeSet2 := Op2Result.AsNodeSet; NodeSet2 := Op2Result.AsNodeSet;
try for i := 0 to NodeSet2.Count - 1 do
for i := 0 to NodeSet2.Count - 1 do begin
begin DoAdd := True;
DoAdd := True; CurNode := NodeSet2[i];
CurNode := NodeSet2[i]; for j := 0 to NodeSet.Count - 1 do
for j := 0 to NodeSet.Count - 1 do if NodeSet[j] = CurNode then
if NodeSet[j] = CurNode then begin
begin DoAdd := False;
DoAdd := False; break;
break; end;
end; if DoAdd then
if DoAdd then NodeSet.Add(CurNode);
NodeSet.Add(CurNode);
end;
finally
NodeSet2.Free;
end; end;
finally finally
Op2Result.Release; Op2Result.Release;
end; end;
finally finally
Op1Result.Release; Result := Op1Result;
end; end;
Result := TXPathNodeSetVariable.Create(NodeSet);
end; end;
@ -979,9 +974,6 @@ var
StepNodes: TList; StepNodes: TList;
procedure DoNodeTest(Node: TDOMNode); procedure DoNodeTest(Node: TDOMNode);
var
i: Integer;
DoAdd: Boolean;
begin begin
case AStep.NodeTestType of case AStep.NodeTestType of
ntAnyPrincipal: ntAnyPrincipal:
@ -1002,14 +994,7 @@ var
if Node.NodeType <> PROCESSING_INSTRUCTION_NODE then if Node.NodeType <> PROCESSING_INSTRUCTION_NODE then
exit; exit;
end; end;
DoAdd := True; if StepNodes.IndexOf(Node) < 0 then
for i := 0 to StepNodes.Count - 1 do
if TDOMNode(StepNodes[i]) = Node then
begin
DoAdd := False;
break;
end;
if DoAdd then
StepNodes.Add(Node); StepNodes.Add(Node);
end; end;
@ -1030,12 +1015,12 @@ var
Node, Node2: TDOMNode; Node, Node2: TDOMNode;
Attr: TDOMNamedNodeMap; Attr: TDOMNamedNodeMap;
i, j: Integer; i, j: Integer;
DoAdd: Boolean;
NewContext: TXPathContext; NewContext: TXPathContext;
NewStepNodes: TNodeSet; NewStepNodes: TNodeSet;
Predicate: TXPathExprNode; Predicate: TXPathExprNode;
PredicateResult: TXPathVariable; PredicateResult: TXPathVariable;
TempList: TList;
begin begin
StepNodes := TList.Create; StepNodes := TList.Create;
@ -1090,7 +1075,7 @@ var
begin begin
DoNodeTest(Node2); DoNodeTest(Node2);
AddDescendants(Node2); AddDescendants(Node2);
Node := Node.NextSibling; Node2 := Node2.NextSibling;
end; end;
Node := Node.ParentNode; Node := Node.ParentNode;
until not Assigned(Node); until not Assigned(Node);
@ -1110,17 +1095,30 @@ var
DoNodeTest(AContext.ContextNode); DoNodeTest(AContext.ContextNode);
axisPreceding: axisPreceding:
begin begin
Node := AContext.ContextNode; TempList := TList.Create;
repeat try
Node2 := Node.PreviousSibling; Node := AContext.ContextNode;
while Assigned(Node2) do // build list of ancestors
while Assigned(Node) do
begin begin
DoNodeTest(Node2); TempList.Add(Node);
AddDescendants(Node2); Node := Node.ParentNode;
Node := Node.PreviousSibling;
end; end;
Node := Node.ParentNode; // then process it in reverse order
until not Assigned(Node); for i := TempList.Count-1 downto 1 do
begin
Node := TDOMNode(TempList[i]);
Node2 := Node.FirstChild;
while Assigned(Node2) and (Node2 <> TDOMNode(TempList[i-1])) do
begin
DoNodeTest(Node2);
AddDescendants(Node2);
Node2 := Node2.NextSibling;
end;
end;
finally
TempList.Free;
end;
end; end;
axisPrecedingSibling: axisPrecedingSibling:
begin begin
@ -1158,7 +1156,8 @@ var
try try
if (PredicateResult.InheritsFrom(TXPathNumberVariable) and if (PredicateResult.InheritsFrom(TXPathNumberVariable) and
(PredicateResult.AsNumber = j + 1)) or (PredicateResult.AsNumber = j + 1)) or
PredicateResult.AsBoolean then (not PredicateResult.InheritsFrom(TXPathNumberVariable) and
PredicateResult.AsBoolean) then
NewStepNodes.Add(Node); NewStepNodes.Add(Node);
finally finally
PredicateResult.Release; PredicateResult.Release;
@ -1190,14 +1189,7 @@ var
for i := 0 to StepNodes.Count - 1 do for i := 0 to StepNodes.Count - 1 do
begin begin
Node := TDOMNode(StepNodes[i]); Node := TDOMNode(StepNodes[i]);
DoAdd := True; if ResultNodeSet.IndexOf(Node) < 0 then
for j := 0 to ResultNodeSet.Count - 1 do
if TDOMNode(ResultNodeSet[j]) = Node then
begin
DoAdd := False;
break;
end;
if DoAdd then
ResultNodeSet.Add(Node); ResultNodeSet.Add(Node);
end; end;
end; end;
@ -1628,7 +1620,7 @@ end;
function TXPathScanner.ParseLocationPath: TXPathLocationPathNode; // [1] function TXPathScanner.ParseLocationPath: TXPathLocationPathNode; // [1]
var var
IsAbsolute, NeedColonColon: Boolean; IsAbsolute, NeedColonColon: Boolean;
FirstStep, CurStep, NextStep: TStep; CurStep, NextStep: TStep;
procedure NeedBrackets; procedure NeedBrackets;
begin begin
@ -1640,17 +1632,13 @@ var
begin begin
CurStep := nil; CurStep := nil;
Result := nil; IsAbsolute := False;
case CurToken of case CurToken of
tkSlash: // [2] AbsoluteLocationPath, first case tkSlash: // [2] AbsoluteLocationPath, first case
begin begin
if NextToken = tkEndOfStream then NextToken;
CurStep := TStep.Create(axisSelf, ntAnyNode) CurStep := TStep.Create(axisSelf, ntAnyNode);
else
if not (CurToken in
[tkDot, tkDotDot, tkAsterisk, tkAt, tkIdentifier, tkEndOfStream]) then
exit;
IsAbsolute := True; IsAbsolute := True;
end; end;
tkSlashSlash: // [10] AbbreviatedAbsoluteLocationPath tkSlashSlash: // [10] AbbreviatedAbsoluteLocationPath
@ -1659,12 +1647,12 @@ begin
IsAbsolute := True; IsAbsolute := True;
CurStep := TStep.Create(axisDescendantOrSelf, ntAnyNode); CurStep := TStep.Create(axisDescendantOrSelf, ntAnyNode);
end; end;
else
IsAbsolute := False;
end; end;
Result := TXPathLocationPathNode.Create(IsAbsolute);
Result.FFirstStep := CurStep;
// Parse [3] RelativeLocationPath // Parse [3] RelativeLocationPath
FirstStep := CurStep;
repeat repeat
if CurToken <> tkEndOfStream then if CurToken <> tkEndOfStream then
begin begin
@ -1672,7 +1660,7 @@ begin
if Assigned(CurStep) then if Assigned(CurStep) then
CurStep.NextStep := NextStep CurStep.NextStep := NextStep
else else
FirstStep := NextStep; Result.FFirstStep := NextStep;
CurStep := NextStep; CurStep := NextStep;
end; end;
@ -1804,7 +1792,7 @@ begin
end; end;
tkEndOfStream: // Enable support of "/" and "//" as path tkEndOfStream: // Enable support of "/" and "//" as path
else else
Error(SParserInvalidNodeTest); Exit;
end; end;
// Parse predicates // Parse predicates
@ -1833,9 +1821,6 @@ begin
else else
NextToken; // skip the slash NextToken; // skip the slash
until False; until False;
Result := TXPathLocationPathNode.Create(IsAbsolute);
Result.FFirstStep := FirstStep;
end; end;
function TXPathScanner.ParsePrimaryExpr: TXPathExprNode; // [15] function TXPathScanner.ParsePrimaryExpr: TXPathExprNode; // [15]