@@ -285,8 +285,18 @@ INTERNAL_HIDDEN void *_page_fault_thread_handler(void *unused) {
285285
286286INTERNAL_HIDDEN INLINE void write_sanity_canary (void * p ) {
287287 const uint64_t canary = (_sanity_canary & SANITY_CANARY_VALIDATE_MASK );
288+ int32_t qwords = (int32_t ) (g_page_size / sizeof (uint64_t ));
288289
289- for (int32_t i = 0 ; i < (g_page_size / sizeof (uint64_t )); i ++ ) {
290+ #if USE_NEON
291+ const uint64x2_t cv = vdupq_n_u64 (canary );
292+ while (qwords >= 2 ) {
293+ vst1q_u64 ((uint64_t * ) p , cv );
294+ p += sizeof (uint64x2_t );
295+ qwords -= 2 ;
296+ }
297+ #endif
298+
299+ while (qwords -- ) {
290300 * (uint64_t * ) p = canary ;
291301 p += sizeof (uint64_t );
292302 }
@@ -305,16 +315,53 @@ INTERNAL_HIDDEN INLINE void check_sanity_canary(_sane_allocation_t *sane_alloc)
305315 start = sane_alloc -> address + sane_alloc -> orig_size ;
306316 }
307317
308- while (start < end ) {
318+ const uint64_t canary = (_sanity_canary & SANITY_CANARY_VALIDATE_MASK );
319+
320+ /* orig_size is unaligned in general, so [start, end) may begin or
321+ * end mid-qword. The expected byte at offset (p & 7) is that byte
322+ * within the canary qword, since write_sanity_canary stored qwords
323+ * starting at the page base. Walk the partial bytes at the head
324+ * until start is 8-aligned. */
325+ while (start < end && ((uintptr_t ) start & 7 )) {
326+ uint8_t expected = (uint8_t ) (canary >> (((uintptr_t ) start & 7 ) << 3 ));
327+ if (UNLIKELY (* (uint8_t * ) start != expected )) {
328+ LOG_AND_ABORT ("Sanity canary byte at 0x%p has been corrupted! Value: 0x%x Expected: 0x%x" , start , * (uint8_t * ) start , expected );
329+ }
330+ start ++ ;
331+ }
332+
333+ #if USE_NEON
334+ /* Compare two qwords at a time and reduce. On any mismatch, fall
335+ * through to the scalar loop which will pinpoint and abort. */
336+ const uint64x2_t cv = vdupq_n_u64 (canary );
337+ while ((start + sizeof (uint64x2_t )) <= end ) {
338+ uint64x2_t v = vld1q_u64 ((const uint64_t * ) start );
339+ if (UNLIKELY (vmaxvq_u32 (vreinterpretq_u32_u64 (veorq_u64 (v , cv ))) != 0 )) {
340+ break ;
341+ }
342+ start += sizeof (uint64x2_t );
343+ }
344+ #endif
345+
346+ while ((start + sizeof (uint64_t )) <= end ) {
309347 uint64_t v = * ((uint64_t * ) start );
310- uint64_t canary = (_sanity_canary & SANITY_CANARY_VALIDATE_MASK );
311348
312349 if (UNLIKELY (v != canary )) {
313350 LOG_AND_ABORT ("Sanity canary at 0x%p has been corrupted! Value: 0x%x Expected: 0x%x" , start , v , canary );
314351 }
315352
316353 start += sizeof (uint64_t );
317354 }
355+
356+ /* Tail: 0–7 partial bytes when end isn't 8-aligned (right-aligned
357+ * sample with unaligned orig_size). */
358+ while (start < end ) {
359+ uint8_t expected = (uint8_t ) (canary >> (((uintptr_t ) start & 7 ) << 3 ));
360+ if (UNLIKELY (* (uint8_t * ) start != expected )) {
361+ LOG_AND_ABORT ("Sanity canary byte at 0x%p has been corrupted! Value: 0x%x Expected: 0x%x" , start , * (uint8_t * ) start , expected );
362+ }
363+ start ++ ;
364+ }
318365}
319366
320367/* Callers of this function should hold the sanity cache lock */
0 commit comments