@@ -193,26 +193,40 @@ void RBBINode::NRDeleteNode(RBBINode *node) {
193193// references in preparation for generating the DFA tables.
194194//
195195// -------------------------------------------------------------------------
196- RBBINode *RBBINode::cloneTree () {
196+ constexpr int kRecursiveDepthLimit = 3500 ;
197+ RBBINode *RBBINode::cloneTree (UErrorCode &status, int depth) {
198+ if (U_FAILURE (status)) {
199+ return nullptr ;
200+ }
201+ // If the depth of the stack is too deep, we return U_INPUT_TOO_LONG_ERROR
202+ // to avoid stack overflow crash.
203+ if (depth > kRecursiveDepthLimit ) {
204+ status = U_INPUT_TOO_LONG_ERROR;
205+ return nullptr ;
206+ }
197207 RBBINode *n;
198208
199209 if (fType == RBBINode::varRef) {
200210 // If the current node is a variable reference, skip over it
201211 // and clone the definition of the variable instead.
202- n = fLeftChild ->cloneTree ();
212+ n = fLeftChild ->cloneTree (status, depth+ 1 );
203213 } else if (fType == RBBINode::uset) {
204214 n = this ;
205215 } else {
206216 n = new RBBINode (*this );
207217 // Check for null pointer.
208218 if (n != nullptr ) {
209219 if (fLeftChild != nullptr ) {
210- n->fLeftChild = fLeftChild ->cloneTree ();
211- n->fLeftChild ->fParent = n;
220+ n->fLeftChild = fLeftChild ->cloneTree (status, depth+1 );
221+ if (U_SUCCESS (status)) {
222+ n->fLeftChild ->fParent = n;
223+ }
212224 }
213225 if (fRightChild != nullptr ) {
214- n->fRightChild = fRightChild ->cloneTree ();
215- n->fRightChild ->fParent = n;
226+ n->fRightChild = fRightChild ->cloneTree (status, depth+1 );
227+ if (U_SUCCESS (status)) {
228+ n->fRightChild ->fParent = n;
229+ }
216230 }
217231 }
218232 }
@@ -239,7 +253,6 @@ RBBINode *RBBINode::cloneTree() {
239253// nested references are handled by cloneTree(), not here.
240254//
241255// -------------------------------------------------------------------------
242- constexpr int kRecursiveDepthLimit = 3500 ;
243256RBBINode *RBBINode::flattenVariables (UErrorCode& status, int depth) {
244257 if (U_FAILURE (status)) {
245258 return this ;
@@ -251,7 +264,7 @@ RBBINode *RBBINode::flattenVariables(UErrorCode& status, int depth) {
251264 return this ;
252265 }
253266 if (fType == varRef) {
254- RBBINode *retNode = fLeftChild ->cloneTree ();
267+ RBBINode *retNode = fLeftChild ->cloneTree (status, depth+ 1 );
255268 if (retNode != nullptr ) {
256269 retNode->fRuleRoot = this ->fRuleRoot ;
257270 retNode->fChainIn = this ->fChainIn ;
@@ -280,19 +293,30 @@ RBBINode *RBBINode::flattenVariables(UErrorCode& status, int depth) {
280293// the left child of the uset node.
281294//
282295// -------------------------------------------------------------------------
283- void RBBINode::flattenSets () {
296+ void RBBINode::flattenSets (UErrorCode &status, int depth) {
297+ if (U_FAILURE (status)) {
298+ return ;
299+ }
300+ // If the depth of the stack is too deep, we return U_INPUT_TOO_LONG_ERROR
301+ // to avoid stack overflow crash.
302+ if (depth > kRecursiveDepthLimit ) {
303+ status = U_INPUT_TOO_LONG_ERROR;
304+ return ;
305+ }
284306 U_ASSERT (fType != setRef);
285307
286308 if (fLeftChild != nullptr ) {
287309 if (fLeftChild ->fType ==setRef) {
288310 RBBINode *setRefNode = fLeftChild ;
289311 RBBINode *usetNode = setRefNode->fLeftChild ;
290312 RBBINode *replTree = usetNode->fLeftChild ;
291- fLeftChild = replTree->cloneTree ();
292- fLeftChild ->fParent = this ;
313+ fLeftChild = replTree->cloneTree (status, depth+1 );
314+ if (U_FAILURE (status)) {
315+ fLeftChild ->fParent = this ;
316+ }
293317 delete setRefNode;
294318 } else {
295- fLeftChild ->flattenSets ();
319+ fLeftChild ->flattenSets (status, depth+ 1 );
296320 }
297321 }
298322
@@ -301,11 +325,13 @@ void RBBINode::flattenSets() {
301325 RBBINode *setRefNode = fRightChild ;
302326 RBBINode *usetNode = setRefNode->fLeftChild ;
303327 RBBINode *replTree = usetNode->fLeftChild ;
304- fRightChild = replTree->cloneTree ();
305- fRightChild ->fParent = this ;
328+ fRightChild = replTree->cloneTree (status, depth+1 );
329+ if (U_FAILURE (status)) {
330+ fRightChild ->fParent = this ;
331+ }
306332 delete setRefNode;
307333 } else {
308- fRightChild ->flattenSets ();
334+ fRightChild ->flattenSets (status, depth+ 1 );
309335 }
310336 }
311337}
0 commit comments