struct: Check that argument counts match, similar to cpython3

.. and test our struct module during the build-time tests

Closes #7771
This commit is contained in:
Jeff Epler 2023-03-22 09:35:01 -05:00
parent c93560144b
commit 349dedca54
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 69 additions and 23 deletions

View File

@ -62,6 +62,7 @@
#define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_FRAMEBUF (1)
#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_STRUCT (0) // uses shared-bindings struct
#define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_UCRYPTOLIB (1)
#define MICROPY_PY_UCRYPTOLIB_CTR (1) #define MICROPY_PY_UCRYPTOLIB_CTR (1)
#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1) #define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1)

View File

@ -33,6 +33,7 @@ SRC_BITMAP := \
shared-bindings/bitmaptools/__init__.c \ shared-bindings/bitmaptools/__init__.c \
shared-bindings/displayio/Bitmap.c \ shared-bindings/displayio/Bitmap.c \
shared-bindings/rainbowio/__init__.c \ shared-bindings/rainbowio/__init__.c \
shared-bindings/struct/__init__.c \
shared-bindings/traceback/__init__.c \ shared-bindings/traceback/__init__.c \
shared-bindings/util.c \ shared-bindings/util.c \
shared-bindings/zlib/__init__.c \ shared-bindings/zlib/__init__.c \
@ -45,6 +46,7 @@ SRC_BITMAP := \
shared-module/displayio/ColorConverter.c \ shared-module/displayio/ColorConverter.c \
shared-module/os/getenv.c \ shared-module/os/getenv.c \
shared-module/rainbowio/__init__.c \ shared-module/rainbowio/__init__.c \
shared-module/struct/__init__.c \
shared-module/traceback/__init__.c \ shared-module/traceback/__init__.c \
shared-module/zlib/__init__.c \ shared-module/zlib/__init__.c \
@ -57,6 +59,7 @@ CFLAGS += \
-DCIRCUITPY_OS_GETENV=1 \ -DCIRCUITPY_OS_GETENV=1 \
-DCIRCUITPY_GIFIO=1 \ -DCIRCUITPY_GIFIO=1 \
-DCIRCUITPY_RAINBOWIO=1 \ -DCIRCUITPY_RAINBOWIO=1 \
-DCIRCUITPY_STRUCT=1 \
-DCIRCUITPY_TRACEBACK=1 \ -DCIRCUITPY_TRACEBACK=1 \
-DCIRCUITPY_ZLIB=1 -DCIRCUITPY_ZLIB=1

View File

@ -129,14 +129,10 @@ void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte *end_p, size
mp_raise_RuntimeError(translate("buffer too small")); mp_raise_RuntimeError(translate("buffer too small"));
} }
size_t i; size_t i = 0;
byte *p_base = p; byte *p_base = p;
for (i = 0; i < n_args;) { while (*fmt) {
mp_uint_t sz = 1; mp_uint_t sz = 1;
if (*fmt == '\0') {
// more arguments given than used by format string; CPython raises struct.error here
mp_raise_RuntimeError(translate("too many arguments provided with the given format"));
}
struct_validate_format(*fmt); struct_validate_format(*fmt);
if (unichar_isdigit(*fmt)) { if (unichar_isdigit(*fmt)) {
@ -144,14 +140,17 @@ void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte *end_p, size
} }
if (*fmt == 's') { if (*fmt == 's') {
mp_buffer_info_t bufinfo; if (i < n_args) {
mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ); mp_buffer_info_t bufinfo;
mp_uint_t to_copy = sz; mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len < to_copy) { mp_uint_t to_copy = sz;
to_copy = bufinfo.len; if (bufinfo.len < to_copy) {
to_copy = bufinfo.len;
}
memcpy(p, bufinfo.buf, to_copy);
memset(p + to_copy, 0, sz - to_copy);
} }
memcpy(p, bufinfo.buf, to_copy); i++;
memset(p + to_copy, 0, sz - to_copy);
p += sz; p += sz;
} else { } else {
while (sz--) { while (sz--) {
@ -159,13 +158,18 @@ void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte *end_p, size
if (*fmt == 'x') { if (*fmt == 'x') {
mp_binary_set_val(fmt_type, *fmt, MP_OBJ_NEW_SMALL_INT(0), p_base, &p); mp_binary_set_val(fmt_type, *fmt, MP_OBJ_NEW_SMALL_INT(0), p_base, &p);
} else { } else {
mp_binary_set_val(fmt_type, *fmt, args[i], p_base, &p); if (i < n_args) {
mp_binary_set_val(fmt_type, *fmt, args[i], p_base, &p);
}
i++; i++;
} }
} }
} }
fmt++; fmt++;
} }
if (i != n_args) {
mp_raise_ValueError_varg(translate("%q length must be %d"), MP_QSTR_args, i);
}
} }
mp_obj_tuple_t *shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byte *end_p, bool exact_size) { mp_obj_tuple_t *shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byte *end_p, bool exact_size) {

View File

@ -0,0 +1,38 @@
import struct
def do_pack(*args):
try:
print(struct.pack(*args))
except Exception as e:
print("ERROR")
do_pack("H")
do_pack("H", 1)
do_pack("H", 1, 2)
do_pack("2H")
do_pack("2H", 1)
do_pack("2H", 1, 2)
do_pack("3H")
do_pack("3H", 1)
do_pack("3H", 1, 2)
do_pack("3H", 1, 2, 3)
do_pack("3H", 1, 2, 3, 4)
do_pack("4sH", b"x")
do_pack("4sH", b"x", 1)
do_pack("4sH", b"x", 1, 2)
do_pack("4s2H", b"x")
do_pack("4s2H", b"x", 1)
do_pack("4s2H", b"x", 1, 2)
do_pack("4s2H", b"x", 1, 2, 3)
do_pack("4s3H", b"x")
do_pack("4s3H", b"x", 1)
do_pack("4s3H", b"x", 1, 2)
do_pack("4s3H", b"x", 1, 2, 3)
do_pack("4s3H", b"x", 1, 2, 3, 4)

View File

@ -35,15 +35,15 @@ bitmaptools btree cexample cmath
collections cppexample displayio errno collections cppexample displayio errno
ffi framebuf gc hashlib ffi framebuf gc hashlib
json math qrio rainbowio json math qrio rainbowio
re sys termios traceback re struct sys termios
ubinascii uctypes uerrno uheapq traceback ubinascii uctypes uerrno
uio ujson ulab ulab.numpy uheapq uio ujson ulab
ulab.numpy.fft ulab.numpy.linalg ulab.scipy ulab.numpy ulab.numpy.fft ulab.numpy.linalg
ulab.scipy.linalg ulab.scipy.optimize ulab.scipy ulab.scipy.linalg
ulab.scipy.signal ulab.scipy.special ulab.scipy.optimize ulab.scipy.signal
ulab.utils uos urandom ure ulab.scipy.special ulab.utils uos
uselect ustruct utime utimeq urandom ure uselect utime
uzlib zlib utimeq uzlib zlib
ime ime
utime utimeq utime utimeq