Skip to content

Commit 4525714

Browse files
authored
Merge pull request adafruit#7772 from jepler/fix-struct-pack
struct: Check that argument counts match, similar to cpython3
2 parents e1f1647 + 98c546b commit 4525714

File tree

5 files changed

+67
-23
lines changed

5 files changed

+67
-23
lines changed

ports/unix/variants/coverage/mpconfigvariant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#define MICROPY_PY_FRAMEBUF (1)
6363
#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1)
6464
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
65+
#define MICROPY_PY_STRUCT (0) // uses shared-bindings struct
6566
#define MICROPY_PY_UCRYPTOLIB (1)
6667
#define MICROPY_PY_UCRYPTOLIB_CTR (1)
6768
#define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (1)

ports/unix/variants/coverage/mpconfigvariant.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SRC_BITMAP := \
3333
shared-bindings/bitmaptools/__init__.c \
3434
shared-bindings/displayio/Bitmap.c \
3535
shared-bindings/rainbowio/__init__.c \
36+
shared-bindings/struct/__init__.c \
3637
shared-bindings/traceback/__init__.c \
3738
shared-bindings/util.c \
3839
shared-bindings/zlib/__init__.c \
@@ -45,6 +46,7 @@ SRC_BITMAP := \
4546
shared-module/displayio/ColorConverter.c \
4647
shared-module/os/getenv.c \
4748
shared-module/rainbowio/__init__.c \
49+
shared-module/struct/__init__.c \
4850
shared-module/traceback/__init__.c \
4951
shared-module/zlib/__init__.c \
5052

@@ -57,6 +59,7 @@ CFLAGS += \
5759
-DCIRCUITPY_OS_GETENV=1 \
5860
-DCIRCUITPY_GIFIO=1 \
5961
-DCIRCUITPY_RAINBOWIO=1 \
62+
-DCIRCUITPY_STRUCT=1 \
6063
-DCIRCUITPY_TRACEBACK=1 \
6164
-DCIRCUITPY_ZLIB=1
6265

shared-module/struct/__init__.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -129,43 +129,45 @@ void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte *end_p, size
129129
mp_raise_RuntimeError(translate("buffer too small"));
130130
}
131131

132-
size_t i;
132+
size_t i = 0;
133133
byte *p_base = p;
134-
for (i = 0; i < n_args;) {
134+
while (*fmt) {
135135
mp_uint_t sz = 1;
136-
if (*fmt == '\0') {
137-
// more arguments given than used by format string; CPython raises struct.error here
138-
mp_raise_RuntimeError(translate("too many arguments provided with the given format"));
139-
}
140136
struct_validate_format(*fmt);
141137

142138
if (unichar_isdigit(*fmt)) {
143139
sz = get_fmt_num(&fmt);
144140
}
145141

146142
if (*fmt == 's') {
147-
mp_buffer_info_t bufinfo;
148-
mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);
149-
mp_uint_t to_copy = sz;
150-
if (bufinfo.len < to_copy) {
151-
to_copy = bufinfo.len;
143+
if (i < n_args) {
144+
mp_buffer_info_t bufinfo;
145+
mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
146+
mp_uint_t to_copy = sz;
147+
if (bufinfo.len < to_copy) {
148+
to_copy = bufinfo.len;
149+
}
150+
memcpy(p, bufinfo.buf, to_copy);
151+
memset(p + to_copy, 0, sz - to_copy);
152152
}
153-
memcpy(p, bufinfo.buf, to_copy);
154-
memset(p + to_copy, 0, sz - to_copy);
153+
i++;
155154
p += sz;
156155
} else {
157156
while (sz--) {
158157
// Pad bytes don't have a corresponding argument.
159158
if (*fmt == 'x') {
160159
mp_binary_set_val(fmt_type, *fmt, MP_OBJ_NEW_SMALL_INT(0), p_base, &p);
161160
} else {
162-
mp_binary_set_val(fmt_type, *fmt, args[i], p_base, &p);
161+
if (i < n_args) {
162+
mp_binary_set_val(fmt_type, *fmt, args[i], p_base, &p);
163+
}
163164
i++;
164165
}
165166
}
166167
}
167168
fmt++;
168169
}
170+
(void)mp_arg_validate_length(n_args, i, MP_QSTR_args);
169171
}
170172

171173
mp_obj_tuple_t *shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byte *end_p, bool exact_size) {

tests/circuitpython/struct_nargs.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import struct
2+
3+
4+
def do_pack(*args):
5+
try:
6+
print(struct.pack(*args))
7+
except Exception as e:
8+
print("ERROR")
9+
10+
11+
do_pack("H")
12+
do_pack("H", 1)
13+
do_pack("H", 1, 2)
14+
15+
do_pack("2H")
16+
do_pack("2H", 1)
17+
do_pack("2H", 1, 2)
18+
19+
do_pack("3H")
20+
do_pack("3H", 1)
21+
do_pack("3H", 1, 2)
22+
do_pack("3H", 1, 2, 3)
23+
do_pack("3H", 1, 2, 3, 4)
24+
25+
do_pack("4sH", b"x")
26+
do_pack("4sH", b"x", 1)
27+
do_pack("4sH", b"x", 1, 2)
28+
29+
do_pack("4s2H", b"x")
30+
do_pack("4s2H", b"x", 1)
31+
do_pack("4s2H", b"x", 1, 2)
32+
do_pack("4s2H", b"x", 1, 2, 3)
33+
34+
do_pack("4s3H", b"x")
35+
do_pack("4s3H", b"x", 1)
36+
do_pack("4s3H", b"x", 1, 2)
37+
do_pack("4s3H", b"x", 1, 2, 3)
38+
do_pack("4s3H", b"x", 1, 2, 3, 4)

tests/unix/extra_coverage.py.exp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ bitmaptools btree cexample cmath
3535
collections cppexample displayio errno
3636
ffi framebuf gc hashlib
3737
json math qrio rainbowio
38-
re sys termios traceback
39-
ubinascii uctypes uerrno uheapq
40-
uio ujson ulab ulab.numpy
41-
ulab.numpy.fft ulab.numpy.linalg ulab.scipy
42-
ulab.scipy.linalg ulab.scipy.optimize
43-
ulab.scipy.signal ulab.scipy.special
44-
ulab.utils uos urandom ure
45-
uselect ustruct utime utimeq
46-
uzlib zlib
38+
re struct sys termios
39+
traceback ubinascii uctypes uerrno
40+
uheapq uio ujson ulab
41+
ulab.numpy ulab.numpy.fft ulab.numpy.linalg
42+
ulab.scipy ulab.scipy.linalg
43+
ulab.scipy.optimize ulab.scipy.signal
44+
ulab.scipy.special ulab.utils uos
45+
urandom ure uselect utime
46+
utimeq uzlib zlib
4747
ime
4848

4949
utime utimeq

0 commit comments

Comments
 (0)