mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Fix disabled stream identity and annotation operand checks (#8960)
Return the context's canonical None singleton when standard streams are disabled. Check the exact set type before accessing user-rebindable conditional-annotation tracking objects. Both fixes apply to the unchanged Python 3.14 target. Include the no-stdio embedding regression and the unchanged canonical regression from CPython's 3.14 maintenance backport c21e7c45, after the vulnerable 3.14.7 tag. Extracted from the larger 3.15 migration; no marshal or version changes. Assisted-by: Codex:model-version-unavailable
This commit is contained in:
1 parent
7536730ed6
commit
6903fed201
3 files changed
+41
-7
No files matched your search
Vendored
+16
@@ -1,5 +1,6 @@
|
||||
import annotationlib
|
||||
import inspect
|
||||
import itertools
|
||||
import textwrap
|
||||
import types
|
||||
import unittest
|
||||
@@ -782,6 +783,21 @@ class ConditionalAnnotationTests(unittest.TestCase):
|
||||
|
||||
|
||||
class RegressionTests(unittest.TestCase):
|
||||
# gh-154902
|
||||
def test_conditional_annotations_rebound(self):
|
||||
# user code can rebind __conditional_annotations__ to any object
|
||||
lefts = ("__conditional_annotations__",
|
||||
'globals()["__conditional_annotations__"]')
|
||||
values = ("0", "{}", "[]", "''", "object()", "frozenset()")
|
||||
for left, value in itertools.product(lefts, values):
|
||||
with self.subTest(left=left, value=value):
|
||||
code = f"""
|
||||
{left} = {value}
|
||||
x: int
|
||||
"""
|
||||
with self.assertRaises(TypeError):
|
||||
run_code(code)
|
||||
|
||||
# gh-132479
|
||||
def test_complex_comprehension_inlining(self):
|
||||
# Test that the various repro cases from the issue don't crash
|
||||
|
||||
@@ -5587,10 +5587,10 @@ impl ExecutingFrame<'_> {
|
||||
Instruction::SetAdd { i } => {
|
||||
let item = self.pop_value();
|
||||
let obj = self.nth_value(i.get(arg) - 1);
|
||||
let set: &Py<PySet> = unsafe {
|
||||
// SAFETY: trust compiler
|
||||
obj.downcast_unchecked_ref()
|
||||
};
|
||||
// Annotation tracking can load a user-rebound global here.
|
||||
let set = obj.downcast_ref_if_exact::<PySet>(vm).ok_or_else(|| {
|
||||
vm.new_type_error(format!("'{}' object is not a set", obj.class().name()))
|
||||
})?;
|
||||
set.add(item, vm)?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
+21
-3
@@ -1514,9 +1514,7 @@ impl VirtualMachine {
|
||||
|
||||
// No stdio: set to None (embedding use case)
|
||||
#[cfg(not(feature = "stdio"))]
|
||||
let make_stdio = |_name: &str, _fd: i32, _write: bool| {
|
||||
Ok(crate::builtins::PyNone.into_pyobject(self))
|
||||
};
|
||||
let make_stdio = |_name: &str, _fd: i32, _write: bool| Ok(self.ctx.none());
|
||||
|
||||
let set_stdio = |name, fd, write| {
|
||||
let stdio: PyObjectRef = make_stdio(name, fd, write)?;
|
||||
@@ -3925,6 +3923,26 @@ pub fn resolve_frozen_alias(name: &str) -> &str {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[cfg(not(feature = "stdio"))]
|
||||
#[test]
|
||||
fn no_stdio_streams_are_none_singleton() {
|
||||
Interpreter::builder(Default::default())
|
||||
.build()
|
||||
.enter(|vm| {
|
||||
for name in [
|
||||
"stdin",
|
||||
"stdout",
|
||||
"stderr",
|
||||
"__stdin__",
|
||||
"__stdout__",
|
||||
"__stderr__",
|
||||
] {
|
||||
let stream = vm.sys_module.get_attr(name, vm).unwrap();
|
||||
assert!(vm.is_none(&stream), "sys.{name} must be the None singleton");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_frozen() {
|
||||
use rustpython_vm as vm;
|
||||
|
||||
Reference in new issue
Block a user