mirror of https://github.com/python/cpython.git
[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
|
@ -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…
Reference in New Issue