git: edee11f3ade7 - main - mail/bogofilter*: fix unaligned access on some databases

From: Gleb Popov <arrowd_at_FreeBSD.org>
Date: Fri, 24 Jul 2026 18:58:42 UTC
The branch main has been updated by arrowd:

URL: https://cgit.FreeBSD.org/ports/commit/?id=edee11f3ade730ece6643703213c3823d67b8138

commit edee11f3ade730ece6643703213c3823d67b8138
Author:     Matthias Andree <mandree@FreeBSD.org>
AuthorDate: 2026-07-24 09:49:48 +0000
Commit:     Gleb Popov <arrowd@FreeBSD.org>
CommitDate: 2026-07-24 18:57:45 +0000

    mail/bogofilter*: fix unaligned access on some databases
    
    This was found with the undefined behavior sanitizer,
    and affects the generic code (independent of the concrete database
    back-end in use) so we need to bump all PORTREVISIONS.
    
    The bug was that internal code was casting a void * to a uint32_t *
    without ensuring alignment of the source value.
    
    Let's use memcpy to a statically-sized array and let the optimizer
    handle it for us.  Adds files/patch-src_datastore.c.
    
    PR:             297024
    MFH:            2026Q3
---
 mail/bogofilter-kc/Makefile                 |  2 +-
 mail/bogofilter-lmdb1/Makefile              |  2 +-
 mail/bogofilter-sqlite/Makefile             |  2 +-
 mail/bogofilter/Makefile                    |  2 +-
 mail/bogofilter/files/patch-src_datastore.c | 52 +++++++++++++++++++++++++++++
 5 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/mail/bogofilter-kc/Makefile b/mail/bogofilter-kc/Makefile
index 9aa253204a77..615ad8325c13 100644
--- a/mail/bogofilter-kc/Makefile
+++ b/mail/bogofilter-kc/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	bogofilter
-PORTREVISION=	1
+PORTREVISION=	2
 PKGNAMESUFFIX=	-kc
 
 COMMENT=	Fast, teachable, learning spam detector (KyotoCabinet database)
diff --git a/mail/bogofilter-lmdb1/Makefile b/mail/bogofilter-lmdb1/Makefile
index 0379514f854a..5bfd7787213c 100644
--- a/mail/bogofilter-lmdb1/Makefile
+++ b/mail/bogofilter-lmdb1/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	bogofilter
-PORTREVISION=	0
+PORTREVISION=	1
 PKGNAMESUFFIX=	-lmdb1
 
 COMMENT=	Fast, teachable, learning spam detector (LMDB 1.0 database)
diff --git a/mail/bogofilter-sqlite/Makefile b/mail/bogofilter-sqlite/Makefile
index 8e95209c9b0b..0b660068a64d 100644
--- a/mail/bogofilter-sqlite/Makefile
+++ b/mail/bogofilter-sqlite/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	bogofilter
-PORTREVISION=	1
+PORTREVISION=	2
 PKGNAMESUFFIX=	-sqlite
 
 COMMENT?=	Fast, teachable, learning spam detector (SQLite3 database)
diff --git a/mail/bogofilter/Makefile b/mail/bogofilter/Makefile
index 12ba42744f5b..ccba0f443d8b 100644
--- a/mail/bogofilter/Makefile
+++ b/mail/bogofilter/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	bogofilter
 DISTVERSION=	1.3.0.rc1
-PORTREVISION?=	3
+PORTREVISION?=	4
 CATEGORIES?=	mail
 MASTER_SITES=	SF/bogofilter/bogofilter-current/bogofilter-1.3.0.beta/ \
 		https://gitlab.com/-/project/12408342/uploads/647db3bd2f28a1f91bdd3bb1945d91fe/
diff --git a/mail/bogofilter/files/patch-src_datastore.c b/mail/bogofilter/files/patch-src_datastore.c
new file mode 100644
index 000000000000..b958c332bef5
--- /dev/null
+++ b/mail/bogofilter/files/patch-src_datastore.c
@@ -0,0 +1,52 @@
+--- src/datastore.c.orig	2025-04-09 19:03:00 UTC
++++ src/datastore.c
+@@ -93,17 +93,24 @@ static void convert_external_to_internal(dsh_t *dsh, d
+ 
+ static void convert_external_to_internal(dsh_t *dsh, dbv_const_t *ex_data, dsv_t *in_data)
+ {
+-    size_t i = 0;
+-    const uint32_t *cv = (const uint32_t *)ex_data->data;
++    size_t i = 0u;
++    const uint32_t len = ex_data->leng;
++    uint32_t cv[3] = {0u, 0u, 0u};
++
++    // ensure we don't break on misaligned access
++    if (len < 4u) abort();
++    memcpy(&cv, ex_data->data, min(ex_data->leng, sizeof(cv)));
+ 
+-    in_data->spamcount = !dsh->is_swapped ? cv[i++] : swap_32bit(cv[i++]);
++    in_data->spamcount = !dsh->is_swapped ? cv[i] : swap_32bit(cv[i]);
++    ++i;
+ 
+-    if (ex_data->leng <= i * sizeof(uint32_t))
++    if (len < (i + 1) * sizeof(uint32_t))
+ 	in_data->goodcount = 0;
+     else
+-	in_data->goodcount = !dsh->is_swapped ? cv[i++] : swap_32bit(cv[i++]);
++	in_data->goodcount = !dsh->is_swapped ? cv[i] : swap_32bit(cv[i]);
++    ++i;
+ 
+-    if (ex_data->leng <= i * sizeof(uint32_t))
++    if (len < (i + 1) * sizeof(uint32_t))
+ 	in_data->date = 0;
+     else
+ 	in_data->date = !dsh->is_swapped ? cv[i] : swap_32bit(cv[i]);
+@@ -113,8 +120,8 @@ static void convert_internal_to_external(dsh_t *dsh, d
+ 
+ static void convert_internal_to_external(dsh_t *dsh, dsv_t *in_data, dbv_t *ex_data)
+ {
+-    size_t i = 0;
+-    uint32_t *cv = (uint32_t *)ex_data->data;
++    size_t i = 0u;
++    uint32_t cv[3] = {0u, 0u, 0u};
+ 
+     /* Writing requires extra magic since the counts may need to be
+     ** separated for output to different wordlists.
+@@ -127,6 +133,7 @@ static void convert_internal_to_external(dsh_t *dsh, d
+ 	cv[i++] = !dsh->is_swapped ? in_data->date : swap_32bit(in_data->date);
+ 
+     ex_data->leng = i * sizeof(cv[0]);
++    memcpy(ex_data->data, &cv, i * sizeof(cv[0]));
+ 
+     return;
+ }