Disallow recursive xtrace (#46095)
@@ -23,6 +23,8 @@ | ||
23 | 23 | = The "array" built-in is now completely ignored in the POSIXly- |
24 | 24 | correct mode. The built-in, formerly a regular built-in, is now |
25 | 25 | categorized as an "extension" built-in. |
26 | + = The xtrace option is now ignored while expanding the $PS4 | |
27 | + variable to prevent possible infinite recursion. | |
26 | 28 | * The allexport option was wrongly ignored in many assignment |
27 | 29 | contexts. |
28 | 30 | * The errexit and errreturn options now work for assignment error |
@@ -822,10 +822,12 @@ | ||
822 | 822 | /* Prints a trace if the "xtrace" option is on. */ |
823 | 823 | void print_xtrace(void *const *argv) |
824 | 824 | { |
825 | + static bool expanding_ps4 = false; | |
826 | + | |
825 | 827 | bool tracevars = xtrace_buffer.contents != NULL |
826 | 828 | && xtrace_buffer.length > 0; |
827 | 829 | |
828 | - if (shopt_xtrace | |
830 | + if (shopt_xtrace && !expanding_ps4 | |
829 | 831 | && (!is_executing_auxiliary || shopt_traceall) |
830 | 832 | && (tracevars || argv != NULL) |
831 | 833 | #if YASH_ENABLE_LINEEDIT |
@@ -834,7 +836,12 @@ | ||
834 | 836 | ) { |
835 | 837 | bool first = true; |
836 | 838 | |
839 | + // Disallow recursion in case $PS4 contains a command substitution | |
840 | + // that may trigger another xtrace, which would be an infinite loop | |
841 | + expanding_ps4 = true; | |
837 | 842 | struct promptset_T prompt = get_prompt(4); |
843 | + expanding_ps4 = false; | |
844 | + | |
838 | 845 | print_prompt(prompt.main); |
839 | 846 | print_prompt(prompt.styler); |
840 | 847 |