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 *