Bintuils with patches for Dreamcast
Revision | 25162c795b1a2becf936bb3581d86a307ea491eb (tree) |
---|---|
Time | 2021-07-16 00:51:56 |
Author | Nick Clifton <nickc@redh...> |
Commiter | Nick Clifton |
Fix a stack exhaustion problem in the Rust demangling code in the libiberty library.
PR 99935
* rust-demangle.c: Add recursion limit.
@@ -1,3 +1,8 @@ | ||
1 | +2021-07-15 Nick Clifton <nickc@redhat.com> | |
2 | + | |
3 | + PR 99935 | |
4 | + * rust-demangle.c: Add recursion limit. | |
5 | + | |
1 | 6 | 2021-07-05 Nick Clifton <nickc@redhat.com> |
2 | 7 | |
3 | 8 | Reapply this change from commit: |
@@ -74,6 +74,12 @@ struct rust_demangler | ||
74 | 74 | /* Rust mangling version, with legacy mangling being -1. */ |
75 | 75 | int version; |
76 | 76 | |
77 | + /* Recursion depth. */ | |
78 | + uint recursion; | |
79 | + /* Maximum number of times demangle_path may be called recursively. */ | |
80 | +#define RUST_MAX_RECURSION_COUNT 1024 | |
81 | +#define RUST_NO_RECURSION_LIMIT ((uint) -1) | |
82 | + | |
77 | 83 | uint64_t bound_lifetime_depth; |
78 | 84 | }; |
79 | 85 |
@@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) | ||
671 | 677 | if (rdm->errored) |
672 | 678 | return; |
673 | 679 | |
680 | + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) | |
681 | + { | |
682 | + ++ rdm->recursion; | |
683 | + if (rdm->recursion > RUST_MAX_RECURSION_COUNT) | |
684 | + /* FIXME: There ought to be a way to report | |
685 | + that the recursion limit has been reached. */ | |
686 | + goto fail_return; | |
687 | + } | |
688 | + | |
674 | 689 | switch (tag = next (rdm)) |
675 | 690 | { |
676 | 691 | case 'C': |
@@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rdm, int in_value) | ||
688 | 703 | case 'N': |
689 | 704 | ns = next (rdm); |
690 | 705 | if (!ISLOWER (ns) && !ISUPPER (ns)) |
691 | - { | |
692 | - rdm->errored = 1; | |
693 | - return; | |
694 | - } | |
706 | + goto fail_return; | |
695 | 707 | |
696 | 708 | demangle_path (rdm, in_value); |
697 | 709 |
@@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) | ||
776 | 788 | } |
777 | 789 | break; |
778 | 790 | default: |
779 | - rdm->errored = 1; | |
780 | - return; | |
791 | + goto fail_return; | |
781 | 792 | } |
793 | + goto pass_return; | |
794 | + | |
795 | + fail_return: | |
796 | + rdm->errored = 1; | |
797 | + pass_return: | |
798 | + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) | |
799 | + -- rdm->recursion; | |
782 | 800 | } |
783 | 801 | |
784 | 802 | static void |
@@ -1320,6 +1338,7 @@ rust_demangle_callback (const char *mangled, int options, | ||
1320 | 1338 | rdm.skipping_printing = 0; |
1321 | 1339 | rdm.verbose = (options & DMGL_VERBOSE) != 0; |
1322 | 1340 | rdm.version = 0; |
1341 | + rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0; | |
1323 | 1342 | rdm.bound_lifetime_depth = 0; |
1324 | 1343 | |
1325 | 1344 | /* Rust symbols always start with _R (v0) or _ZN (legacy). */ |