1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fxjs/xfa/cfxjse_resolveprocessor.h"
8 
9 #include <algorithm>
10 #include <utility>
11 #include <vector>
12 
13 #include "core/fxcrt/fx_extension.h"
14 #include "fxjs/xfa/cfxjse_engine.h"
15 #include "fxjs/xfa/cfxjse_nodehelper.h"
16 #include "fxjs/xfa/cfxjse_value.h"
17 #include "fxjs/xfa/cjx_object.h"
18 #include "third_party/base/stl_util.h"
19 #include "xfa/fxfa/parser/cxfa_document.h"
20 #include "xfa/fxfa/parser/cxfa_localemgr.h"
21 #include "xfa/fxfa/parser/cxfa_node.h"
22 #include "xfa/fxfa/parser/cxfa_object.h"
23 #include "xfa/fxfa/parser/cxfa_occur.h"
24 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
25 #include "xfa/fxfa/parser/xfa_utils.h"
26 
27 namespace {
28 
DoPredicateFilter(v8::Isolate * pIsolate,WideString wsCondition,size_t iFoundCount,CFXJSE_ResolveNodeData * pRnd)29 void DoPredicateFilter(v8::Isolate* pIsolate,
30                        WideString wsCondition,
31                        size_t iFoundCount,
32                        CFXJSE_ResolveNodeData* pRnd) {
33   ASSERT(iFoundCount == pRnd->m_Objects.size());
34   WideString wsExpression;
35   CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown;
36   if (wsCondition.First(2).EqualsASCII(".[") && wsCondition.Back() == L']')
37     eLangType = CXFA_Script::Type::Formcalc;
38   else if (wsCondition.First(2).EqualsASCII(".(") && wsCondition.Back() == L')')
39     eLangType = CXFA_Script::Type::Javascript;
40   else
41     return;
42 
43   wsExpression = wsCondition.Substr(2, wsCondition.GetLength() - 3);
44   for (size_t i = iFoundCount; i > 0; --i) {
45     auto pRetValue = std::make_unique<CFXJSE_Value>();
46     bool bRet =
47         pRnd->m_pSC->RunScript(eLangType, wsExpression.AsStringView(),
48                                pRetValue.get(), pRnd->m_Objects[i - 1].Get());
49     if (!bRet || !pRetValue->ToBoolean(pIsolate))
50       pRnd->m_Objects.erase(pRnd->m_Objects.begin() + i - 1);
51   }
52 }
53 
54 }  // namespace
55 
CFXJSE_ResolveProcessor()56 CFXJSE_ResolveProcessor::CFXJSE_ResolveProcessor()
57     : m_pNodeHelper(std::make_unique<CFXJSE_NodeHelper>()) {}
58 
59 CFXJSE_ResolveProcessor::~CFXJSE_ResolveProcessor() = default;
60 
Resolve(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)61 bool CFXJSE_ResolveProcessor::Resolve(v8::Isolate* pIsolate,
62                                       CFXJSE_ResolveNodeData& rnd) {
63   if (!rnd.m_CurObject)
64     return false;
65 
66   if (!rnd.m_CurObject->IsNode()) {
67     if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) {
68       return ResolveForAttributeRs(rnd.m_CurObject.Get(), rnd,
69                                    rnd.m_wsName.AsStringView());
70     }
71     return false;
72   }
73   if (rnd.m_dwStyles & XFA_RESOLVENODE_AnyChild)
74     return ResolveAnyChild(pIsolate, rnd);
75 
76   if (rnd.m_wsName.GetLength()) {
77     wchar_t wch = rnd.m_wsName[0];
78     switch (wch) {
79       case '$':
80         return ResolveDollar(pIsolate, rnd);
81       case '!':
82         return ResolveExcalmatory(pIsolate, rnd);
83       case '#':
84         return ResolveNumberSign(pIsolate, rnd);
85       case '*':
86         return ResolveAsterisk(rnd);
87       // TODO(dsinclair): We could probably remove this.
88       case '.':
89         return ResolveAnyChild(pIsolate, rnd);
90       default:
91         break;
92     }
93   }
94   if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) {
95     rnd.m_Objects.emplace_back(rnd.m_pSC->GetThisObject());
96     return true;
97   }
98   if (rnd.m_CurObject->GetElementType() == XFA_Element::Xfa) {
99     CXFA_Object* pObjNode =
100         rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName);
101     if (pObjNode) {
102       rnd.m_Objects.emplace_back(pObjNode);
103     } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) {
104       rnd.m_Objects.emplace_back(rnd.m_CurObject.Get());
105     } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) &&
106                ResolveForAttributeRs(rnd.m_CurObject.Get(), rnd,
107                                      rnd.m_wsName.AsStringView())) {
108       return true;
109     }
110     if (!rnd.m_Objects.empty())
111       FilterCondition(pIsolate, rnd.m_wsCondition, &rnd);
112 
113     return !rnd.m_Objects.empty();
114   }
115   if (!ResolveNormal(pIsolate, rnd) && rnd.m_uHashName == XFA_HASHCODE_Xfa)
116     rnd.m_Objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
117 
118   return !rnd.m_Objects.empty();
119 }
120 
ResolveAnyChild(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)121 bool CFXJSE_ResolveProcessor::ResolveAnyChild(v8::Isolate* pIsolate,
122                                               CFXJSE_ResolveNodeData& rnd) {
123   CXFA_Node* pParent = ToNode(rnd.m_CurObject.Get());
124   if (!pParent)
125     return false;
126 
127   WideStringView wsName = rnd.m_wsName.AsStringView();
128   WideString wsCondition = rnd.m_wsCondition;
129   const bool bClassName = !wsName.IsEmpty() && wsName[0] == '#';
130   CXFA_Node* const pChild =
131       bClassName
132           ? pParent->GetOneChildOfClass(wsName.Last(wsName.GetLength() - 1))
133           : pParent->GetOneChildNamed(wsName);
134   if (!pChild)
135     return false;
136 
137   if (wsCondition.IsEmpty()) {
138     rnd.m_Objects.emplace_back(pChild);
139     return true;
140   }
141 
142   std::vector<CXFA_Node*> nodes;
143   for (const auto& pObject : rnd.m_Objects)
144     nodes.push_back(pObject->AsNode());
145 
146   std::vector<CXFA_Node*> siblings = pChild->GetSiblings(bClassName);
147   nodes.insert(nodes.end(), siblings.begin(), siblings.end());
148   rnd.m_Objects =
149       std::vector<UnownedPtr<CXFA_Object>>(nodes.begin(), nodes.end());
150   FilterCondition(pIsolate, wsCondition, &rnd);
151   return !rnd.m_Objects.empty();
152 }
153 
ResolveDollar(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)154 bool CFXJSE_ResolveProcessor::ResolveDollar(v8::Isolate* pIsolate,
155                                             CFXJSE_ResolveNodeData& rnd) {
156   WideString wsName = rnd.m_wsName;
157   WideString wsCondition = rnd.m_wsCondition;
158   int32_t iNameLen = wsName.GetLength();
159   if (iNameLen == 1) {
160     rnd.m_Objects.emplace_back(rnd.m_CurObject.Get());
161     return true;
162   }
163   if (rnd.m_nLevel > 0)
164     return false;
165 
166   XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(
167       FX_HashCode_GetW(wsName.AsStringView().Last(iNameLen - 1), false));
168   if (dwNameHash == XFA_HASHCODE_Xfa) {
169     rnd.m_Objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
170   } else {
171     CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash);
172     if (pObjNode)
173       rnd.m_Objects.emplace_back(pObjNode);
174   }
175   if (!rnd.m_Objects.empty())
176     FilterCondition(pIsolate, wsCondition, &rnd);
177   return !rnd.m_Objects.empty();
178 }
179 
ResolveExcalmatory(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)180 bool CFXJSE_ResolveProcessor::ResolveExcalmatory(v8::Isolate* pIsolate,
181                                                  CFXJSE_ResolveNodeData& rnd) {
182   if (rnd.m_nLevel > 0)
183     return false;
184 
185   CXFA_Node* datasets =
186       ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
187   if (!datasets)
188     return false;
189 
190   CFXJSE_ResolveNodeData rndFind(rnd.m_pSC.Get());
191   rndFind.m_CurObject = datasets;
192   rndFind.m_wsName = rnd.m_wsName.Last(rnd.m_wsName.GetLength() - 1);
193   rndFind.m_uHashName = static_cast<XFA_HashCode>(
194       FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false));
195   rndFind.m_nLevel = rnd.m_nLevel + 1;
196   rndFind.m_dwStyles = XFA_RESOLVENODE_Children;
197   rndFind.m_wsCondition = rnd.m_wsCondition;
198   Resolve(pIsolate, rndFind);
199 
200   rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
201                        rndFind.m_Objects.end());
202   return !rnd.m_Objects.empty();
203 }
204 
ResolveNumberSign(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)205 bool CFXJSE_ResolveProcessor::ResolveNumberSign(v8::Isolate* pIsolate,
206                                                 CFXJSE_ResolveNodeData& rnd) {
207   WideString wsName = rnd.m_wsName.Last(rnd.m_wsName.GetLength() - 1);
208   WideString wsCondition = rnd.m_wsCondition;
209   CXFA_Node* curNode = ToNode(rnd.m_CurObject.Get());
210   if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView()))
211     return true;
212 
213   CFXJSE_ResolveNodeData rndFind(rnd.m_pSC.Get());
214   rndFind.m_nLevel = rnd.m_nLevel + 1;
215   rndFind.m_dwStyles = rnd.m_dwStyles;
216   rndFind.m_dwStyles |= XFA_RESOLVENODE_TagName;
217   rndFind.m_dwStyles &= ~XFA_RESOLVENODE_Attributes;
218   rndFind.m_wsName = std::move(wsName);
219   rndFind.m_uHashName = static_cast<XFA_HashCode>(
220       FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false));
221   rndFind.m_wsCondition = wsCondition;
222   rndFind.m_CurObject = curNode;
223   ResolveNormal(pIsolate, rndFind);
224   if (rndFind.m_Objects.empty())
225     return false;
226 
227   if (wsCondition.IsEmpty() && pdfium::Contains(rndFind.m_Objects, curNode)) {
228     rnd.m_Objects.emplace_back(curNode);
229   } else {
230     rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
231                          rndFind.m_Objects.end());
232   }
233   return !rnd.m_Objects.empty();
234 }
235 
ResolveForAttributeRs(CXFA_Object * curNode,CFXJSE_ResolveNodeData & rnd,WideStringView strAttr)236 bool CFXJSE_ResolveProcessor::ResolveForAttributeRs(CXFA_Object* curNode,
237                                                     CFXJSE_ResolveNodeData& rnd,
238                                                     WideStringView strAttr) {
239   Optional<XFA_SCRIPTATTRIBUTEINFO> info =
240       XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr);
241   if (!info.has_value())
242     return false;
243 
244   rnd.m_ScriptAttribute = info.value();
245   rnd.m_Objects.emplace_back(curNode);
246   rnd.m_dwFlag = XFA_ResolveNodeRS::Type::kAttribute;
247   return true;
248 }
249 
ResolveNormal(v8::Isolate * pIsolate,CFXJSE_ResolveNodeData & rnd)250 bool CFXJSE_ResolveProcessor::ResolveNormal(v8::Isolate* pIsolate,
251                                             CFXJSE_ResolveNodeData& rnd) {
252   if (rnd.m_nLevel > 32 || !rnd.m_CurObject->IsNode())
253     return false;
254 
255   CXFA_Node* curNode = rnd.m_CurObject->AsNode();
256   size_t nNum = rnd.m_Objects.size();
257   uint32_t dwStyles = rnd.m_dwStyles;
258   WideString& wsName = rnd.m_wsName;
259   XFA_HashCode uNameHash = rnd.m_uHashName;
260   WideString& wsCondition = rnd.m_wsCondition;
261 
262   CFXJSE_ResolveNodeData rndFind(rnd.m_pSC.Get());
263   rndFind.m_wsName = rnd.m_wsName;
264   rndFind.m_wsCondition = rnd.m_wsCondition;
265   rndFind.m_nLevel = rnd.m_nLevel + 1;
266   rndFind.m_uHashName = uNameHash;
267 
268   std::vector<CXFA_Node*> children;
269   std::vector<CXFA_Node*> properties;
270   CXFA_Node* pVariablesNode = nullptr;
271   CXFA_Node* pPageSetNode = nullptr;
272   for (CXFA_Node* pChild = curNode->GetFirstChild(); pChild;
273        pChild = pChild->GetNextSibling()) {
274     if (pChild->GetElementType() == XFA_Element::Variables) {
275       pVariablesNode = pChild;
276       continue;
277     }
278     if (pChild->GetElementType() == XFA_Element::PageSet) {
279       pPageSetNode = pChild;
280       continue;
281     }
282     if (curNode->HasProperty(pChild->GetElementType()))
283       properties.push_back(pChild);
284     else
285       children.push_back(pChild);
286   }
287   if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) {
288     if (pVariablesNode->GetClassHashCode() == uNameHash) {
289       rnd.m_Objects.emplace_back(pVariablesNode);
290     } else {
291       rndFind.m_CurObject = pVariablesNode;
292       SetStylesForChild(dwStyles, rndFind);
293       WideString wsSaveCondition = std::move(rndFind.m_wsCondition);
294       ResolveNormal(pIsolate, rndFind);
295       rndFind.m_wsCondition = std::move(wsSaveCondition);
296       rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
297                            rndFind.m_Objects.end());
298       rndFind.m_Objects.clear();
299     }
300     if (rnd.m_Objects.size() > nNum) {
301       FilterCondition(pIsolate, wsCondition, &rnd);
302       return !rnd.m_Objects.empty();
303     }
304   }
305 
306   if (dwStyles & XFA_RESOLVENODE_Children) {
307     bool bSetFlag = false;
308     if (pPageSetNode && (dwStyles & XFA_RESOLVENODE_Properties))
309       children.push_back(pPageSetNode);
310 
311     for (CXFA_Node* child : children) {
312       if (dwStyles & XFA_RESOLVENODE_TagName) {
313         if (child->GetClassHashCode() == uNameHash)
314           rnd.m_Objects.emplace_back(child);
315       } else if (child->GetNameHash() == uNameHash) {
316         rnd.m_Objects.emplace_back(child);
317       }
318 
319       if (child->GetElementType() != XFA_Element::PageSet &&
320           child->IsTransparent()) {
321         if (!bSetFlag) {
322           SetStylesForChild(dwStyles, rndFind);
323           bSetFlag = true;
324         }
325         rndFind.m_CurObject = child;
326 
327         WideString wsSaveCondition = std::move(rndFind.m_wsCondition);
328         ResolveNormal(pIsolate, rndFind);
329         rndFind.m_wsCondition = std::move(wsSaveCondition);
330         rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
331                              rndFind.m_Objects.end());
332         rndFind.m_Objects.clear();
333       }
334     }
335     if (rnd.m_Objects.size() > nNum) {
336       if (!(dwStyles & XFA_RESOLVENODE_ALL)) {
337         std::vector<CXFA_Node*> upArrayNodes;
338         if (curNode->IsTransparent()) {
339           CXFA_Node* pCurrent = ToNode(rnd.m_Objects.front().Get());
340           if (pCurrent) {
341             upArrayNodes =
342                 pCurrent->GetSiblings(!!(dwStyles & XFA_RESOLVENODE_TagName));
343           }
344         }
345         if (upArrayNodes.size() > rnd.m_Objects.size()) {
346           CXFA_Object* pSaveObject = rnd.m_Objects.front().Get();
347           rnd.m_Objects = std::vector<UnownedPtr<CXFA_Object>>(
348               upArrayNodes.begin(), upArrayNodes.end());
349           rnd.m_Objects.front() = pSaveObject;
350         }
351       }
352       FilterCondition(pIsolate, wsCondition, &rnd);
353       return !rnd.m_Objects.empty();
354     }
355   }
356   if (dwStyles & XFA_RESOLVENODE_Attributes) {
357     if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView()))
358       return 1;
359   }
360   if (dwStyles & XFA_RESOLVENODE_Properties) {
361     for (CXFA_Node* pChildProperty : properties) {
362       if (pChildProperty->IsUnnamed()) {
363         if (pChildProperty->GetClassHashCode() == uNameHash)
364           rnd.m_Objects.emplace_back(pChildProperty);
365         continue;
366       }
367       if (pChildProperty->GetNameHash() == uNameHash &&
368           pChildProperty->GetElementType() != XFA_Element::Extras &&
369           pChildProperty->GetElementType() != XFA_Element::Items) {
370         rnd.m_Objects.emplace_back(pChildProperty);
371       }
372     }
373     if (rnd.m_Objects.size() > nNum) {
374       FilterCondition(pIsolate, wsCondition, &rnd);
375       return !rnd.m_Objects.empty();
376     }
377 
378     CXFA_Node* pProp = nullptr;
379     if (XFA_Element::Subform == curNode->GetElementType() &&
380         XFA_HASHCODE_Occur == uNameHash) {
381       CXFA_Node* pInstanceManager = curNode->GetInstanceMgrOfSubform();
382       if (pInstanceManager) {
383         pProp = pInstanceManager->JSObject()->GetOrCreateProperty<CXFA_Occur>(
384             0, XFA_Element::Occur);
385       }
386     } else {
387       XFA_Element eType = XFA_GetElementByName(wsName.AsStringView());
388       if (eType == XFA_Element::PageSet) {
389         pProp = curNode->JSObject()->GetProperty<CXFA_Node>(0, eType);
390       } else if (eType != XFA_Element::Unknown) {
391         pProp = curNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, eType);
392       }
393     }
394     if (pProp) {
395       rnd.m_Objects.emplace_back(pProp);
396       return !rnd.m_Objects.empty();
397     }
398   }
399 
400   CXFA_Node* const parentNode = curNode->GetParent();
401   uint32_t uCurClassHash = curNode->GetClassHashCode();
402   if (!parentNode) {
403     if (uCurClassHash == uNameHash) {
404       rnd.m_Objects.emplace_back(curNode);
405       FilterCondition(pIsolate, wsCondition, &rnd);
406       if (!rnd.m_Objects.empty())
407         return true;
408     }
409     return false;
410   }
411 
412   if (dwStyles & XFA_RESOLVENODE_Siblings) {
413     CXFA_Node* child = parentNode->GetFirstChild();
414     uint32_t dwSubStyles =
415         XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties;
416     if (dwStyles & XFA_RESOLVENODE_TagName)
417       dwSubStyles |= XFA_RESOLVENODE_TagName;
418     if (dwStyles & XFA_RESOLVENODE_ALL)
419       dwSubStyles |= XFA_RESOLVENODE_ALL;
420 
421     rndFind.m_dwStyles = dwSubStyles;
422     while (child) {
423       if (child == curNode) {
424         if (dwStyles & XFA_RESOLVENODE_TagName) {
425           if (uCurClassHash == uNameHash)
426             rnd.m_Objects.emplace_back(curNode);
427         } else {
428           if (child->GetNameHash() == uNameHash) {
429             rnd.m_Objects.emplace_back(curNode);
430             if (rnd.m_nLevel == 0 && wsCondition.IsEmpty()) {
431               rnd.m_Objects.clear();
432               rnd.m_Objects.emplace_back(curNode);
433               return true;
434             }
435           }
436         }
437         child = child->GetNextSibling();
438         continue;
439       }
440 
441       if (dwStyles & XFA_RESOLVENODE_TagName) {
442         if (child->GetClassHashCode() == uNameHash)
443           rnd.m_Objects.emplace_back(child);
444       } else if (child->GetNameHash() == uNameHash) {
445         rnd.m_Objects.emplace_back(child);
446       }
447 
448       bool bInnerSearch = false;
449       if (parentNode->HasProperty(child->GetElementType())) {
450         if ((child->GetElementType() == XFA_Element::Variables ||
451              child->GetElementType() == XFA_Element::PageSet)) {
452           bInnerSearch = true;
453         }
454       } else if (child->IsTransparent()) {
455         bInnerSearch = true;
456       }
457       if (bInnerSearch) {
458         rndFind.m_CurObject = child;
459         WideString wsOriginCondition = std::move(rndFind.m_wsCondition);
460         uint32_t dwOriginStyle = rndFind.m_dwStyles;
461         rndFind.m_dwStyles = dwOriginStyle | XFA_RESOLVENODE_ALL;
462         ResolveNormal(pIsolate, rndFind);
463         rndFind.m_dwStyles = dwOriginStyle;
464         rndFind.m_wsCondition = std::move(wsOriginCondition);
465         rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
466                              rndFind.m_Objects.end());
467         rndFind.m_Objects.clear();
468       }
469       child = child->GetNextSibling();
470     }
471     if (rnd.m_Objects.size() > nNum) {
472       if (parentNode->IsTransparent()) {
473         std::vector<CXFA_Node*> upArrayNodes;
474         CXFA_Node* pCurrent = ToNode(rnd.m_Objects.front().Get());
475         if (pCurrent) {
476           upArrayNodes =
477               pCurrent->GetSiblings(!!(dwStyles & XFA_RESOLVENODE_TagName));
478         }
479         if (upArrayNodes.size() > rnd.m_Objects.size()) {
480           CXFA_Object* pSaveObject = rnd.m_Objects.front().Get();
481           rnd.m_Objects = std::vector<UnownedPtr<CXFA_Object>>(
482               upArrayNodes.begin(), upArrayNodes.end());
483           rnd.m_Objects.front() = pSaveObject;
484         }
485       }
486       FilterCondition(pIsolate, wsCondition, &rnd);
487       return !rnd.m_Objects.empty();
488     }
489   }
490 
491   if (dwStyles & XFA_RESOLVENODE_Parent) {
492     uint32_t dwSubStyles = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
493                            XFA_RESOLVENODE_Properties;
494     if (dwStyles & XFA_RESOLVENODE_TagName)
495       dwSubStyles |= XFA_RESOLVENODE_TagName;
496     if (dwStyles & XFA_RESOLVENODE_ALL)
497       dwSubStyles |= XFA_RESOLVENODE_ALL;
498 
499     rndFind.m_dwStyles = dwSubStyles;
500     rndFind.m_CurObject = parentNode;
501     rnd.m_pSC->GetUpObjectArray()->push_back(parentNode);
502     ResolveNormal(pIsolate, rndFind);
503     rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
504                          rndFind.m_Objects.end());
505     rndFind.m_Objects.clear();
506     if (rnd.m_Objects.size() > nNum)
507       return true;
508   }
509   return false;
510 }
511 
ResolveAsterisk(CFXJSE_ResolveNodeData & rnd)512 bool CFXJSE_ResolveProcessor::ResolveAsterisk(CFXJSE_ResolveNodeData& rnd) {
513   CXFA_Node* curNode = ToNode(rnd.m_CurObject.Get());
514   std::vector<CXFA_Node*> array = curNode->GetNodeListWithFilter(
515       XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties);
516   rnd.m_Objects.insert(rnd.m_Objects.end(), array.begin(), array.end());
517   return !rnd.m_Objects.empty();
518 }
519 
GetFilter(WideStringView wsExpression,int32_t nStart,CFXJSE_ResolveNodeData & rnd)520 int32_t CFXJSE_ResolveProcessor::GetFilter(WideStringView wsExpression,
521                                            int32_t nStart,
522                                            CFXJSE_ResolveNodeData& rnd) {
523   ASSERT(nStart > -1);
524 
525   int32_t iLength = wsExpression.GetLength();
526   if (nStart >= iLength)
527     return 0;
528 
529   WideString& wsName = rnd.m_wsName;
530   WideString& wsCondition = rnd.m_wsCondition;
531   int32_t nNameCount = 0;
532   int32_t nConditionCount = 0;
533   {
534     // Span's lifetime must end before ReleaseBuffer() below.
535     pdfium::span<wchar_t> pNameBuf = wsName.GetBuffer(iLength - nStart);
536     pdfium::span<wchar_t> pConditionBuf =
537         wsCondition.GetBuffer(iLength - nStart);
538     pdfium::span<const wchar_t> pSrc = wsExpression.span();
539     std::vector<int32_t> stack;
540     int32_t nType = -1;
541     wchar_t wPrev = 0;
542     wchar_t wCur;
543     bool bIsCondition = false;
544     while (nStart < iLength) {
545       wCur = pSrc[nStart++];
546       if (wCur == '.') {
547         if (nNameCount == 0) {
548           rnd.m_dwStyles |= XFA_RESOLVENODE_AnyChild;
549           continue;
550         }
551         if (wPrev == '\\') {
552           pNameBuf[nNameCount - 1] = wPrev = '.';
553           continue;
554         }
555 
556         wchar_t wLookahead = nStart < iLength ? pSrc[nStart] : 0;
557         if (wLookahead != '[' && wLookahead != '(' && nType < 0)
558           break;
559       }
560       if (wCur == '[' || wCur == '(') {
561         bIsCondition = true;
562       } else if (wCur == '.' && nStart < iLength &&
563                  (pSrc[nStart] == '[' || pSrc[nStart] == '(')) {
564         bIsCondition = true;
565       }
566       if (bIsCondition)
567         pConditionBuf[nConditionCount++] = wCur;
568       else
569         pNameBuf[nNameCount++] = wCur;
570 
571       if ((nType == 0 && wCur == ']') || (nType == 1 && wCur == ')') ||
572           (nType == 2 && wCur == '"')) {
573         nType = stack.empty() ? -1 : stack.back();
574         if (!stack.empty())
575           stack.pop_back();
576       } else if (wCur == '[') {
577         stack.push_back(nType);
578         nType = 0;
579       } else if (wCur == '(') {
580         stack.push_back(nType);
581         nType = 1;
582       } else if (wCur == '"') {
583         stack.push_back(nType);
584         nType = 2;
585       }
586       wPrev = wCur;
587     }
588     if (!stack.empty())
589       return -1;
590   }
591   wsName.ReleaseBuffer(nNameCount);
592   wsCondition.ReleaseBuffer(nConditionCount);
593   wsName.Trim();
594   wsCondition.Trim();
595   rnd.m_uHashName =
596       static_cast<XFA_HashCode>(FX_HashCode_GetW(wsName.AsStringView(), false));
597   return nStart;
598 }
599 
ConditionArray(size_t iCurIndex,WideString wsCondition,size_t iFoundCount,CFXJSE_ResolveNodeData * pRnd)600 void CFXJSE_ResolveProcessor::ConditionArray(size_t iCurIndex,
601                                              WideString wsCondition,
602                                              size_t iFoundCount,
603                                              CFXJSE_ResolveNodeData* pRnd) {
604   size_t iLen = wsCondition.GetLength();
605   bool bRelative = false;
606   bool bAll = false;
607   size_t i = 1;
608   for (; i < iLen; ++i) {
609     wchar_t ch = wsCondition[i];
610     if (ch == ' ')
611       continue;
612     if (ch == '+' || ch == '-')
613       bRelative = true;
614     else if (ch == '*')
615       bAll = true;
616 
617     break;
618   }
619   if (bAll) {
620     if (pRnd->m_dwStyles & XFA_RESOLVENODE_CreateNode) {
621       if (pRnd->m_dwStyles & XFA_RESOLVENODE_Bind) {
622         m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
623         m_pNodeHelper->m_iCreateCount = 1;
624         pRnd->m_Objects.clear();
625         m_pNodeHelper->m_iCurAllStart = -1;
626         m_pNodeHelper->m_pAllStartParent = nullptr;
627       } else if (m_pNodeHelper->m_iCurAllStart == -1) {
628         m_pNodeHelper->m_iCurAllStart = m_iCurStart;
629         m_pNodeHelper->m_pAllStartParent = ToNode(pRnd->m_CurObject.Get());
630       }
631     } else if (pRnd->m_dwStyles & XFA_RESOLVENODE_BindNew) {
632       if (m_pNodeHelper->m_iCurAllStart == -1)
633         m_pNodeHelper->m_iCurAllStart = m_iCurStart;
634     }
635     return;
636   }
637   if (iFoundCount == 1 && !iLen)
638     return;
639 
640   int32_t iIndex = wsCondition.Substr(i, iLen - 1 - i).GetInteger();
641   if (bRelative)
642     iIndex += iCurIndex;
643 
644   if (iIndex < 0 || static_cast<size_t>(iIndex) >= iFoundCount) {
645     if (pRnd->m_dwStyles & XFA_RESOLVENODE_CreateNode) {
646       m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
647       m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1;
648     }
649     pRnd->m_Objects.clear();
650   } else {
651     pRnd->m_Objects =
652         std::vector<UnownedPtr<CXFA_Object>>(1, pRnd->m_Objects[iIndex]);
653   }
654 }
655 
FilterCondition(v8::Isolate * pIsolate,WideString wsCondition,CFXJSE_ResolveNodeData * pRnd)656 void CFXJSE_ResolveProcessor::FilterCondition(v8::Isolate* pIsolate,
657                                               WideString wsCondition,
658                                               CFXJSE_ResolveNodeData* pRnd) {
659   size_t iCurIndex = 0;
660   const auto* pArray = pRnd->m_pSC->GetUpObjectArray();
661   if (!pArray->empty()) {
662     CXFA_Node* pNode = pArray->back();
663     bool bIsProperty = pNode->IsProperty();
664     bool bIsClassIndex =
665         pNode->IsUnnamed() ||
666         (bIsProperty && pNode->GetElementType() != XFA_Element::PageSet);
667     iCurIndex = pNode->GetIndex(bIsProperty, bIsClassIndex);
668   }
669 
670   size_t iFoundCount = pRnd->m_Objects.size();
671   wsCondition.Trim();
672 
673   int32_t iLen = wsCondition.GetLength();
674   if (!iLen) {
675     if (pRnd->m_dwStyles & XFA_RESOLVENODE_ALL)
676       return;
677     if (iFoundCount == 1)
678       return;
679 
680     if (iFoundCount <= iCurIndex) {
681       if (pRnd->m_dwStyles & XFA_RESOLVENODE_CreateNode) {
682         m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
683         m_pNodeHelper->m_iCreateCount = iCurIndex - iFoundCount + 1;
684       }
685       pRnd->m_Objects.clear();
686       return;
687     }
688 
689     pRnd->m_Objects =
690         std::vector<UnownedPtr<CXFA_Object>>(1, pRnd->m_Objects[iCurIndex]);
691     return;
692   }
693 
694   wchar_t wTypeChar = wsCondition[0];
695   switch (wTypeChar) {
696     case '[':
697       ConditionArray(iCurIndex, wsCondition, iFoundCount, pRnd);
698       return;
699     case '.':
700       if (iLen > 1 && (wsCondition[1] == '[' || wsCondition[1] == '('))
701         DoPredicateFilter(pIsolate, wsCondition, iFoundCount, pRnd);
702       return;
703     case '(':
704     case '"':
705     default:
706       return;
707   }
708 }
709 
SetStylesForChild(uint32_t dwParentStyles,CFXJSE_ResolveNodeData & rnd)710 void CFXJSE_ResolveProcessor::SetStylesForChild(uint32_t dwParentStyles,
711                                                 CFXJSE_ResolveNodeData& rnd) {
712   uint32_t dwSubStyles = XFA_RESOLVENODE_Children;
713   if (dwParentStyles & XFA_RESOLVENODE_TagName)
714     dwSubStyles |= XFA_RESOLVENODE_TagName;
715 
716   dwSubStyles &= ~XFA_RESOLVENODE_Parent;
717   dwSubStyles &= ~XFA_RESOLVENODE_Siblings;
718   dwSubStyles &= ~XFA_RESOLVENODE_Properties;
719   dwSubStyles |= XFA_RESOLVENODE_ALL;
720   rnd.m_dwStyles = dwSubStyles;
721 }
722 
SetIndexDataBind(WideString & wsNextCondition,int32_t & iIndex,int32_t iCount)723 void CFXJSE_ResolveProcessor::SetIndexDataBind(WideString& wsNextCondition,
724                                                int32_t& iIndex,
725                                                int32_t iCount) {
726   if (m_pNodeHelper->CreateNodeForCondition(wsNextCondition)) {
727     if (m_pNodeHelper->m_eLastCreateType == XFA_Element::DataGroup) {
728       iIndex = 0;
729     } else {
730       iIndex = iCount - 1;
731     }
732   } else {
733     iIndex = iCount - 1;
734   }
735 }
736 
CFXJSE_ResolveNodeData(CFXJSE_Engine * pSC)737 CFXJSE_ResolveNodeData::CFXJSE_ResolveNodeData(CFXJSE_Engine* pSC)
738     : m_pSC(pSC) {}
739 
740 CFXJSE_ResolveNodeData::~CFXJSE_ResolveNodeData() = default;
741