diff options
| author | Yuan Fu | 2023-04-14 13:32:55 -0700 |
|---|---|---|
| committer | Yuan Fu | 2023-04-14 16:54:25 -0700 |
| commit | 00fba2a4d54cb117ad3176e6633cf2137d52223a (patch) | |
| tree | 0415c8b021a933dcd98320da8ffe14df973fa20d /src | |
| parent | 9f777475be5ec2092b7f0ef98be5b1641100beb2 (diff) | |
| download | emacs-00fba2a4d54cb117ad3176e6633cf2137d52223a.tar.gz emacs-00fba2a4d54cb117ad3176e6633cf2137d52223a.zip | |
Add a recursion level limit for tree-sitter search predicates
* src/treesit.c:
(treesit_traverse_validate_predicate): Check for recursion level.
(Ftreesit_search_subtree)
(Ftreesit_search_forward)
(Ftreesit_induce_sparse_tree)
(Ftreesit_node_match_p): Update uses of
treesit_traverse_validate_predicate.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/treesit.c b/src/treesit.c index 9b4695b267e..0a289800a0f 100644 --- a/src/treesit.c +++ b/src/treesit.c | |||
| @@ -3155,11 +3155,23 @@ treesit_traverse_child_helper (TSTreeCursor *cursor, | |||
| 3155 | 3155 | ||
| 3156 | /* Validate the PRED passed to treesit_traverse_match_predicate. If | 3156 | /* Validate the PRED passed to treesit_traverse_match_predicate. If |
| 3157 | there's an error, set SIGNAL_DATA to something signal accepts, and | 3157 | there's an error, set SIGNAL_DATA to something signal accepts, and |
| 3158 | return false, otherwise return true. */ | 3158 | return false, otherwise return true. This function also check for |
| 3159 | recusion levels: we place a arbitrary 100 level limit on recursive | ||
| 3160 | predicates. RECURSION_LEVEL is the current recursion level (that | ||
| 3161 | starts at 0), if it goes over 99, return false and set | ||
| 3162 | SIGNAL_DATA. */ | ||
| 3159 | static bool | 3163 | static bool |
| 3160 | treesit_traverse_validate_predicate (Lisp_Object pred, | 3164 | treesit_traverse_validate_predicate (Lisp_Object pred, |
| 3161 | Lisp_Object *signal_data) | 3165 | Lisp_Object *signal_data, |
| 3166 | ptrdiff_t recursion_level) | ||
| 3162 | { | 3167 | { |
| 3168 | if (recursion_level > 99) | ||
| 3169 | { | ||
| 3170 | *signal_data = list1 (build_string ("Predicate recursion level " | ||
| 3171 | "exceeded: it must not exceed " | ||
| 3172 | "100 levels")); | ||
| 3173 | return false; | ||
| 3174 | } | ||
| 3163 | if (STRINGP (pred)) | 3175 | if (STRINGP (pred)) |
| 3164 | return true; | 3176 | return true; |
| 3165 | else if (FUNCTIONP (pred)) | 3177 | else if (FUNCTIONP (pred)) |
| @@ -3186,7 +3198,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred, | |||
| 3186 | return false; | 3198 | return false; |
| 3187 | } | 3199 | } |
| 3188 | return treesit_traverse_validate_predicate (XCAR (cdr), | 3200 | return treesit_traverse_validate_predicate (XCAR (cdr), |
| 3189 | signal_data); | 3201 | signal_data, |
| 3202 | recursion_level + 1); | ||
| 3190 | } | 3203 | } |
| 3191 | else if (BASE_EQ (car, Qor)) | 3204 | else if (BASE_EQ (car, Qor)) |
| 3192 | { | 3205 | { |
| @@ -3201,7 +3214,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred, | |||
| 3201 | FOR_EACH_TAIL (cdr) | 3214 | FOR_EACH_TAIL (cdr) |
| 3202 | { | 3215 | { |
| 3203 | if (!treesit_traverse_validate_predicate (XCAR (cdr), | 3216 | if (!treesit_traverse_validate_predicate (XCAR (cdr), |
| 3204 | signal_data)) | 3217 | signal_data, |
| 3218 | recursion_level + 1)) | ||
| 3205 | return false; | 3219 | return false; |
| 3206 | } | 3220 | } |
| 3207 | return true; | 3221 | return true; |
| @@ -3399,7 +3413,7 @@ Return the first matched node, or nil if none matches. */) | |||
| 3399 | CHECK_SYMBOL (backward); | 3413 | CHECK_SYMBOL (backward); |
| 3400 | 3414 | ||
| 3401 | Lisp_Object signal_data = Qnil; | 3415 | Lisp_Object signal_data = Qnil; |
| 3402 | if (!treesit_traverse_validate_predicate (predicate, &signal_data)) | 3416 | if (!treesit_traverse_validate_predicate (predicate, &signal_data, 0)) |
| 3403 | xsignal1 (Qtreesit_invalid_predicate, signal_data); | 3417 | xsignal1 (Qtreesit_invalid_predicate, signal_data); |
| 3404 | 3418 | ||
| 3405 | /* We use a default limit of 1000. See bug#59426 for the | 3419 | /* We use a default limit of 1000. See bug#59426 for the |
| @@ -3470,7 +3484,7 @@ always traverse leaf nodes first, then upwards. */) | |||
| 3470 | CHECK_SYMBOL (backward); | 3484 | CHECK_SYMBOL (backward); |
| 3471 | 3485 | ||
| 3472 | Lisp_Object signal_data = Qnil; | 3486 | Lisp_Object signal_data = Qnil; |
| 3473 | if (!treesit_traverse_validate_predicate (predicate, &signal_data)) | 3487 | if (!treesit_traverse_validate_predicate (predicate, &signal_data, 0)) |
| 3474 | xsignal1 (Qtreesit_invalid_predicate, signal_data); | 3488 | xsignal1 (Qtreesit_invalid_predicate, signal_data); |
| 3475 | 3489 | ||
| 3476 | treesit_initialize (); | 3490 | treesit_initialize (); |
| @@ -3587,7 +3601,7 @@ a regexp. */) | |||
| 3587 | CHECK_TS_NODE (root); | 3601 | CHECK_TS_NODE (root); |
| 3588 | 3602 | ||
| 3589 | Lisp_Object signal_data = Qnil; | 3603 | Lisp_Object signal_data = Qnil; |
| 3590 | if (!treesit_traverse_validate_predicate (predicate, &signal_data)) | 3604 | if (!treesit_traverse_validate_predicate (predicate, &signal_data, 0)) |
| 3591 | xsignal1 (Qtreesit_invalid_predicate, signal_data); | 3605 | xsignal1 (Qtreesit_invalid_predicate, signal_data); |
| 3592 | 3606 | ||
| 3593 | if (!NILP (process_fn)) | 3607 | if (!NILP (process_fn)) |
| @@ -3639,7 +3653,7 @@ if NODE matches PRED, nil otherwise. */) | |||
| 3639 | CHECK_TS_NODE (node); | 3653 | CHECK_TS_NODE (node); |
| 3640 | 3654 | ||
| 3641 | Lisp_Object signal_data = Qnil; | 3655 | Lisp_Object signal_data = Qnil; |
| 3642 | if (!treesit_traverse_validate_predicate (predicate, &signal_data)) | 3656 | if (!treesit_traverse_validate_predicate (predicate, &signal_data, 0)) |
| 3643 | xsignal1 (Qtreesit_invalid_predicate, signal_data); | 3657 | xsignal1 (Qtreesit_invalid_predicate, signal_data); |
| 3644 | 3658 | ||
| 3645 | Lisp_Object parser = XTS_NODE (node)->parser; | 3659 | Lisp_Object parser = XTS_NODE (node)->parser; |