File tree Expand file tree Collapse file tree 3 files changed +33
-5
lines changed Expand file tree Collapse file tree 3 files changed +33
-5
lines changed Original file line number Diff line number Diff line change @@ -523,6 +523,18 @@ def test_code_equal_with_instrumentation(self):
523523        self .assertNotEqual (code1 , code2 )
524524        sys .settrace (None )
525525
526+     def  test_co_stacksize_overflow (self ):
527+         # See: https://github.com/python/cpython/issues/126119. 
528+ 
529+         # Since co_framesize = nlocalsplus + co_stacksize + FRAME_SPECIALS_SIZE, 
530+         # we need to check that co_stacksize is not too large. We could fortify 
531+         # the test by explicitly checking that bound, but this needs to expose 
532+         # FRAME_SPECIALS_SIZE and a getter for 'nlocalsplus'. 
533+ 
534+         c  =  (lambda : ...).__code__ 
535+         with  self .assertRaisesRegex (OverflowError , "co_stacksize" ):
536+             c .__replace__ (co_stacksize = 2147483647 )
537+ 
526538
527539def  isinterned (s ):
528540    return  s  is  sys .intern (('_'  +  s  +  '_' )[1 :- 1 ])
Original file line number Diff line number Diff line change @@ -436,7 +436,12 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
436436        PyErr_SetString (PyExc_ValueError , "code: co_varnames is too small" );
437437        return  -1 ;
438438    }
439- 
439+     /* Ensure that the framesize will not overflow */ 
440+     int  nlocalsplus  =  (int )PyTuple_GET_SIZE (con -> localsplusnames );
441+     if  (con -> stacksize  >= INT_MAX  -  nlocalsplus  -  FRAME_SPECIALS_SIZE ) {
442+         PyErr_SetString (PyExc_OverflowError , "code: co_stacksize is too large" );
443+         return  -1 ;
444+     }
440445    return  0 ;
441446}
442447
Original file line number Diff line number Diff line change @@ -1804,11 +1804,22 @@ PyDoc_STRVAR(clear__doc__,
18041804static  PyObject  * 
18051805frame_sizeof (PyFrameObject  * f , PyObject  * Py_UNUSED (ignored ))
18061806{
1807-     Py_ssize_t  res ; 
1808-     res   =  offsetof( PyFrameObject ,  _f_frame_data )  +  offsetof(_PyInterpreterFrame , localsplus );
1807+     Py_ssize_t  res   =  offsetof( PyFrameObject ,  _f_frame_data ) 
1808+                       +  offsetof(_PyInterpreterFrame , localsplus );
18091809    PyCodeObject  * code  =  _PyFrame_GetCode (f -> f_frame );
1810-     res  +=  _PyFrame_NumSlotsForCodeObject (code ) *  sizeof (PyObject  * );
1811-     return  PyLong_FromSsize_t (res );
1810+     int  nslots  =  _PyFrame_NumSlotsForCodeObject (code );
1811+     assert (nslots  >= 0 );
1812+     if  ((size_t )nslots  >= (PY_SSIZE_T_MAX  -  res ) / sizeof (PyObject  * )) {
1813+         // This could happen if the underlying code object has a 
1814+         // very large stacksize (but at most INT_MAX) yet that the 
1815+         // above offsets make the result overflow. 
1816+         // 
1817+         // This should normally only happen if PY_SSIZE_T_MAX == INT_MAX, 
1818+         // but we anyway raise an exception on other systems for safety. 
1819+         PyErr_SetString (PyExc_OverflowError , "size exceeds PY_SSIZE_T_MAX" );
1820+         return  NULL ;
1821+     }
1822+     return  PyLong_FromSsize_t (res  +  nslots  *  sizeof (PyObject  * ));
18121823}
18131824
18141825PyDoc_STRVAR (sizeof__doc__ ,
 
 
   
 
     
   
   
          
    
    
     
    
      
     
     
    You can’t perform that action at this time.
  
 
    
  
    
      
        
     
       
      
     
   
 
    
    
  
 
  
 
     
    
0 commit comments