+++ /dev/null
-From 783fbbd591982749714fba784318bf0fac3c9d41 Mon Sep 17 00:00:00 2001
-From: Matt Merhar <mattmerhar@protonmail.com>
-Date: Tue, 3 Feb 2026 23:01:41 -0500
-Subject: [PATCH 2/4] defines: rework apk_unaligned_* helpers
-
-These only work properly on little endian input words, and
-apk_unaligned_u64a32 won't work correctly as-is on big endian systems.
-
-Change the suffixes to explicitly call out this "limitation" and switch
-the uint64_t variant to operate on single bytes as the others already do
-so it works as expected on big endian hosts.
-
-And, add a uint16_t variant.
----
- src/adb.c | 2 +-
- src/apk_defines.h | 22 ++++++++++++++++------
- src/blob.c | 2 +-
- src/database.c | 2 +-
- 4 files changed, 19 insertions(+), 9 deletions(-)
-
---- a/src/adb.c
-+++ b/src/adb.c
-@@ -434,7 +434,7 @@ uint64_t adb_r_int(const struct adb *db,
- case ADB_TYPE_INT_64:
- ptr = adb_r_deref(db, v, 0, sizeof(uint64_t));
- if (!ptr) return 0;
-- return le64toh(apk_unaligned_u64a32(ptr));
-+ return apk_unaligned_le64(ptr);
- default:
- return 0;
- }
---- a/src/apk_defines.h
-+++ b/src/apk_defines.h
-@@ -151,24 +151,34 @@ static inline uint64_t apk_calc_installe
- }
-
- #if defined(__x86_64__) || defined(__i386__)
--static inline uint32_t apk_unaligned_u32(const void *ptr)
-+static inline uint16_t apk_unaligned_le16(const void *ptr)
-+{
-+ return *(const uint16_t *)ptr;
-+}
-+static inline uint32_t apk_unaligned_le32(const void *ptr)
- {
- return *(const uint32_t *)ptr;
- }
--static inline uint64_t apk_unaligned_u64a32(const void *ptr)
-+static inline uint64_t apk_unaligned_le64(const void *ptr)
- {
- return *(const uint64_t *)ptr;
- }
- #else
--static inline uint32_t apk_unaligned_u32(const void *ptr)
-+static inline uint16_t apk_unaligned_le16(const void *ptr)
-+{
-+ const uint8_t *p = ptr;
-+ return p[0] | (uint16_t)p[1] << 8;
-+}
-+static inline uint32_t apk_unaligned_le32(const void *ptr)
- {
- const uint8_t *p = ptr;
- return p[0] | (uint32_t)p[1] << 8 | (uint32_t)p[2] << 16 | (uint32_t)p[3] << 24;
- }
--static inline uint64_t apk_unaligned_u64a32(const void *ptr)
-+static inline uint64_t apk_unaligned_le64(const void *ptr)
- {
-- const uint32_t *p = ptr;
-- return p[0] | (uint64_t)p[1] << 32;
-+ const uint8_t *p = ptr;
-+ return p[0] | (uint64_t)p[1] << 8 | (uint64_t)p[2] << 16 | (uint64_t)p[3] << 24 |
-+ (uint64_t)p[4] << 32 | (uint64_t)p[5] << 40 | (uint64_t)p[6] << 48 | (uint64_t)p[7] << 56;
- }
- #endif
-
---- a/src/blob.c
-+++ b/src/blob.c
-@@ -98,7 +98,7 @@ static uint32_t murmur3_32(const void *p
- int i;
-
- for (i = 0; i < nblocks; i++, key += 4) {
-- k = apk_unaligned_u32(key);
-+ k = apk_unaligned_le32(key);
- k *= c1;
- k = rotl32(k, 15);
- k *= c2;
---- a/src/database.c
-+++ b/src/database.c
-@@ -90,7 +90,7 @@ static unsigned long csum_hash(apk_blob_
- /* Checksum's highest bits have the most "randomness", use that
- * directly as hash */
- if (csum.len >= sizeof(uint32_t))
-- return apk_unaligned_u32(csum.ptr);
-+ return apk_unaligned_le32(csum.ptr);
- return 0;
- }
-
+++ /dev/null
-From 2cb386c75518ca4df5348d1f29c75ac923fc847c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
-Date: Thu, 5 Feb 2026 13:07:04 +0200
-Subject: [PATCH 4/4] io: synchronize istream buffer alignment with file
- offset
-
-To correctly guarantee buffer alignment for apk_istream_get() reads
-the buffer needs to be aligned with the file offset. Fixup the
-io code to properly synchronize the alignment.
-
-This removes unaligned memory reads in various places. In practice
-this speeds up things and fixes the faults/read errors on platforms
-where unaligned access is an error.
----
- src/apk_io.h | 3 ++-
- src/io.c | 37 +++++++++++++++++---------
- src/io_gunzip.c | 2 ++
- src/io_url_libfetch.c | 2 ++
- src/process.c | 2 ++
- test/unit/io_test.c | 62 +++++++++++++++++++++++++++++++++++++++++++
- 6 files changed, 94 insertions(+), 14 deletions(-)
-
---- a/src/apk_io.h
-+++ b/src/apk_io.h
-@@ -82,7 +82,7 @@ struct apk_istream {
- unsigned int flags;
- struct apk_progress *prog;
- const struct apk_istream_ops *ops;
--};
-+} __attribute__((aligned(8)));
-
- typedef int (*apk_archive_entry_parser)(void *ctx,
- const struct apk_file_info *ae,
-@@ -144,6 +144,7 @@ struct apk_segment_istream {
- struct apk_istream *pis;
- uint64_t bytes_left;
- time_t mtime;
-+ uint8_t align;
- };
- struct apk_istream *apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is, uint64_t len, time_t mtime);
-
---- a/src/io.c
-+++ b/src/io.c
-@@ -33,6 +33,9 @@
- #define HAVE_O_TMPFILE
- #endif
-
-+// The granularity for the file offset and istream buffer alignment synchronization.
-+#define APK_ISTREAM_ALIGN_SYNC 8
-+
- size_t apk_io_bufsize = 128*1024;
-
-
-@@ -111,16 +114,16 @@ ssize_t apk_istream_read_max(struct apk_
- if (left > is->buf_size/4) {
- r = is->ops->read(is, ptr, left);
- if (r <= 0) break;
-+ is->ptr = is->end = &is->buf[(is->ptr - is->buf + r) % APK_ISTREAM_ALIGN_SYNC];
- left -= r;
- ptr += r;
- continue;
- }
-
-- r = is->ops->read(is, is->buf, is->buf_size);
-+ r = is->ops->read(is, is->ptr, is->buf + is->buf_size - is->ptr);
- if (r <= 0) break;
-
-- is->ptr = is->buf;
-- is->end = is->buf + r;
-+ is->end = is->ptr + r;
- }
-
- if (r < 0) return apk_istream_error(is, r);
-@@ -136,19 +139,20 @@ int apk_istream_read(struct apk_istream
-
- static int __apk_istream_fill(struct apk_istream *is)
- {
-- ssize_t sz;
--
- if (is->err) return is->err;
-
-- if (is->ptr != is->buf) {
-- sz = is->end - is->ptr;
-- memmove(is->buf, is->ptr, sz);
-- is->ptr = is->buf;
-- is->end = is->buf + sz;
-- } else if (is->end-is->ptr == is->buf_size)
-- return -ENOBUFS;
-+ size_t offs = is->ptr - is->buf;
-+ if (offs >= APK_ISTREAM_ALIGN_SYNC) {
-+ size_t buf_used = is->end - is->ptr;
-+ uint8_t *ptr = &is->buf[offs % APK_ISTREAM_ALIGN_SYNC];
-+ memmove(ptr, is->ptr, buf_used);
-+ is->ptr = ptr;
-+ is->end = ptr + buf_used;
-+ } else {
-+ if (is->end == is->buf+is->buf_size) return -ENOBUFS;
-+ }
-
-- sz = is->ops->read(is, is->end, is->buf + is->buf_size - is->end);
-+ ssize_t sz = is->ops->read(is, is->end, is->buf + is->buf_size - is->end);
- if (sz <= 0) return apk_istream_error(is, sz ?: 1);
- is->end += sz;
- return 0;
-@@ -282,6 +286,7 @@ static ssize_t segment_read(struct apk_i
- if (r == 0) r = -ECONNABORTED;
- } else {
- sis->bytes_left -= r;
-+ sis->align += r;
- }
- return r;
- }
-@@ -290,6 +295,7 @@ static int segment_close(struct apk_istr
- {
- struct apk_segment_istream *sis = container_of(is, struct apk_segment_istream, is);
-
-+ if (!sis->pis->ptr) sis->pis->ptr = sis->pis->end = &is->buf[sis->align % APK_ISTREAM_ALIGN_SYNC];
- if (sis->bytes_left) apk_istream_skip(sis->pis, sis->bytes_left);
- return is->err < 0 ? is->err : 0;
- }
-@@ -316,6 +322,9 @@ struct apk_istream *apk_istream_segment(
- sis->is.end = sis->is.ptr + len;
- is->ptr += len;
- } else {
-+ // Calculated at segment_closet again, set to null to catch if
-+ // the inner istream is used before segment close.
-+ sis->align = is->end - is->buf;
- is->ptr = is->end = 0;
- }
- sis->bytes_left -= sis->is.end - sis->is.ptr;
-@@ -600,6 +609,8 @@ struct apk_istream *apk_istream_from_fd(
- .is.ops = &fd_istream_ops,
- .is.buf = (uint8_t *)(fis + 1),
- .is.buf_size = apk_io_bufsize,
-+ .is.ptr = (uint8_t *)(fis + 1),
-+ .is.end = (uint8_t *)(fis + 1),
- .fd = fd,
- };
-
---- a/src/io_gunzip.c
-+++ b/src/io_gunzip.c
-@@ -165,6 +165,8 @@ struct apk_istream *apk_istream_zlib(str
- .is.ops = &gunzip_istream_ops,
- .is.buf = (uint8_t*)(gis + 1),
- .is.buf_size = apk_io_bufsize,
-+ .is.ptr = (uint8_t*)(gis + 1),
-+ .is.end = (uint8_t*)(gis + 1),
- .zis = is,
- .cb = cb,
- .cbctx = ctx,
---- a/src/io_url_libfetch.c
-+++ b/src/io_url_libfetch.c
-@@ -161,6 +161,8 @@ struct apk_istream *apk_io_url_istream(c
- .is.ops = &fetch_istream_ops,
- .is.buf = (uint8_t*)(fis+1),
- .is.buf_size = apk_io_bufsize,
-+ .is.ptr = (uint8_t*)(fis+1),
-+ .is.end = (uint8_t*)(fis+1),
- .fetchIO = io,
- .urlstat = fis->urlstat,
- };
---- a/src/process.c
-+++ b/src/process.c
-@@ -317,6 +317,8 @@ struct apk_istream *apk_process_istream(
- .is.ops = &process_istream_ops,
- .is.buf = (uint8_t *)(pis + 1),
- .is.buf_size = apk_io_bufsize,
-+ .is.ptr = (uint8_t *)(pis + 1),
-+ .is.end = (uint8_t *)(pis + 1),
- };
- r = apk_process_init(&pis->proc, apk_last_path_segment(argv[0]), logpfx, out, NULL);
- if (r != 0) goto err;
---- a/test/unit/io_test.c
-+++ b/test/unit/io_test.c
-@@ -119,3 +119,65 @@ APK_TEST(io_foreach_config_file) {
-
- assert_int_equal(0, apk_dir_foreach_config_file(MOCKFD, assert_path_entry, NULL, apk_filename_is_hidden, "a", "b", NULL));
- }
-+
-+APK_TEST(io_istream_align) {
-+ struct apk_istream *is = apk_istream_from_file(AT_FDCWD, "/dev/zero");
-+ struct apk_segment_istream seg;
-+ size_t bufsz = 1024*1024;
-+ uint8_t *buf = malloc(bufsz), *ptr;
-+
-+ assert_int_equal(0, apk_istream_read(is, buf, 1024));
-+
-+ ptr = apk_istream_get(is, 1024);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ assert_ptr_ok(apk_istream_get(is, 7));
-+ assert_ptr_ok(apk_istream_get(is, apk_io_bufsize - 1024));
-+ assert_ptr_ok(apk_istream_get(is, 1));
-+
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ assert_int_equal(0, apk_istream_read(is, buf, bufsz - 1));
-+ assert_int_equal(0, apk_istream_read(is, buf, 1));
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ apk_istream_segment(&seg, is, 1024-1, 0);
-+ apk_istream_close(&seg.is);
-+ assert_ptr_ok(apk_istream_get(is, 1));
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ apk_istream_segment(&seg, is, bufsz-1, 0);
-+ apk_istream_close(&seg.is);
-+ assert_ptr_ok(apk_istream_get(is, 1));
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ assert_ptr_ok(apk_istream_get(is, 7));
-+ apk_istream_segment(&seg, is, bufsz-7, 0);
-+ assert_int_equal(0, apk_istream_read(&seg.is, buf, bufsz-10));
-+ assert_int_equal(0, apk_istream_read(&seg.is, buf, 1));
-+ apk_istream_close(&seg.is);
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ apk_istream_segment(&seg, is, bufsz*2+1, 0);
-+ assert_int_equal(0, apk_istream_read(&seg.is, buf, bufsz));
-+ assert_int_equal(0, apk_istream_read(&seg.is, buf, bufsz));
-+ apk_istream_close(&seg.is);
-+ assert_int_equal(0, apk_istream_read(is, buf, 7));
-+ ptr = apk_istream_get(is, 64);
-+ assert_ptr_ok(ptr);
-+ assert_int_equal(0, (uintptr_t)ptr & 7);
-+
-+ apk_istream_close(is);
-+ free(buf);
-+}