Skip to content

Commit 24c3e9b

Browse files
committed
py/modstruct: Fix struct.pack_into with unaligned offset of native type.
Following the same fix for unpack.
1 parent 1022f9c commit 24c3e9b

File tree

5 files changed

+14
-6
lines changed

5 files changed

+14
-6
lines changed

extmod/moductypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
305305
static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) {
306306
char struct_type = big_endian ? '>' : '<';
307307
static const char type2char[16] = "BbHhIiQq------fd";
308-
mp_binary_set_val(struct_type, type2char[val_type], val, &p);
308+
mp_binary_set_val(struct_type, type2char[val_type], val, p, &p);
309309
}
310310

311311
static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {

py/binary.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,14 @@ void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t
250250
}
251251
}
252252

253-
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
253+
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr) {
254254
byte *p = *ptr;
255255
mp_uint_t align;
256256

257257
size_t size = mp_binary_get_size(struct_type, val_type, &align);
258258
if (struct_type == '@') {
259-
// Make pointer aligned
260-
p = (byte*)MP_ALIGN(p, (size_t)align);
259+
// Align p relative to p_base
260+
p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align);
261261
if (MP_ENDIANNESS_LITTLE) {
262262
struct_type = '<';
263263
} else {

py/binary.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index);
3939
void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in);
4040
void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val);
4141
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr);
42-
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
42+
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr);
4343
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src);
4444
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val);
4545

py/modstruct.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c
180180
const char *fmt = mp_obj_str_get_str(fmt_in);
181181
char fmt_type = get_fmt_type(&fmt);
182182

183+
byte *p_base = p;
183184
size_t i;
184185
for (i = 0; i < n_args;) {
185186
mp_uint_t cnt = 1;
@@ -204,7 +205,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c
204205
} else {
205206
// If we run out of args then we just finish; CPython would raise struct.error
206207
while (cnt-- && i < n_args) {
207-
mp_binary_set_val(fmt_type, *fmt, args[i++], &p);
208+
mp_binary_set_val(fmt_type, *fmt, args[i++], p_base, &p);
208209
}
209210
}
210211
fmt++;

tests/basics/struct_endian.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,10 @@
1515
print(struct.unpack_from('i', buf, 1))
1616
print(struct.unpack_from('@i', buf, 1))
1717
print(struct.unpack_from('@ii', buf, 1))
18+
19+
# pack_into with unaligned native type
20+
buf = bytearray(b'>----<<<<<<<')
21+
struct.pack_into('i', buf, 1, 0x30313233)
22+
print(buf)
23+
struct.pack_into('@ii', buf, 3, 0x34353637, 0x41424344)
24+
print(buf)

0 commit comments

Comments
 (0)