xpath BUGFIX infinite recursion check

The change prevents stack-overflow error. Protection is added in the
::reparse_or_expr(). The rest of the changes are just passing the
'depth' parameter.
diff --git a/src/common.h b/src/common.h
index cb2591b..eb9ed7d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -274,6 +274,7 @@
 #define LY_VCODE_XP_INOP_1      LYVE_XPATH, "Cannot apply XPath operation %s on %s."
 #define LY_VCODE_XP_INOP_2      LYVE_XPATH, "Cannot apply XPath operation %s on %s and %s."
 #define LY_VCODE_XP_INMOD       LYVE_XPATH, "Unknown/non-implemented module \"%.*s\"."
+#define LY_VCODE_XP_DEPTH       LYVE_XPATH, "The maximum nesting of expressions has been exceeded."
 
 #define LY_VCODE_DEV_NOT_PRESENT LYVE_REFERENCE, "Invalid deviation %s \"%s\" property \"%s\" which is not present."
 
diff --git a/src/xpath.c b/src/xpath.c
index 4b46c7d..d658193 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -43,7 +43,7 @@
 #include "tree_schema_internal.h"
 #include "xml.h"
 
-static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx);
+static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth);
 static LY_ERR eval_expr_select(const struct lyxp_expr *exp, uint16_t *tok_idx, enum lyxp_expr_type etype,
         struct lyxp_set *set, uint32_t options);
 static LY_ERR moveto_resolve_model(const char **qname, uint16_t *qname_len, const struct lyxp_set *set,
@@ -1943,10 +1943,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_predicate(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_predicate(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     LY_ERR rc;
 
@@ -1954,7 +1955,7 @@
     LY_CHECK_RET(rc);
     ++(*tok_idx);
 
-    rc = reparse_or_expr(ctx, exp, tok_idx);
+    rc = reparse_or_expr(ctx, exp, tok_idx, depth);
     LY_CHECK_RET(rc);
 
     rc = lyxp_check_token(ctx, exp, *tok_idx, LYXP_TOKEN_BRACK2);
@@ -1974,10 +1975,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression \p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR (LY_EINCOMPLETE on forward reference)
  */
 static LY_ERR
-reparse_relative_location_path(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_relative_location_path(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     LY_ERR rc;
 
@@ -2033,7 +2035,7 @@
 reparse_predicate:
             /* Predicate* */
             while (!lyxp_check_token(NULL, exp, *tok_idx, LYXP_TOKEN_BRACK1)) {
-                rc = reparse_predicate(ctx, exp, tok_idx);
+                rc = reparse_predicate(ctx, exp, tok_idx, depth);
                 LY_CHECK_RET(rc);
             }
             break;
@@ -2054,10 +2056,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression \p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_absolute_location_path(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_absolute_location_path(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     LY_ERR rc;
 
@@ -2077,7 +2080,7 @@
         case LYXP_TOKEN_AT:
         case LYXP_TOKEN_NAMETEST:
         case LYXP_TOKEN_NODETYPE:
-            rc = reparse_relative_location_path(ctx, exp, tok_idx);
+            rc = reparse_relative_location_path(ctx, exp, tok_idx, depth);
             LY_CHECK_RET(rc);
         /* fall through */
         default:
@@ -2088,7 +2091,7 @@
         /* '//' RelativeLocationPath */
         ++(*tok_idx);
 
-        rc = reparse_relative_location_path(ctx, exp, tok_idx);
+        rc = reparse_relative_location_path(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
 
@@ -2103,10 +2106,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_function_call(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_function_call(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     int8_t min_arg_count = -1;
     uint32_t arg_count, max_arg_count = 0;
@@ -2276,14 +2280,14 @@
     LY_CHECK_RET(rc);
     if (exp->tokens[*tok_idx] != LYXP_TOKEN_PAR2) {
         ++arg_count;
-        rc = reparse_or_expr(ctx, exp, tok_idx);
+        rc = reparse_or_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
     while (!lyxp_check_token(NULL, exp, *tok_idx, LYXP_TOKEN_COMMA)) {
         ++(*tok_idx);
 
         ++arg_count;
-        rc = reparse_or_expr(ctx, exp, tok_idx);
+        rc = reparse_or_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
 
@@ -2312,10 +2316,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_path_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_path_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     LY_ERR rc;
 
@@ -2328,7 +2333,7 @@
         /* '(' Expr ')' Predicate* */
         ++(*tok_idx);
 
-        rc = reparse_or_expr(ctx, exp, tok_idx);
+        rc = reparse_or_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
 
         rc = lyxp_check_token(ctx, exp, *tok_idx, LYXP_TOKEN_PAR2);
@@ -2342,19 +2347,19 @@
     case LYXP_TOKEN_NAMETEST:
     case LYXP_TOKEN_NODETYPE:
         /* RelativeLocationPath */
-        rc = reparse_relative_location_path(ctx, exp, tok_idx);
+        rc = reparse_relative_location_path(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
         break;
     case LYXP_TOKEN_FUNCNAME:
         /* FunctionCall */
-        rc = reparse_function_call(ctx, exp, tok_idx);
+        rc = reparse_function_call(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
         goto predicate;
         break;
     case LYXP_TOKEN_OPER_PATH:
     case LYXP_TOKEN_OPER_RPATH:
         /* AbsoluteLocationPath */
-        rc = reparse_absolute_location_path(ctx, exp, tok_idx);
+        rc = reparse_absolute_location_path(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
         break;
     case LYXP_TOKEN_LITERAL:
@@ -2377,7 +2382,7 @@
 predicate:
     /* Predicate* */
     while (!lyxp_check_token(NULL, exp, *tok_idx, LYXP_TOKEN_BRACK1)) {
-        rc = reparse_predicate(ctx, exp, tok_idx);
+        rc = reparse_predicate(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
 
@@ -2387,7 +2392,7 @@
         /* '/' or '//' */
         ++(*tok_idx);
 
-        rc = reparse_relative_location_path(ctx, exp, tok_idx);
+        rc = reparse_relative_location_path(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
 
@@ -2403,10 +2408,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_unary_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_unary_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     uint16_t prev_exp;
     LY_ERR rc;
@@ -2421,7 +2427,7 @@
 
     /* PathExpr */
     prev_exp = *tok_idx;
-    rc = reparse_path_expr(ctx, exp, tok_idx);
+    rc = reparse_path_expr(ctx, exp, tok_idx, depth);
     LY_CHECK_RET(rc);
 
     /* ('|' PathExpr)* */
@@ -2429,7 +2435,7 @@
         exp_repeat_push(exp, prev_exp, LYXP_EXPR_UNION);
         ++(*tok_idx);
 
-        rc = reparse_path_expr(ctx, exp, tok_idx);
+        rc = reparse_path_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
     }
 
@@ -2450,10 +2456,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_additive_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_additive_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     uint16_t prev_add_exp, prev_mul_exp;
     LY_ERR rc;
@@ -2470,7 +2477,7 @@
 reparse_multiplicative_expr:
         /* UnaryExpr */
         prev_mul_exp = *tok_idx;
-        rc = reparse_unary_expr(ctx, exp, tok_idx);
+        rc = reparse_unary_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
 
         /* ('*' / 'div' / 'mod' UnaryExpr)* */
@@ -2479,7 +2486,7 @@
             exp_repeat_push(exp, prev_mul_exp, LYXP_EXPR_MULTIPLICATIVE);
             ++(*tok_idx);
 
-            rc = reparse_unary_expr(ctx, exp, tok_idx);
+            rc = reparse_unary_expr(ctx, exp, tok_idx, depth);
             LY_CHECK_RET(rc);
         }
     }
@@ -2501,10 +2508,11 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_equality_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_equality_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     uint16_t prev_eq_exp, prev_rel_exp;
     LY_ERR rc;
@@ -2520,7 +2528,7 @@
 reparse_additive_expr:
         /* AdditiveExpr */
         prev_rel_exp = *tok_idx;
-        rc = reparse_additive_expr(ctx, exp, tok_idx);
+        rc = reparse_additive_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
 
         /* ('<' / '>' / '<=' / '>=' AdditiveExpr)* */
@@ -2528,7 +2536,7 @@
             exp_repeat_push(exp, prev_rel_exp, LYXP_EXPR_RELATIONAL);
             ++(*tok_idx);
 
-            rc = reparse_additive_expr(ctx, exp, tok_idx);
+            rc = reparse_additive_expr(ctx, exp, tok_idx, depth);
             LY_CHECK_RET(rc);
         }
     }
@@ -2545,14 +2553,18 @@
  * @param[in] ctx Context for logging.
  * @param[in] exp Parsed XPath expression.
  * @param[in] tok_idx Position in the expression @p exp.
+ * @param[in] depth Current number of nested expressions.
  * @return LY_ERR
  */
 static LY_ERR
-reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx)
+reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t depth)
 {
     uint16_t prev_or_exp, prev_and_exp;
     LY_ERR rc;
 
+    ++depth;
+    LY_CHECK_ERR_RET(depth > LYXP_MAX_BLOCK_DEPTH, LOGVAL(ctx, LY_VCODE_XP_DEPTH), LY_EINVAL);
+
     prev_or_exp = *tok_idx;
     goto reparse_equality_expr;
 
@@ -2564,7 +2576,7 @@
 reparse_equality_expr:
         /* EqualityExpr */
         prev_and_exp = *tok_idx;
-        rc = reparse_equality_expr(ctx, exp, tok_idx);
+        rc = reparse_equality_expr(ctx, exp, tok_idx, depth);
         LY_CHECK_RET(rc);
 
         /* ('and' EqualityExpr)* */
@@ -2572,7 +2584,7 @@
             exp_repeat_push(exp, prev_and_exp, LYXP_EXPR_AND);
             ++(*tok_idx);
 
-            rc = reparse_equality_expr(ctx, exp, tok_idx);
+            rc = reparse_equality_expr(ctx, exp, tok_idx, depth);
             LY_CHECK_RET(rc);
         }
     }
@@ -2945,7 +2957,7 @@
         LY_CHECK_ERR_GOTO(!expr->repeat, LOGMEM(ctx); ret = LY_EMEM, error);
 
         /* fill repeat */
-        LY_CHECK_ERR_GOTO(reparse_or_expr(ctx, expr, &tok_idx), ret = LY_EVALID, error);
+        LY_CHECK_ERR_GOTO(reparse_or_expr(ctx, expr, &tok_idx, 0), ret = LY_EVALID, error);
         if (expr->used > tok_idx) {
             LOGVAL(ctx, LYVE_XPATH, "Unparsed characters \"%s\" left at the end of an XPath expression.",
                     &expr->expr[expr->tok_pos[tok_idx]]);
diff --git a/src/xpath.h b/src/xpath.h
index 7858508..1fda77d 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -87,6 +87,9 @@
 #define LYXP_STRING_CAST_SIZE_START 64
 #define LYXP_STRING_CAST_SIZE_STEP 16
 
+/* Maximum number of nested expressions. */
+#define LYXP_MAX_BLOCK_DEPTH 100
+
 /**
  * @brief Tokens that can be in an XPath expression.
  */