Skip to content

Commit 28a9a20

Browse files
committed
Don't crash when assigning attributes of the GeneratorExit const singleton
1 parent f67d279 commit 28a9a20

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

py/mpconfig.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,16 @@ typedef long long mp_longint_impl_t;
773773
#define MICROPY_WARNINGS (0)
774774
#endif
775775

776+
// Whether to support chained exceptions
777+
#ifndef MICROPY_CPYTHON_EXCEPTION_CHAIN
778+
#define MICROPY_CPYTHON_EXCEPTION_CHAIN (0)
779+
#endif
780+
781+
// Whether the statically allocated GeneratorExit exception may be const
782+
#ifndef MICROPY_CONST_GENERATOREXIT_OBJ
783+
#define MICROPY_CONST_GENERATOREXIT_OBJ (!MICROPY_CPYTHON_EXCEPTION_CHAIN)
784+
#endif
785+
776786
// Whether to support warning categories
777787
#ifndef MICROPY_WARNINGS_CATEGORY
778788
#define MICROPY_WARNINGS_CATEGORY (0)

py/obj.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,9 @@ extern const struct _mp_obj_dict_t mp_const_empty_dict_obj;
791791
extern const struct _mp_obj_traceback_t mp_const_empty_traceback_obj;
792792
extern const struct _mp_obj_singleton_t mp_const_ellipsis_obj;
793793
extern const struct _mp_obj_singleton_t mp_const_notimplemented_obj;
794-
extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj;
794+
#if MICROPY_CONST_GENERATOREXIT_OBJ
795+
extern const struct _mp_obj_exception_t mp_static_GeneratorExit_obj;
796+
#endif
795797

796798
// Fixed empty map. Useful when calling keyword-receiving functions
797799
// without any keywords from C, etc.

py/objgenerator.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@
3838
#include "supervisor/shared/translate/translate.h"
3939

4040
// Instance of GeneratorExit exception - needed by generator.close()
41-
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, (mp_obj_tuple_t *)&mp_const_empty_tuple_obj, (mp_obj_traceback_t *)&mp_const_empty_traceback_obj};
41+
#if MICROPY_CONST_GENERATOREXIT_OBJ
42+
const
43+
#else
44+
static
45+
#endif
46+
mp_obj_exception_t mp_static_GeneratorExit_obj = {{&mp_type_GeneratorExit}, (mp_obj_tuple_t *)&mp_const_empty_tuple_obj, (mp_obj_traceback_t *)&mp_const_empty_traceback_obj};
4247

4348
/******************************************************************************/
4449
/* generator wrapper */
@@ -362,9 +367,19 @@ STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) {
362367
}
363368
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw);
364369

370+
static mp_obj_t generatorexit(void) {
371+
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
372+
MP_STATIC_ASSERT(!MICROPY_CONST_GENERATOREXIT_OBJ);
373+
mp_static_GeneratorExit_obj.context = NULL;
374+
mp_static_GeneratorExit_obj.cause = NULL;
375+
mp_static_GeneratorExit_obj.suppress_context = false;
376+
#endif
377+
return MP_OBJ_FROM_PTR(&mp_static_GeneratorExit_obj);
378+
}
379+
365380
STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {
366381
mp_obj_t ret;
367-
switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) {
382+
switch (mp_obj_gen_resume(self_in, mp_const_none, generatorexit(), &ret)) {
368383
case MP_VM_RETURN_YIELD:
369384
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("generator ignored GeneratorExit"));
370385

py/vm.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,10 @@ unwind_jump:;
13911391
// - constant GeneratorExit object, because it's const
13921392
// - exceptions re-raised by END_FINALLY
13931393
// - exceptions re-raised explicitly by "raise"
1394-
if (nlr.ret_val != &mp_const_GeneratorExit_obj
1394+
if ( true
1395+
#if MICROPY_CONST_GENERATOREXIT_OBJ
1396+
&& nlr.ret_val != &mp_static_GeneratorExit_obj
1397+
#endif
13951398
&& *code_state->ip != MP_BC_END_FINALLY
13961399
&& *code_state->ip != MP_BC_RAISE_LAST) {
13971400
const byte *ip = code_state->fun_bc->bytecode;

0 commit comments

Comments
 (0)