64-bit alignment problems.
Andy Fiddaman
cyrus at fiddaman.net
Sun Sep 16 14:43:40 EDT 2007
On Fri, 14 Sep 2007, Ken Murchison wrote:
; This patch tries to force the entire buffer to be aligned, rather than
; aligning each 64-bit field individually. Don't know if this will work or not.
The concept seems to work fine. There are some other places that
the same trick needs to be done - mailbox_expunge() and restore_expunged()
for example.
I adapted it slightly (see attachment) to use a union to conserve heap
space and a macro given the number of places it was proving necessary.
I also tried using the GNUC extension of specifying alignment but
it doesn't seem to work at all for me so I commented it out.
The following two bits aren't required - the pointer doesn't need to be
aligned, just the memory to which it points. That is already
done by malloc(). Also I don't think that anonymous unions are standard C.
- unsigned char *buf = NULL;
+ struct {
+#ifdef HAVE_LONG_LONG_INT
+ bit64 align8;
+#endif
+ unsigned char *buf;
+ } align8buf;
+ unsigned char *buf = align8buf.buf = NULL;
&
- const char *index_base;
+ union {
+#ifdef HAVE_LONG_LONG_INT
+ bit64 align8;
+#endif
+ const char *index_base;
+ };
I haven't had much time to look at split_attribs() properly so I just
left that the way my previous patch worked for now.
Andy
-------------- next part --------------
diff -ur cyrus-imapd-2.3.9.dist/imap/annotate.c cyrus-imapd-2.3.9/imap/annotate.c
--- cyrus-imapd-2.3.9.dist/imap/annotate.c 2007-08-15 17:20:55.000000000 +0000
+++ cyrus-imapd-2.3.9/imap/annotate.c 2007-09-15 19:20:10.749460641 +0000
@@ -310,7 +310,8 @@
/* xxx use datalen? */
/* xxx sanity check the data? */
- attrib->size = (size_t) ntohl(*(unsigned long *) data);
+ memcpy(&tmp, data, sizeof(unsigned long));
+ attrib->size = (size_t) ntohl(tmp);
data += sizeof(unsigned long); /* skip to value */
attrib->value = data;
diff -ur cyrus-imapd-2.3.9.dist/imap/mailbox.c cyrus-imapd-2.3.9/imap/mailbox.c
--- cyrus-imapd-2.3.9.dist/imap/mailbox.c 2007-07-20 14:21:57.000000000 +0000
+++ cyrus-imapd-2.3.9/imap/mailbox.c 2007-09-16 09:01:24.869639877 +0000
@@ -1283,7 +1283,7 @@
*/
int mailbox_write_index_header(struct mailbox *mailbox)
{
- char buf[INDEX_HEADER_SIZE];
+ ALIGNBUF(buf, INDEX_HEADER_SIZE);
unsigned long header_size = sizeof(buf);
int n;
@@ -1388,7 +1388,7 @@
int sync)
{
int n;
- char buf[INDEX_RECORD_SIZE];
+ ALIGNBUF(buf, INDEX_RECORD_SIZE);
mailbox_index_record_to_buf(record, buf);
@@ -1522,8 +1522,8 @@
unsigned long exists;
unsigned msgno;
bit32 oldstart_offset, oldrecord_size, recsize_diff;
- char buf[INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
- INDEX_HEADER_SIZE : INDEX_RECORD_SIZE];
+ ALIGNBUF(buf, INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
+ INDEX_HEADER_SIZE : INDEX_RECORD_SIZE);
char *bufp;
int quota_offset = 0;
int calculate_flagcounts = 0;
@@ -1851,8 +1851,8 @@
mailbox_decideproc_t *decideproc, void *deciderock,
int expunge_flags)
{
- char buf[INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
- INDEX_HEADER_SIZE : INDEX_RECORD_SIZE];
+ ALIGNBUF(buf, INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
+ INDEX_HEADER_SIZE : INDEX_RECORD_SIZE);
unsigned msgno;
unsigned newexpunged;
unsigned newexists;
@@ -2034,8 +2034,8 @@
unsigned newanswered;
unsigned newflagged;
- char buf[INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
- INDEX_HEADER_SIZE : INDEX_RECORD_SIZE];
+ ALIGNBUF(buf, INDEX_HEADER_SIZE > INDEX_RECORD_SIZE ?
+ INDEX_HEADER_SIZE : INDEX_RECORD_SIZE);
unsigned msgno;
struct stat sbuf;
struct txn *tid = NULL;
diff -ur cyrus-imapd-2.3.9.dist/imap/mailbox.h cyrus-imapd-2.3.9/imap/mailbox.h
--- cyrus-imapd-2.3.9.dist/imap/mailbox.h 2006-11-30 17:11:19.000000000 +0000
+++ cyrus-imapd-2.3.9/imap/mailbox.h 2007-09-16 18:00:00.082289457 +0000
@@ -74,6 +74,23 @@
#define MODSEQ_FMT "%lu"
#endif
+#ifdef HAVE_LONG_LONG_INT
+#if 0 /* __GNUC__ */
+#define ALIGNBUF(buf, size) char buf[(size)] __attribute__ ((aligned (8)))
+#else
+#define ALIGNBUF(buf, size) \
+ struct { \
+ union { \
+ bit64 align8; \
+ char buf[(size)]; \
+ } u; \
+ } align8buf; \
+ char *buf = align8buf.u.buf
+#endif
+#else
+#define ALIGNBUF(buf, size) char buf[(size)]
+#endif
+
#define MAX_MAILBOX_NAME 490
#define MAX_MAILBOX_PATH 4096
diff -ur cyrus-imapd-2.3.9.dist/imap/reconstruct.c cyrus-imapd-2.3.9/imap/reconstruct.c
--- cyrus-imapd-2.3.9.dist/imap/reconstruct.c 2007-04-03 13:01:12.000000000 +0000
+++ cyrus-imapd-2.3.9/imap/reconstruct.c 2007-09-16 09:01:51.717884602 +0000
@@ -439,8 +439,8 @@
char newfnamebuf[MAX_MAILBOX_PATH+1];
struct stat sbuf;
- char buf[((INDEX_HEADER_SIZE > INDEX_RECORD_SIZE) ?
- INDEX_HEADER_SIZE : INDEX_RECORD_SIZE)];
+ ALIGNBUF(buf, ((INDEX_HEADER_SIZE > INDEX_RECORD_SIZE) ?
+ INDEX_HEADER_SIZE : INDEX_RECORD_SIZE));
int expunge_fd;
FILE *fexpunge;
@@ -693,8 +693,8 @@
*/
int reconstruct(char *name, struct discovered *found)
{
- char buf[((INDEX_HEADER_SIZE > INDEX_RECORD_SIZE) ?
- INDEX_HEADER_SIZE : INDEX_RECORD_SIZE)];
+ ALIGNBUF(buf, ((INDEX_HEADER_SIZE > INDEX_RECORD_SIZE) ?
+ INDEX_HEADER_SIZE : INDEX_RECORD_SIZE));
char quota_root[MAX_MAILBOX_PATH+1];
bit32 valid_user_flags[MAX_USER_FLAGS/32];
diff -ur cyrus-imapd-2.3.9.dist/perl/imap/IMAP.xs cyrus-imapd-2.3.9/perl/imap/IMAP.xs
--- cyrus-imapd-2.3.9.dist/perl/imap/IMAP.xs 2006-11-30 17:11:23.000000000 +0000
+++ cyrus-imapd-2.3.9/perl/imap/IMAP.xs 2007-09-15 19:21:00.047555344 +0000
@@ -320,7 +320,7 @@
struct xscb *nx;
CODE:
/* fprintf(stderr, "!DESTROY %p %d\n", client, client->cnt); */
- if (!--client->cnt) {
+ if (!client->cnt--) {
/* printf("closing\n"); */
imclient_close(client->imclient);
while (client->cb) {
More information about the Info-cyrus
mailing list