Mercurial > vim
comparison src/ex_eval.c @ 30483:4bbc920bdef7 v9.0.0577
patch 9.0.0577: buffer underflow with unexpected :finally
Commit: https://github.com/vim/vim/commit/96b9bf8f74af8abf1e30054f996708db7dc285be
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Sep 24 17:24:12 2022 +0100
patch 9.0.0577: buffer underflow with unexpected :finally
Problem: Buffer underflow with unexpected :finally.
Solution: Check CSF_TRY can be found.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 24 Sep 2022 18:30:04 +0200 |
parents | 7fc27d7ce3b0 |
children | 37aa9fd2ed72 |
comparison
equal
deleted
inserted
replaced
30482:dc376deb7e21 | 30483:4bbc920bdef7 |
---|---|
1933 cstack_T *cstack = eap->cstack; | 1933 cstack_T *cstack = eap->cstack; |
1934 | 1934 |
1935 if (cmdmod_error(FALSE)) | 1935 if (cmdmod_error(FALSE)) |
1936 return; | 1936 return; |
1937 | 1937 |
1938 if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) | 1938 for (idx = cstack->cs_idx; idx >= 0; --idx) |
1939 if (cstack->cs_flags[idx] & CSF_TRY) | |
1940 break; | |
1941 if (cstack->cs_trylevel <= 0 || idx < 0) | |
1942 { | |
1939 eap->errmsg = _(e_finally_without_try); | 1943 eap->errmsg = _(e_finally_without_try); |
1940 else | 1944 return; |
1941 { | 1945 } |
1942 if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) | 1946 |
1943 { | 1947 if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) |
1944 eap->errmsg = get_end_emsg(cstack); | 1948 { |
1945 for (idx = cstack->cs_idx - 1; idx > 0; --idx) | 1949 eap->errmsg = get_end_emsg(cstack); |
1946 if (cstack->cs_flags[idx] & CSF_TRY) | 1950 // Make this error pending, so that the commands in the following |
1947 break; | 1951 // finally clause can be executed. This overrules also a pending |
1948 // Make this error pending, so that the commands in the following | 1952 // ":continue", ":break", ":return", or ":finish". |
1949 // finally clause can be executed. This overrules also a pending | 1953 pending = CSTP_ERROR; |
1950 // ":continue", ":break", ":return", or ":finish". | 1954 } |
1951 pending = CSTP_ERROR; | 1955 |
1952 } | 1956 if (cstack->cs_flags[idx] & CSF_FINALLY) |
1953 else | 1957 { |
1954 idx = cstack->cs_idx; | 1958 // Give up for a multiple ":finally" and ignore it. |
1955 | 1959 eap->errmsg = _(e_multiple_finally); |
1956 if (cstack->cs_flags[idx] & CSF_FINALLY) | 1960 return; |
1957 { | 1961 } |
1958 // Give up for a multiple ":finally" and ignore it. | 1962 rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, |
1959 eap->errmsg = _(e_multiple_finally); | 1963 &cstack->cs_looplevel); |
1960 return; | 1964 |
1961 } | 1965 /* |
1962 rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, | 1966 * Don't do something when the corresponding try block never got active |
1963 &cstack->cs_looplevel); | 1967 * (because of an inactive surrounding conditional or after an error or |
1968 * interrupt or throw) or for a ":finally" without ":try" or a multiple | |
1969 * ":finally". After every other error (did_emsg or the conditional | |
1970 * errors detected above) or after an interrupt (got_int) or an | |
1971 * exception (did_throw), the finally clause must be executed. | |
1972 */ | |
1973 skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); | |
1974 | |
1975 if (!skip) | |
1976 { | |
1977 // When debugging or a breakpoint was encountered, display the | |
1978 // debug prompt (if not already done). The user then knows that the | |
1979 // finally clause is executed. | |
1980 if (dbg_check_skipped(eap)) | |
1981 { | |
1982 // Handle a ">quit" debug command as if an interrupt had | |
1983 // occurred before the ":finally". That is, discard the | |
1984 // original exception and replace it by an interrupt | |
1985 // exception. | |
1986 (void)do_intthrow(cstack); | |
1987 } | |
1964 | 1988 |
1965 /* | 1989 /* |
1966 * Don't do something when the corresponding try block never got active | 1990 * If there is a preceding catch clause and it caught the exception, |
1967 * (because of an inactive surrounding conditional or after an error or | 1991 * finish the exception now. This happens also after errors except |
1968 * interrupt or throw) or for a ":finally" without ":try" or a multiple | 1992 * when this is a multiple ":finally" or one not within a ":try". |
1969 * ":finally". After every other error (did_emsg or the conditional | 1993 * After an error or interrupt, this also discards a pending |
1970 * errors detected above) or after an interrupt (got_int) or an | 1994 * ":continue", ":break", ":finish", or ":return" from the preceding |
1971 * exception (did_throw), the finally clause must be executed. | 1995 * try block or catch clause. |
1972 */ | 1996 */ |
1973 skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); | 1997 cleanup_conditionals(cstack, CSF_TRY, FALSE); |
1974 | 1998 |
1975 if (!skip) | 1999 if (cstack->cs_idx >= 0 |
1976 { | 2000 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) |
1977 // When debugging or a breakpoint was encountered, display the | 2001 { |
1978 // debug prompt (if not already done). The user then knows that the | 2002 // Variables declared in the previous block can no longer be |
1979 // finally clause is executed. | 2003 // used. |
1980 if (dbg_check_skipped(eap)) | 2004 leave_block(cstack); |
2005 enter_block(cstack); | |
2006 } | |
2007 | |
2008 /* | |
2009 * Make did_emsg, got_int, did_throw pending. If set, they overrule | |
2010 * a pending ":continue", ":break", ":return", or ":finish". Then | |
2011 * we have particularly to discard a pending return value (as done | |
2012 * by the call to cleanup_conditionals() above when did_emsg or | |
2013 * got_int is set). The pending values are restored by the | |
2014 * ":endtry", except if there is a new error, interrupt, exception, | |
2015 * ":continue", ":break", ":return", or ":finish" in the following | |
2016 * finally clause. A missing ":endwhile", ":endfor" or ":endif" | |
2017 * detected here is treated as if did_emsg and did_throw had | |
2018 * already been set, respectively in case that the error is not | |
2019 * converted to an exception, did_throw had already been unset. | |
2020 * We must not set did_emsg here since that would suppress the | |
2021 * error message. | |
2022 */ | |
2023 if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) | |
2024 { | |
2025 if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) | |
1981 { | 2026 { |
1982 // Handle a ">quit" debug command as if an interrupt had | 2027 report_discard_pending(CSTP_RETURN, |
1983 // occurred before the ":finally". That is, discard the | 2028 cstack->cs_rettv[cstack->cs_idx]); |
1984 // original exception and replace it by an interrupt | 2029 discard_pending_return(cstack->cs_rettv[cstack->cs_idx]); |
1985 // exception. | |
1986 (void)do_intthrow(cstack); | |
1987 } | 2030 } |
1988 | 2031 if (pending == CSTP_ERROR && !did_emsg) |
1989 /* | 2032 pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0; |
1990 * If there is a preceding catch clause and it caught the exception, | 2033 else |
1991 * finish the exception now. This happens also after errors except | 2034 pending |= did_throw ? CSTP_THROW : 0; |
1992 * when this is a multiple ":finally" or one not within a ":try". | 2035 pending |= did_emsg ? CSTP_ERROR : 0; |
1993 * After an error or interrupt, this also discards a pending | 2036 pending |= got_int ? CSTP_INTERRUPT : 0; |
1994 * ":continue", ":break", ":finish", or ":return" from the preceding | 2037 cstack->cs_pending[cstack->cs_idx] = pending; |
1995 * try block or catch clause. | 2038 |
1996 */ | 2039 // It's mandatory that the current exception is stored in the |
1997 cleanup_conditionals(cstack, CSF_TRY, FALSE); | 2040 // cstack so that it can be rethrown at the ":endtry" or be |
1998 | 2041 // discarded if the finally clause is left by a ":continue", |
1999 if (cstack->cs_idx >= 0 | 2042 // ":break", ":return", ":finish", error, interrupt, or another |
2000 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) | 2043 // exception. When emsg() is called for a missing ":endif" or |
2001 { | 2044 // a missing ":endwhile"/":endfor" detected here, the |
2002 // Variables declared in the previous block can no longer be | 2045 // exception will be discarded. |
2003 // used. | 2046 if (did_throw && cstack->cs_exception[cstack->cs_idx] |
2004 leave_block(cstack); | 2047 != current_exception) |
2005 enter_block(cstack); | 2048 internal_error("ex_finally()"); |
2006 } | 2049 } |
2007 | 2050 |
2008 /* | 2051 /* |
2009 * Make did_emsg, got_int, did_throw pending. If set, they overrule | 2052 * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, |
2010 * a pending ":continue", ":break", ":return", or ":finish". Then | 2053 * got_int, and did_throw and make the finally clause active. |
2011 * we have particularly to discard a pending return value (as done | 2054 * This will happen after emsg() has been called for a missing |
2012 * by the call to cleanup_conditionals() above when did_emsg or | 2055 * ":endif" or a missing ":endwhile"/":endfor" detected here, so |
2013 * got_int is set). The pending values are restored by the | 2056 * that the following finally clause will be executed even then. |
2014 * ":endtry", except if there is a new error, interrupt, exception, | 2057 */ |
2015 * ":continue", ":break", ":return", or ":finish" in the following | 2058 cstack->cs_lflags |= CSL_HAD_FINA; |
2016 * finally clause. A missing ":endwhile", ":endfor" or ":endif" | |
2017 * detected here is treated as if did_emsg and did_throw had | |
2018 * already been set, respectively in case that the error is not | |
2019 * converted to an exception, did_throw had already been unset. | |
2020 * We must not set did_emsg here since that would suppress the | |
2021 * error message. | |
2022 */ | |
2023 if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) | |
2024 { | |
2025 if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) | |
2026 { | |
2027 report_discard_pending(CSTP_RETURN, | |
2028 cstack->cs_rettv[cstack->cs_idx]); | |
2029 discard_pending_return(cstack->cs_rettv[cstack->cs_idx]); | |
2030 } | |
2031 if (pending == CSTP_ERROR && !did_emsg) | |
2032 pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0; | |
2033 else | |
2034 pending |= did_throw ? CSTP_THROW : 0; | |
2035 pending |= did_emsg ? CSTP_ERROR : 0; | |
2036 pending |= got_int ? CSTP_INTERRUPT : 0; | |
2037 cstack->cs_pending[cstack->cs_idx] = pending; | |
2038 | |
2039 // It's mandatory that the current exception is stored in the | |
2040 // cstack so that it can be rethrown at the ":endtry" or be | |
2041 // discarded if the finally clause is left by a ":continue", | |
2042 // ":break", ":return", ":finish", error, interrupt, or another | |
2043 // exception. When emsg() is called for a missing ":endif" or | |
2044 // a missing ":endwhile"/":endfor" detected here, the | |
2045 // exception will be discarded. | |
2046 if (did_throw && cstack->cs_exception[cstack->cs_idx] | |
2047 != current_exception) | |
2048 internal_error("ex_finally()"); | |
2049 } | |
2050 | |
2051 /* | |
2052 * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, | |
2053 * got_int, and did_throw and make the finally clause active. | |
2054 * This will happen after emsg() has been called for a missing | |
2055 * ":endif" or a missing ":endwhile"/":endfor" detected here, so | |
2056 * that the following finally clause will be executed even then. | |
2057 */ | |
2058 cstack->cs_lflags |= CSL_HAD_FINA; | |
2059 } | |
2060 } | 2059 } |
2061 } | 2060 } |
2062 | 2061 |
2063 /* | 2062 /* |
2064 * ":endtry" | 2063 * ":endtry" |
2074 cstack_T *cstack = eap->cstack; | 2073 cstack_T *cstack = eap->cstack; |
2075 | 2074 |
2076 if (cmdmod_error(FALSE)) | 2075 if (cmdmod_error(FALSE)) |
2077 return; | 2076 return; |
2078 | 2077 |
2079 if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) | 2078 for (idx = cstack->cs_idx; idx >= 0; --idx) |
2079 if (cstack->cs_flags[idx] & CSF_TRY) | |
2080 break; | |
2081 if (cstack->cs_trylevel <= 0 || idx < 0) | |
2082 { | |
2080 eap->errmsg = _(e_endtry_without_try); | 2083 eap->errmsg = _(e_endtry_without_try); |
2081 else | 2084 return; |
2082 { | 2085 } |
2086 | |
2087 /* | |
2088 * Don't do something after an error, interrupt or throw in the try | |
2089 * block, catch clause, or finally clause preceding this ":endtry" or | |
2090 * when an error or interrupt occurred after a ":continue", ":break", | |
2091 * ":return", or ":finish" in a try block or catch clause preceding this | |
2092 * ":endtry" or when the try block never got active (because of an | |
2093 * inactive surrounding conditional or after an error or interrupt or | |
2094 * throw) or when there is a surrounding conditional and it has been | |
2095 * made inactive by a ":continue", ":break", ":return", or ":finish" in | |
2096 * the finally clause. The latter case need not be tested since then | |
2097 * anything pending has already been discarded. */ | |
2098 skip = did_emsg || got_int || did_throw | |
2099 || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); | |
2100 | |
2101 if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) | |
2102 { | |
2103 eap->errmsg = get_end_emsg(cstack); | |
2104 | |
2105 // Find the matching ":try" and report what's missing. | |
2106 rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, | |
2107 &cstack->cs_looplevel); | |
2108 skip = TRUE; | |
2109 | |
2083 /* | 2110 /* |
2084 * Don't do something after an error, interrupt or throw in the try | 2111 * If an exception is being thrown, discard it to prevent it from |
2085 * block, catch clause, or finally clause preceding this ":endtry" or | 2112 * being rethrown at the end of this function. It would be |
2086 * when an error or interrupt occurred after a ":continue", ":break", | 2113 * discarded by the error message, anyway. Resets did_throw. |
2087 * ":return", or ":finish" in a try block or catch clause preceding this | 2114 * This does not affect the script termination due to the error |
2088 * ":endtry" or when the try block never got active (because of an | 2115 * since "trylevel" is decremented after emsg() has been called. |
2089 * inactive surrounding conditional or after an error or interrupt or | 2116 */ |
2090 * throw) or when there is a surrounding conditional and it has been | 2117 if (did_throw) |
2091 * made inactive by a ":continue", ":break", ":return", or ":finish" in | 2118 discard_current_exception(); |
2092 * the finally clause. The latter case need not be tested since then | 2119 |
2093 * anything pending has already been discarded. */ | 2120 // report eap->errmsg, also when there already was an error |
2094 skip = did_emsg || got_int || did_throw | 2121 did_emsg = FALSE; |
2095 || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); | 2122 } |
2096 | 2123 else |
2097 if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) | 2124 { |
2098 { | 2125 idx = cstack->cs_idx; |
2099 eap->errmsg = get_end_emsg(cstack); | 2126 |
2100 | 2127 // Check the flags only when not in a skipped block. |
2101 // Find the matching ":try" and report what's missing. | 2128 if (!skip && in_vim9script() |
2102 idx = cstack->cs_idx; | 2129 && (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0) |
2103 do | 2130 { |
2104 --idx; | 2131 // try/endtry without any catch or finally: give an error and |
2105 while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); | 2132 // continue. |
2106 rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, | 2133 eap->errmsg = _(e_missing_catch_or_finally); |
2107 &cstack->cs_looplevel); | 2134 } |
2135 | |
2136 /* | |
2137 * If we stopped with the exception currently being thrown at this | |
2138 * try conditional since we didn't know that it doesn't have | |
2139 * a finally clause, we need to rethrow it after closing the try | |
2140 * conditional. | |
2141 */ | |
2142 if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE) | |
2143 && !(cstack->cs_flags[idx] & CSF_FINALLY)) | |
2144 rethrow = TRUE; | |
2145 } | |
2146 | |
2147 // If there was no finally clause, show the user when debugging or | |
2148 // a breakpoint was encountered that the end of the try conditional has | |
2149 // been reached: display the debug prompt (if not already done). Do | |
2150 // this on normal control flow or when an exception was thrown, but not | |
2151 // on an interrupt or error not converted to an exception or when | |
2152 // a ":break", ":continue", ":return", or ":finish" is pending. These | |
2153 // actions are carried out immediately. | |
2154 if ((rethrow || (!skip && !(cstack->cs_flags[idx] & CSF_FINALLY) | |
2155 && !cstack->cs_pending[idx])) | |
2156 && dbg_check_skipped(eap)) | |
2157 { | |
2158 // Handle a ">quit" debug command as if an interrupt had occurred | |
2159 // before the ":endtry". That is, throw an interrupt exception and | |
2160 // set "skip" and "rethrow". | |
2161 if (got_int) | |
2162 { | |
2108 skip = TRUE; | 2163 skip = TRUE; |
2109 | 2164 (void)do_intthrow(cstack); |
2110 /* | 2165 // The do_intthrow() call may have reset did_throw or |
2111 * If an exception is being thrown, discard it to prevent it from | 2166 // cstack->cs_pending[idx]. |
2112 * being rethrown at the end of this function. It would be | 2167 rethrow = FALSE; |
2113 * discarded by the error message, anyway. Resets did_throw. | 2168 if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY)) |
2114 * This does not affect the script termination due to the error | |
2115 * since "trylevel" is decremented after emsg() has been called. | |
2116 */ | |
2117 if (did_throw) | |
2118 discard_current_exception(); | |
2119 | |
2120 // report eap->errmsg, also when there already was an error | |
2121 did_emsg = FALSE; | |
2122 } | |
2123 else | |
2124 { | |
2125 idx = cstack->cs_idx; | |
2126 | |
2127 // Check the flags only when not in a skipped block. | |
2128 if (!skip && in_vim9script() | |
2129 && (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0) | |
2130 { | |
2131 // try/endtry without any catch or finally: give an error and | |
2132 // continue. | |
2133 eap->errmsg = _(e_missing_catch_or_finally); | |
2134 } | |
2135 | |
2136 /* | |
2137 * If we stopped with the exception currently being thrown at this | |
2138 * try conditional since we didn't know that it doesn't have | |
2139 * a finally clause, we need to rethrow it after closing the try | |
2140 * conditional. | |
2141 */ | |
2142 if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE) | |
2143 && !(cstack->cs_flags[idx] & CSF_FINALLY)) | |
2144 rethrow = TRUE; | 2169 rethrow = TRUE; |
2145 } | 2170 } |
2146 | 2171 } |
2147 // If there was no finally clause, show the user when debugging or | 2172 |
2148 // a breakpoint was encountered that the end of the try conditional has | 2173 /* |
2149 // been reached: display the debug prompt (if not already done). Do | 2174 * If a ":return" is pending, we need to resume it after closing the |
2150 // this on normal control flow or when an exception was thrown, but not | 2175 * try conditional; remember the return value. If there was a finally |
2151 // on an interrupt or error not converted to an exception or when | 2176 * clause making an exception pending, we need to rethrow it. Make it |
2152 // a ":break", ":continue", ":return", or ":finish" is pending. These | 2177 * the exception currently being thrown. |
2153 // actions are carried out immediately. | 2178 */ |
2154 if ((rethrow || (!skip | 2179 if (!skip) |
2155 && !(cstack->cs_flags[idx] & CSF_FINALLY) | 2180 { |
2156 && !cstack->cs_pending[idx])) | 2181 pending = cstack->cs_pending[idx]; |
2157 && dbg_check_skipped(eap)) | 2182 cstack->cs_pending[idx] = CSTP_NONE; |
2158 { | 2183 if (pending == CSTP_RETURN) |
2159 // Handle a ">quit" debug command as if an interrupt had occurred | 2184 rettv = cstack->cs_rettv[idx]; |
2160 // before the ":endtry". That is, throw an interrupt exception and | 2185 else if (pending & CSTP_THROW) |
2161 // set "skip" and "rethrow". | 2186 current_exception = cstack->cs_exception[idx]; |
2162 if (got_int) | 2187 } |
2163 { | 2188 |
2164 skip = TRUE; | 2189 /* |
2165 (void)do_intthrow(cstack); | 2190 * Discard anything pending on an error, interrupt, or throw in the |
2166 // The do_intthrow() call may have reset did_throw or | 2191 * finally clause. If there was no ":finally", discard a pending |
2167 // cstack->cs_pending[idx]. | 2192 * ":continue", ":break", ":return", or ":finish" if an error or |
2168 rethrow = FALSE; | 2193 * interrupt occurred afterwards, but before the ":endtry" was reached. |
2169 if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY)) | 2194 * If an exception was caught by the last of the catch clauses and there |
2170 rethrow = TRUE; | 2195 * was no finally clause, finish the exception now. This happens also |
2171 } | 2196 * after errors except when this ":endtry" is not within a ":try". |
2172 } | 2197 * Restore "emsg_silent" if it has been reset by this try conditional. |
2173 | 2198 */ |
2174 /* | 2199 (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); |
2175 * If a ":return" is pending, we need to resume it after closing the | 2200 |
2176 * try conditional; remember the return value. If there was a finally | 2201 if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) |
2177 * clause making an exception pending, we need to rethrow it. Make it | 2202 leave_block(cstack); |
2178 * the exception currently being thrown. | 2203 --cstack->cs_trylevel; |
2179 */ | 2204 |
2180 if (!skip) | 2205 if (!skip) |
2181 { | 2206 { |
2182 pending = cstack->cs_pending[idx]; | 2207 report_resume_pending(pending, |
2183 cstack->cs_pending[idx] = CSTP_NONE; | |
2184 if (pending == CSTP_RETURN) | |
2185 rettv = cstack->cs_rettv[idx]; | |
2186 else if (pending & CSTP_THROW) | |
2187 current_exception = cstack->cs_exception[idx]; | |
2188 } | |
2189 | |
2190 /* | |
2191 * Discard anything pending on an error, interrupt, or throw in the | |
2192 * finally clause. If there was no ":finally", discard a pending | |
2193 * ":continue", ":break", ":return", or ":finish" if an error or | |
2194 * interrupt occurred afterwards, but before the ":endtry" was reached. | |
2195 * If an exception was caught by the last of the catch clauses and there | |
2196 * was no finally clause, finish the exception now. This happens also | |
2197 * after errors except when this ":endtry" is not within a ":try". | |
2198 * Restore "emsg_silent" if it has been reset by this try conditional. | |
2199 */ | |
2200 (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); | |
2201 | |
2202 if (cstack->cs_idx >= 0 | |
2203 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) | |
2204 leave_block(cstack); | |
2205 --cstack->cs_trylevel; | |
2206 | |
2207 if (!skip) | |
2208 { | |
2209 report_resume_pending(pending, | |
2210 (pending == CSTP_RETURN) ? rettv : | 2208 (pending == CSTP_RETURN) ? rettv : |
2211 (pending & CSTP_THROW) ? (void *)current_exception : NULL); | 2209 (pending & CSTP_THROW) ? (void *)current_exception : NULL); |
2212 switch (pending) | 2210 switch (pending) |
2213 { | 2211 { |
2214 case CSTP_NONE: | 2212 case CSTP_NONE: |
2215 break; | 2213 break; |
2216 | 2214 |
2217 // Reactivate a pending ":continue", ":break", ":return", | 2215 // Reactivate a pending ":continue", ":break", ":return", |
2218 // ":finish" from the try block or a catch clause of this try | 2216 // ":finish" from the try block or a catch clause of this try |
2219 // conditional. This is skipped, if there was an error in an | 2217 // conditional. This is skipped, if there was an error in an |
2220 // (unskipped) conditional command or an interrupt afterwards | 2218 // (unskipped) conditional command or an interrupt afterwards |
2221 // or if the finally clause is present and executed a new error, | 2219 // or if the finally clause is present and executed a new error, |
2222 // interrupt, throw, ":continue", ":break", ":return", or | 2220 // interrupt, throw, ":continue", ":break", ":return", or |
2223 // ":finish". | 2221 // ":finish". |
2224 case CSTP_CONTINUE: | 2222 case CSTP_CONTINUE: |
2225 ex_continue(eap); | 2223 ex_continue(eap); |
2226 break; | 2224 break; |
2227 case CSTP_BREAK: | 2225 case CSTP_BREAK: |
2228 ex_break(eap); | 2226 ex_break(eap); |
2229 break; | 2227 break; |
2230 case CSTP_RETURN: | 2228 case CSTP_RETURN: |
2231 do_return(eap, FALSE, FALSE, rettv); | 2229 do_return(eap, FALSE, FALSE, rettv); |
2232 break; | 2230 break; |
2233 case CSTP_FINISH: | 2231 case CSTP_FINISH: |
2234 do_finish(eap, FALSE); | 2232 do_finish(eap, FALSE); |
2235 break; | 2233 break; |
2236 | 2234 |
2237 // When the finally clause was entered due to an error, | 2235 // When the finally clause was entered due to an error, |
2238 // interrupt or throw (as opposed to a ":continue", ":break", | 2236 // interrupt or throw (as opposed to a ":continue", ":break", |
2239 // ":return", or ":finish"), restore the pending values of | 2237 // ":return", or ":finish"), restore the pending values of |
2240 // did_emsg, got_int, and did_throw. This is skipped, if there | 2238 // did_emsg, got_int, and did_throw. This is skipped, if there |
2241 // was a new error, interrupt, throw, ":continue", ":break", | 2239 // was a new error, interrupt, throw, ":continue", ":break", |
2242 // ":return", or ":finish". in the finally clause. | 2240 // ":return", or ":finish". in the finally clause. |
2243 default: | 2241 default: |
2244 if (pending & CSTP_ERROR) | 2242 if (pending & CSTP_ERROR) |
2245 did_emsg = TRUE; | 2243 did_emsg = TRUE; |
2246 if (pending & CSTP_INTERRUPT) | 2244 if (pending & CSTP_INTERRUPT) |
2247 got_int = TRUE; | 2245 got_int = TRUE; |
2248 if (pending & CSTP_THROW) | 2246 if (pending & CSTP_THROW) |
2249 rethrow = TRUE; | 2247 rethrow = TRUE; |
2250 break; | 2248 break; |
2251 } | 2249 } |
2252 } | 2250 } |
2253 | 2251 |
2254 if (rethrow) | 2252 if (rethrow) |
2255 // Rethrow the current exception (within this cstack). | 2253 // Rethrow the current exception (within this cstack). |
2256 do_throw(cstack); | 2254 do_throw(cstack); |
2257 } | |
2258 } | 2255 } |
2259 | 2256 |
2260 /* | 2257 /* |
2261 * enter_cleanup() and leave_cleanup() | 2258 * enter_cleanup() and leave_cleanup() |
2262 * | 2259 * |