Fix memoryview.cast over sliced memoryview

Fixes #4758
This commit is contained in:
Scott Shawcroft 2023-05-18 13:24:50 -07:00
parent f2bfced407
commit 9d11bda9e8
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA
3 changed files with 28 additions and 5 deletions

View File

@ -716,7 +716,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
} }
#if !MICROPY_VFS #if !MICROPY_VFS
uint mp_import_stat(const char *path) { mp_import_stat_t mp_import_stat(const char *path) {
struct stat st; struct stat st;
if (stat(path, &st) == 0) { if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {

View File

@ -254,12 +254,14 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args,
STATIC mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_in) { STATIC mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_in) {
mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
const char *typecode = mp_obj_str_get_str(typecode_in); const char *typecode = mp_obj_str_get_str(typecode_in);
size_t element_size = mp_binary_get_size('@', typecode[0], NULL); size_t new_element_size = mp_binary_get_size('@', typecode[0], NULL);
size_t bytelen = self->len * mp_binary_get_size('@', self->typecode & ~MP_OBJ_ARRAY_TYPECODE_FLAG_RW, NULL); size_t old_element_size = mp_binary_get_size('@', self->typecode & ~MP_OBJ_ARRAY_TYPECODE_FLAG_RW, NULL);
if (bytelen % element_size != 0) { size_t bytelen = self->len * old_element_size;
if (bytelen % new_element_size != 0) {
mp_raise_TypeError(MP_ERROR_TEXT("memoryview: length is not a multiple of itemsize")); mp_raise_TypeError(MP_ERROR_TEXT("memoryview: length is not a multiple of itemsize"));
} }
mp_obj_array_t *result = MP_OBJ_TO_PTR(mp_obj_new_memoryview(*typecode, bytelen / element_size, self->items)); mp_obj_array_t *result = MP_OBJ_TO_PTR(mp_obj_new_memoryview(*typecode, bytelen / new_element_size, self->items));
result->memview_offset = (self->memview_offset * old_element_size) / new_element_size;
// test if the object can be written to // test if the object can be written to
if (self->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW) { if (self->typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW) {

View File

@ -0,0 +1,21 @@
try:
memoryview(b'a').cast
except:
print("SKIP")
raise SystemExit
b = bytearray(range(16))
def print_memview(mv):
print(", ".join(hex(v) for v in mv))
mv = memoryview(b)
print_memview(mv)
print_memview(mv[4:])
words = mv.cast("I")
print_memview(words)
print_memview(mv[4:].cast("I"))
print_memview(words[1:])
print_memview(words.cast("B"))