@@ -21,7 +21,8 @@ static PyMemberDef frame_memberlist[] = {
21
21
static PyObject *
22
22
frame_getlocals (PyFrameObject * f , void * closure )
23
23
{
24
- PyFrame_FastToLocals (f );
24
+ if (PyFrame_FastToLocalsWithError (f ) < 0 )
25
+ return NULL ;
25
26
Py_INCREF (f -> f_locals );
26
27
return f -> f_locals ;
27
28
}
@@ -772,12 +773,9 @@ PyFrame_BlockPop(PyFrameObject *f)
772
773
If deref is true, then the values being copied are cell variables
773
774
and the value is extracted from the cell variable before being put
774
775
in dict.
775
-
776
- Exceptions raised while modifying the dict are silently ignored,
777
- because there is no good way to report them.
778
776
*/
779
777
780
- static void
778
+ static int
781
779
map_to_dict (PyObject * map , Py_ssize_t nmap , PyObject * dict , PyObject * * values ,
782
780
int deref )
783
781
{
@@ -794,14 +792,19 @@ map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
794
792
value = PyCell_GET (value );
795
793
}
796
794
if (value == NULL ) {
797
- if (PyObject_DelItem (dict , key ) != 0 )
798
- PyErr_Clear ();
795
+ if (PyObject_DelItem (dict , key ) != 0 ) {
796
+ if (PyErr_ExceptionMatches (PyExc_KeyError ))
797
+ PyErr_Clear ();
798
+ else
799
+ return -1 ;
800
+ }
799
801
}
800
802
else {
801
803
if (PyObject_SetItem (dict , key , value ) != 0 )
802
- PyErr_Clear () ;
804
+ return -1 ;
803
805
}
804
806
}
807
+ return 0 ;
805
808
}
806
809
807
810
/* Copy values from the "locals" dict into the fast locals.
@@ -858,42 +861,49 @@ dict_to_map(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
858
861
}
859
862
}
860
863
861
- void
862
- PyFrame_FastToLocals (PyFrameObject * f )
864
+ int
865
+ PyFrame_FastToLocalsWithError (PyFrameObject * f )
863
866
{
864
867
/* Merge fast locals into f->f_locals */
865
868
PyObject * locals , * map ;
866
869
PyObject * * fast ;
867
- PyObject * error_type , * error_value , * error_traceback ;
868
870
PyCodeObject * co ;
869
871
Py_ssize_t j ;
870
872
Py_ssize_t ncells , nfreevars ;
871
- if (f == NULL )
872
- return ;
873
+
874
+ if (f == NULL ) {
875
+ PyErr_BadInternalCall ();
876
+ return -1 ;
877
+ }
873
878
locals = f -> f_locals ;
874
879
if (locals == NULL ) {
875
880
locals = f -> f_locals = PyDict_New ();
876
- if (locals == NULL ) {
877
- PyErr_Clear (); /* Can't report it :-( */
878
- return ;
879
- }
881
+ if (locals == NULL )
882
+ return -1 ;
880
883
}
881
884
co = f -> f_code ;
882
885
map = co -> co_varnames ;
883
- if (!PyTuple_Check (map ))
884
- return ;
885
- PyErr_Fetch (& error_type , & error_value , & error_traceback );
886
+ if (!PyTuple_Check (map )) {
887
+ PyErr_Format (PyExc_SystemError ,
888
+ "co_varnames must be a tuple, not %s" ,
889
+ Py_TYPE (map )-> tp_name );
890
+ return -1 ;
891
+ }
886
892
fast = f -> f_localsplus ;
887
893
j = PyTuple_GET_SIZE (map );
888
894
if (j > co -> co_nlocals )
889
895
j = co -> co_nlocals ;
890
- if (co -> co_nlocals )
891
- map_to_dict (map , j , locals , fast , 0 );
896
+ if (co -> co_nlocals ) {
897
+ if (map_to_dict (map , j , locals , fast , 0 ) < 0 )
898
+ return -1 ;
899
+ }
892
900
ncells = PyTuple_GET_SIZE (co -> co_cellvars );
893
901
nfreevars = PyTuple_GET_SIZE (co -> co_freevars );
894
902
if (ncells || nfreevars ) {
895
- map_to_dict (co -> co_cellvars , ncells ,
896
- locals , fast + co -> co_nlocals , 1 );
903
+ if (map_to_dict (co -> co_cellvars , ncells ,
904
+ locals , fast + co -> co_nlocals , 1 ))
905
+ return -1 ;
906
+
897
907
/* If the namespace is unoptimized, then one of the
898
908
following cases applies:
899
909
1. It does not contain free variables, because it
@@ -903,11 +913,24 @@ PyFrame_FastToLocals(PyFrameObject *f)
903
913
into the locals dict used by the class.
904
914
*/
905
915
if (co -> co_flags & CO_OPTIMIZED ) {
906
- map_to_dict (co -> co_freevars , nfreevars ,
907
- locals , fast + co -> co_nlocals + ncells , 1 );
916
+ if (map_to_dict (co -> co_freevars , nfreevars ,
917
+ locals , fast + co -> co_nlocals + ncells , 1 ) < 0 )
918
+ return -1 ;
908
919
}
909
920
}
910
- PyErr_Restore (error_type , error_value , error_traceback );
921
+ return 0 ;
922
+ }
923
+
924
+ void
925
+ PyFrame_FastToLocals (PyFrameObject * f )
926
+ {
927
+ int res ;
928
+
929
+ assert (!PyErr_Occurred ());
930
+
931
+ res = PyFrame_FastToLocalsWithError (f );
932
+ if (res < 0 )
933
+ PyErr_Clear ();
911
934
}
912
935
913
936
void
0 commit comments