mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	[3.11] GH-94438: Backport GH-94444 (#94486)
* Account for NULLs on evaluation stack when jumping lines.
This commit is contained in:
		
							parent
							
								
									9fa966136f
								
							
						
					
					
						commit
						02b30a8ef8
					
				
					 3 changed files with 98 additions and 17 deletions
				
			
		|  | @ -2264,25 +2264,25 @@ async def test_no_jump_backwards_into_async_for_block(output): | ||||||
|             output.append(2) |             output.append(2) | ||||||
|         output.append(3) |         output.append(3) | ||||||
| 
 | 
 | ||||||
|     @jump_test(1, 3, [], (ValueError, 'depth')) |     @jump_test(1, 3, [], (ValueError, 'stack')) | ||||||
|     def test_no_jump_forwards_into_with_block(output): |     def test_no_jump_forwards_into_with_block(output): | ||||||
|         output.append(1) |         output.append(1) | ||||||
|         with tracecontext(output, 2): |         with tracecontext(output, 2): | ||||||
|             output.append(3) |             output.append(3) | ||||||
| 
 | 
 | ||||||
|     @async_jump_test(1, 3, [], (ValueError, 'depth')) |     @async_jump_test(1, 3, [], (ValueError, 'stack')) | ||||||
|     async def test_no_jump_forwards_into_async_with_block(output): |     async def test_no_jump_forwards_into_async_with_block(output): | ||||||
|         output.append(1) |         output.append(1) | ||||||
|         async with asynctracecontext(output, 2): |         async with asynctracecontext(output, 2): | ||||||
|             output.append(3) |             output.append(3) | ||||||
| 
 | 
 | ||||||
|     @jump_test(3, 2, [1, 2, -1], (ValueError, 'depth')) |     @jump_test(3, 2, [1, 2, -1], (ValueError, 'stack')) | ||||||
|     def test_no_jump_backwards_into_with_block(output): |     def test_no_jump_backwards_into_with_block(output): | ||||||
|         with tracecontext(output, 1): |         with tracecontext(output, 1): | ||||||
|             output.append(2) |             output.append(2) | ||||||
|         output.append(3) |         output.append(3) | ||||||
| 
 | 
 | ||||||
|     @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'depth')) |     @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'stack')) | ||||||
|     async def test_no_jump_backwards_into_async_with_block(output): |     async def test_no_jump_backwards_into_async_with_block(output): | ||||||
|         async with asynctracecontext(output, 1): |         async with asynctracecontext(output, 1): | ||||||
|             output.append(2) |             output.append(2) | ||||||
|  | @ -2584,6 +2584,63 @@ async def test_jump_backward_over_async_listcomp_v2(output): | ||||||
|         output.append(7) |         output.append(7) | ||||||
|         output.append(8) |         output.append(8) | ||||||
| 
 | 
 | ||||||
|  |     # checking for segfaults. | ||||||
|  |     @jump_test(3, 7, [], error=(ValueError, "stack")) | ||||||
|  |     def test_jump_with_null_on_stack_load_global(output): | ||||||
|  |         a = 1 | ||||||
|  |         print( | ||||||
|  |             output.append(3) | ||||||
|  |         ) | ||||||
|  |         output.append(5) | ||||||
|  |         ( | ||||||
|  |             ( # 7 | ||||||
|  |                 a | ||||||
|  |                 + | ||||||
|  |                 10 | ||||||
|  |             ) | ||||||
|  |             + | ||||||
|  |             13 | ||||||
|  |         ) | ||||||
|  |         output.append(15) | ||||||
|  | 
 | ||||||
|  |     # checking for segfaults. | ||||||
|  |     @jump_test(4, 8, [], error=(ValueError, "stack")) | ||||||
|  |     def test_jump_with_null_on_stack_push_null(output): | ||||||
|  |         a = 1 | ||||||
|  |         f = print | ||||||
|  |         f( | ||||||
|  |             output.append(4) | ||||||
|  |         ) | ||||||
|  |         output.append(6) | ||||||
|  |         ( | ||||||
|  |             ( # 8 | ||||||
|  |                 a | ||||||
|  |                 + | ||||||
|  |                 11 | ||||||
|  |             ) | ||||||
|  |             + | ||||||
|  |             14 | ||||||
|  |         ) | ||||||
|  |         output.append(16) | ||||||
|  | 
 | ||||||
|  |     # checking for segfaults. | ||||||
|  |     @jump_test(3, 7, [], error=(ValueError, "stack")) | ||||||
|  |     def test_jump_with_null_on_stack_load_attr(output): | ||||||
|  |         a = 1 | ||||||
|  |         list.append( | ||||||
|  |             output, 3 | ||||||
|  |         ) | ||||||
|  |         output.append(5) | ||||||
|  |         ( | ||||||
|  |             ( # 7 | ||||||
|  |                 a | ||||||
|  |                 + | ||||||
|  |                 10 | ||||||
|  |             ) | ||||||
|  |             + | ||||||
|  |             13 | ||||||
|  |         ) | ||||||
|  |         output.append(15) | ||||||
| 
 | 
 | ||||||
| class TestExtendedArgs(unittest.TestCase): | class TestExtendedArgs(unittest.TestCase): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | Account for instructions that can push NULL to the stack when setting line | ||||||
|  | number in a frame. Prevents some (unlikely) crashes. | ||||||
|  | @ -137,9 +137,24 @@ typedef enum kind { | ||||||
|     Iterator = 1, |     Iterator = 1, | ||||||
|     Except = 2, |     Except = 2, | ||||||
|     Object = 3, |     Object = 3, | ||||||
|  |     Null = 4, | ||||||
| } Kind; | } Kind; | ||||||
| 
 | 
 | ||||||
| #define BITS_PER_BLOCK 2 | static int | ||||||
|  | compatible_kind(Kind from, Kind to) { | ||||||
|  |     if (to == 0) { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |     if (to == Object) { | ||||||
|  |         return from != Null; | ||||||
|  |     } | ||||||
|  |     if (to == Null) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     return from == to; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define BITS_PER_BLOCK 3 | ||||||
| 
 | 
 | ||||||
| #define UNINITIALIZED -2 | #define UNINITIALIZED -2 | ||||||
| #define OVERFLOWED -1 | #define OVERFLOWED -1 | ||||||
|  | @ -298,6 +313,23 @@ mark_stacks(PyCodeObject *code_obj, int len) | ||||||
|                 case RERAISE: |                 case RERAISE: | ||||||
|                     /* End of block */ |                     /* End of block */ | ||||||
|                     break; |                     break; | ||||||
|  |                 case PUSH_NULL: | ||||||
|  |                     next_stack = push_value(next_stack, Null); | ||||||
|  |                     stacks[i+1] = next_stack; | ||||||
|  |                     break; | ||||||
|  |                 case LOAD_GLOBAL: | ||||||
|  |                     if (_Py_OPARG(code[i]) & 1) { | ||||||
|  |                         next_stack = push_value(next_stack, Null); | ||||||
|  |                     } | ||||||
|  |                     next_stack = push_value(next_stack, Object); | ||||||
|  |                     stacks[i+1] = next_stack; | ||||||
|  |                     break; | ||||||
|  |                 case LOAD_METHOD: | ||||||
|  |                     next_stack = pop_value(next_stack); | ||||||
|  |                     next_stack = push_value(next_stack, Null); | ||||||
|  |                     next_stack = push_value(next_stack, Object); | ||||||
|  |                     stacks[i+1] = next_stack; | ||||||
|  |                     break; | ||||||
|                 default: |                 default: | ||||||
|                 { |                 { | ||||||
|                     int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i])); |                     int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i])); | ||||||
|  | @ -318,17 +350,6 @@ mark_stacks(PyCodeObject *code_obj, int len) | ||||||
|     return stacks; |     return stacks; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int |  | ||||||
| compatible_kind(Kind from, Kind to) { |  | ||||||
|     if (to == 0) { |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|     if (to == Object) { |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|     return from == to; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| compatible_stack(int64_t from_stack, int64_t to_stack) | compatible_stack(int64_t from_stack, int64_t to_stack) | ||||||
| { | { | ||||||
|  | @ -365,7 +386,8 @@ explain_incompatible_stack(int64_t to_stack) | ||||||
|         case Except: |         case Except: | ||||||
|             return "can't jump into an 'except' block as there's no exception"; |             return "can't jump into an 'except' block as there's no exception"; | ||||||
|         case Object: |         case Object: | ||||||
|             return "differing stack depth"; |         case Null: | ||||||
|  |             return "incompatible stacks"; | ||||||
|         case Iterator: |         case Iterator: | ||||||
|             return "can't jump into the body of a for loop"; |             return "can't jump into the body of a for loop"; | ||||||
|         default: |         default: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon