summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extmod/moductypes.c2
-rw-r--r--py/binary.c6
-rw-r--r--py/binary.h2
-rw-r--r--py/modstruct.c3
-rw-r--r--tests/basics/struct_endian.py7
5 files changed, 14 insertions, 6 deletions
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index d4c7611df..cf83f43e3 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -305,7 +305,7 @@ static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[16] = "BbHhIiQq------fd";
- mp_binary_set_val(struct_type, type2char[val_type], val, &p);
+ mp_binary_set_val(struct_type, type2char[val_type], val, p, &p);
}
static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {
diff --git a/py/binary.c b/py/binary.c
index 9810e4660..dfd25018c 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -250,14 +250,14 @@ void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t
}
}
-void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
+void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr) {
byte *p = *ptr;
mp_uint_t align;
size_t size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
- // Make pointer aligned
- p = (byte*)MP_ALIGN(p, (size_t)align);
+ // Align p relative to p_base
+ p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align);
if (MP_ENDIANNESS_LITTLE) {
struct_type = '<';
} else {
diff --git a/py/binary.h b/py/binary.h
index 092b72288..ac24378d2 100644
--- a/py/binary.h
+++ b/py/binary.h
@@ -39,7 +39,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index);
void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in);
void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val);
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr);
-void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
+void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr);
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src);
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val);
diff --git a/py/modstruct.c b/py/modstruct.c
index 957e4917b..3e7d90ec1 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -180,6 +180,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c
const char *fmt = mp_obj_str_get_str(fmt_in);
char fmt_type = get_fmt_type(&fmt);
+ byte *p_base = p;
size_t i;
for (i = 0; i < n_args;) {
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
} else {
// If we run out of args then we just finish; CPython would raise struct.error
while (cnt-- && i < n_args) {
- mp_binary_set_val(fmt_type, *fmt, args[i++], &p);
+ mp_binary_set_val(fmt_type, *fmt, args[i++], p_base, &p);
}
}
fmt++;
diff --git a/tests/basics/struct_endian.py b/tests/basics/struct_endian.py
index ae3243824..91f5539c1 100644
--- a/tests/basics/struct_endian.py
+++ b/tests/basics/struct_endian.py
@@ -15,3 +15,10 @@ print(struct.unpack('h', memoryview(buf)[1:3]))
print(struct.unpack_from('i', buf, 1))
print(struct.unpack_from('@i', buf, 1))
print(struct.unpack_from('@ii', buf, 1))
+
+# pack_into with unaligned native type
+buf = bytearray(b'>----<<<<<<<')
+struct.pack_into('i', buf, 1, 0x30313233)
+print(buf)
+struct.pack_into('@ii', buf, 3, 0x34353637, 0x41424344)
+print(buf)