vfs: Check that open() resulted in a file-like object.

That is, an object whose type defines the protocol slot.

Note that due to protocol confusion, a variant of the original
crasher that returned e.g., a machine.Pin instance could still
lead to a crash. (#17852)

Closes: #17841

Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
Jeff Epler 2025-08-08 08:53:14 -05:00
parent 593ae04eeb
commit 880dd0a1cd
3 changed files with 26 additions and 1 deletions

View file

@ -338,7 +338,12 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
#endif #endif
mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj); mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj);
return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t *)&args); mp_obj_t result = mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t *)&args);
const mp_obj_type_t *type = mp_obj_get_type(vfs->obj);
if (!MP_OBJ_TYPE_HAS_SLOT(type, protocol)) {
mp_raise_TypeError(NULL);
}
return result;
} }
MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open); MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open);

View file

@ -0,0 +1,19 @@
import os
import vfs
class Filesystem:
def mount(self, readonly, mkfs):
pass
def open(self, file, mode):
return None # violates vfs contract
fs = Filesystem()
vfs.mount(fs, "/test_mnt")
try:
execfile("/test_mnt/test.py")
print("ExecFile succeeded")
except TypeError:
print("TypeError")

View file

@ -0,0 +1 @@
TypeError