Angus Gratton 2024-04-25 22:52:05 +02:00 zatwierdzone przez GitHub
commit 096a381df2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
4 zmienionych plików z 232 dodań i 2 usunięć

Wyświetl plik

@ -32,6 +32,18 @@
#if MICROPY_VFS
// Block device functions are expected to return 0 on success
// and negative integer on errors. Check for positive integer
// results as some callers (i.e. littlefs) will produce corrupt
// results from these.
static int mp_vfs_check_result(mp_obj_t ret) {
int i = MP_OBJ_SMALL_INT_VALUE(ret);
if (i > 0) {
mp_raise_OSError(MP_EINVAL);
}
return i;
}
void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks);
mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks);
@ -69,7 +81,7 @@ int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t b
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
return mp_vfs_check_result(ret);
}
}
@ -106,7 +118,7 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
if (ret == mp_const_none) {
return 0;
} else {
return MP_OBJ_SMALL_INT_VALUE(ret);
return mp_vfs_check_result(ret);
}
}

Wyświetl plik

@ -64,6 +64,11 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode
if (out_sz == 0) {
return done;
}
if (out_sz != MP_STREAM_ERROR && out_sz > size) {
// This can only happen if the filesystem implementation returned invalid out_sz
*errcode = MP_EINVAL;
out_sz = MP_STREAM_ERROR;
}
if (out_sz == MP_STREAM_ERROR) {
// If we read something before getting EAGAIN, don't leak it
if (mp_is_nonblocking_error(*errcode) && done != 0) {

Wyświetl plik

@ -0,0 +1,87 @@
# Tests where the block device returns invalid values
try:
import vfs
vfs.VfsFat
vfs.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 512
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
self.read_res = 0
self.write_res = 0
def readblocks(self, block, buf, off=0):
print("readblocks")
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
return self.read_res
def writeblocks(self, block, buf, off=None):
if off is None:
# erase, then write
off = 0
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
return self.write_res
def ioctl(self, op, arg):
if op == 4: # block count
return len(self.data) // self.ERASE_BLOCK_SIZE
if op == 5: # block size
return self.ERASE_BLOCK_SIZE
if op == 6: # erase block
return 0
try:
bdev = RAMBlockDevice(50)
except MemoryError:
print("SKIP")
raise SystemExit
def test(vfs_class):
print(vfs_class)
vfs_class.mkfs(bdev)
fs = vfs_class(bdev)
with fs.open("test", "w") as f:
f.write("a" * 64)
for res in (0, -5, 5, 33, "invalid"):
# -5 is a legitimate negative failure (EIO), positive integer
# is not
# This variant will fail on open
bdev.read_res = res
try:
with fs.open("test", "r") as f:
print("opened")
except OSError as e:
print("OSError", e)
# This variant should succeed on open, may fail on read
# unless the filesystem cached the contents already
bdev.read_res = 0
try:
with fs.open("test", "r") as f:
bdev.read_res = res
print("read 1", f.read(1))
print("read rest", f.read())
except OSError as e:
print("OSError", e)
test(vfs.VfsLfs2)
test(vfs.VfsFat) # Looks like most failures of underlying device are ignored by VFAT currently

Wyświetl plik

@ -0,0 +1,126 @@
<class 'VfsLfs2'>
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
opened
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
OSError [Errno 5] EIO
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
OSError [Errno 22] EINVAL
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
OSError [Errno 22] EINVAL
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
OSError [Errno 22] EINVAL
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
<class 'VfsFat'>
readblocks
readblocks
readblocks
readblocks
readblocks
opened
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
opened
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
opened
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
opened
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
readblocks
opened
readblocks
read 1 a
read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa