mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Reject oversized pickle lengths with OverflowError (#9040)
Preserve the wrapper-pickle regressions merged into main while refreshing the independent length checks. Assisted-by: OpenAI Codex:model identifier unavailable
This commit is contained in:
1 parent
9d6bf4d224
commit
be52c97463
2 files changed
+33
-6
No files matched your search
@@ -818,13 +818,18 @@ mod _pickle {
|
||||
.ok()
|
||||
.filter(|n| isize::try_from(*n).is_ok())
|
||||
.ok_or_else(|| {
|
||||
new_unpickling_error(
|
||||
vm,
|
||||
let message = if what == "FRAME" {
|
||||
format!(
|
||||
"FRAME length exceeds system's maximum of {} bytes",
|
||||
isize::MAX
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"{what} exceeds system's maximum size of {} bytes",
|
||||
isize::MAX
|
||||
),
|
||||
)
|
||||
)
|
||||
};
|
||||
vm.new_overflow_error(message)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1090,7 +1095,7 @@ mod _pickle {
|
||||
}
|
||||
Some(BINBYTES8) => {
|
||||
let arr: [u8; 8] = st.read_n(8, vm)?.try_into().unwrap();
|
||||
let n = read_size(&arr, vm, "BINBYTES8")?;
|
||||
let n = read_size(&arr, vm, "BINBYTES")?;
|
||||
let data = st.read_n(n, vm)?.to_vec();
|
||||
stack.push(vm.ctx.new_bytes(data).into());
|
||||
}
|
||||
@@ -1129,7 +1134,7 @@ mod _pickle {
|
||||
}
|
||||
Some(BINUNICODE8) => {
|
||||
let arr: [u8; 8] = st.read_n(8, vm)?.try_into().unwrap();
|
||||
let n = read_size(&arr, vm, "BINUNICODE8")?;
|
||||
let n = read_size(&arr, vm, "BINUNICODE")?;
|
||||
let data = st.read_n(n, vm)?.to_vec();
|
||||
stack.push(utf8_surrogatepass(&data, vm)?);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import _pickle
|
||||
import io
|
||||
import sys
|
||||
|
||||
from testutils import assert_raises
|
||||
|
||||
# BINPUT leaves holes; MEMOIZE uses the number of present entries.
|
||||
unpickler = _pickle.Unpickler(io.BytesIO(b"\x80\x04]q\x07\x94h\x01\x86."))
|
||||
@@ -13,3 +16,22 @@ assert memo[7] is left
|
||||
# Slot wrapper descriptors reduce to lookup on their defining class.
|
||||
assert object.__str__.__reduce__() == (getattr, (object, "__str__"))
|
||||
assert _pickle.loads(_pickle.dumps(object.__str__)) is object.__str__
|
||||
|
||||
# Oversized advertised lengths are rejected before trying to read or allocate.
|
||||
for opcode, name in (
|
||||
(b"\x8e", "BINBYTES"),
|
||||
(b"\x8d", "BINUNICODE"),
|
||||
(b"\x95", "FRAME"),
|
||||
):
|
||||
data = b"\x80\x04" + opcode + (sys.maxsize + 1).to_bytes(8, "little")
|
||||
for load in (
|
||||
_pickle.loads,
|
||||
lambda data: _pickle.Unpickler(io.BytesIO(data)).load(),
|
||||
):
|
||||
with assert_raises(OverflowError) as caught:
|
||||
load(data)
|
||||
if name == "FRAME":
|
||||
expected = f"FRAME length exceeds system's maximum of {sys.maxsize} bytes"
|
||||
else:
|
||||
expected = f"{name} exceeds system's maximum size of {sys.maxsize} bytes"
|
||||
assert str(caught.exception) == expected
|
||||
Reference in new issue
Block a user