Browse code

fix SIGBUS on Sparc.

Need to use the alignment of the largest possible type that we access, which is
uint64_t in this case.
void* can be 32-bits, and uint64_t still requires 64-bit alignment on Sparc,
when compiling for 32-bits (default).

Török Edvin authored on 2009/08/02 20:47:11
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Sun Aug  2 14:46:40 EEST 2009 (edwin)
2
+-------------------------------------
3
+ * libclamav/bytecode_vm.c: fix SIGBUS on sparc.
4
+
1 5
 Fri Jul 31 21:28:18 CEST 2009 (tk)
2 6
 ----------------------------------
3 7
  * libclamav, clamd: handle file exclusion in cli_ftw() (bb#1656)
... ...
@@ -103,6 +103,10 @@ struct stack {
103 103
     uint16_t last_size;
104 104
 };
105 105
 
106
+/* type with largest alignment that we use (in general it is a long double, but
107
+ * thats too big alignment for us) */
108
+typedef uint64_t align_t;
109
+
106 110
 static always_inline void* cli_stack_alloc(struct stack *stack, unsigned bytes)
107 111
 {
108 112
     struct stack_chunk *chunk = stack->chunk;
... ...
@@ -110,7 +114,7 @@ static always_inline void* cli_stack_alloc(struct stack *stack, unsigned bytes)
110 110
 
111 111
     /* last_size is stored after data */
112 112
     /* align bytes to pointer size */
113
-    bytes = (bytes + sizeof(uint16_t) + sizeof(void*)) & ~(sizeof(void*)-1);
113
+    bytes = (bytes + sizeof(uint16_t) + sizeof(align_t)) & ~(sizeof(align_t)-1);
114 114
     last_size_off = bytes - 2;
115 115
 
116 116
     if (chunk && (chunk->used + bytes <= STACK_CHUNKSIZE)) {
... ...
@@ -118,7 +122,7 @@ static always_inline void* cli_stack_alloc(struct stack *stack, unsigned bytes)
118 118
 	void *ret;
119 119
 
120 120
 	*(uint16_t*)&chunk->u.data[chunk->used + last_size_off] = stack->last_size;
121
-	stack->last_size = bytes/sizeof(void*);
121
+	stack->last_size = bytes/sizeof(align_t);
122 122
 
123 123
 	ret = chunk->u.data + chunk->used;
124 124
 	chunk->used += bytes;
... ...
@@ -135,7 +139,7 @@ static always_inline void* cli_stack_alloc(struct stack *stack, unsigned bytes)
135 135
 	return NULL;
136 136
 
137 137
     *(uint16_t*)&chunk->u.data[last_size_off] = stack->last_size;
138
-    stack->last_size = bytes/sizeof(void*);
138
+    stack->last_size = bytes/sizeof(align_t);
139 139
 
140 140
     chunk->used = bytes;
141 141
     chunk->prev = stack->chunk;
... ...
@@ -151,17 +155,17 @@ static always_inline void cli_stack_free(struct stack *stack, void *data)
151 151
 	cli_errmsg("cli_stack_free: stack empty!\n");
152 152
 	return;
153 153
     }
154
-    if ((chunk->u.data + chunk->used) != ((char*)data + stack->last_size*sizeof(void*))) {
154
+    if ((chunk->u.data + chunk->used) != ((char*)data + stack->last_size*sizeof(align_t))) {
155 155
 	cli_errmsg("cli_stack_free: wrong free order: %p, expected %p\n",
156
-		   data, chunk->u.data + chunk->used - stack->last_size*sizeof(void*));
156
+		   data, chunk->u.data + chunk->used - stack->last_size*sizeof(align_t));
157 157
 	return;
158 158
     }
159 159
     last_size = *(uint16_t*)&chunk->u.data[chunk->used-2];
160
-    if (chunk->used < stack->last_size*sizeof(void*)) {
160
+    if (chunk->used < stack->last_size*sizeof(align_t)) {
161 161
 	cli_errmsg("cli_stack_free: last_size is corrupt!\n");
162 162
 	return;
163 163
     }
164
-    chunk->used -= stack->last_size*sizeof(void*);
164
+    chunk->used -= stack->last_size*sizeof(align_t);
165 165
     stack->last_size = last_size;
166 166
     if (!chunk->used) {
167 167
 	stack->chunk = chunk->prev;