aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-03-31 20:13:18 +0200
committerMattias EngdegÄrd2023-03-31 21:37:53 +0200
commit6523359dfe212633f5bd274b29a1f5e613384c79 (patch)
treea8ad810602390d85bbd19297b8e09d647ed53968 /src
parent6f496105e392af45c2248b4523ef19804837a8a6 (diff)
downloademacs-6523359dfe212633f5bd274b29a1f5e613384c79.tar.gz
emacs-6523359dfe212633f5bd274b29a1f5e613384c79.zip
Make string-lessp vectorisation safer
Use memcpy for loading unaligned words on platforms where this can be done efficiently. This guards against problems arising from future compiler autovectorisation improvements that might cause instructions that require aligned addresses to be emitted, and should also work with an address sanitiser enabled. * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): Only define when optimising. (load_unaligned_size_t): New. (Fstring_lessp): Use load_unaligned_size_t. * src/lisp.h (UNALIGNED_LOAD_SIZE): Remove now unused macro.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c43
-rw-r--r--src/lisp.h20
2 files changed, 25 insertions, 38 deletions
diff --git a/src/fns.c b/src/fns.c
index 0af9b725c7a..94505eda444 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -439,17 +439,29 @@ If string STR1 is greater, the value is a positive number N;
439} 439}
440 440
441/* Check whether the platform allows access to unaligned addresses for 441/* Check whether the platform allows access to unaligned addresses for
442 size_t integers without trapping or undue penalty (a few cycles is OK). 442 size_t integers without trapping or undue penalty (a few cycles is OK),
443 and that a word-sized memcpy can be used to generate such an access.
443 444
444 This whitelist is incomplete but since it is only used to improve 445 This whitelist is incomplete but since it is only used to improve
445 performance, omitting cases is safe. */ 446 performance, omitting cases is safe. */
446#if defined __x86_64__|| defined __amd64__ \ 447#if (defined __x86_64__|| defined __amd64__ \
447 || defined __i386__ || defined __i386 \ 448 || defined __i386__ || defined __i386 \
448 || defined __arm64__ || defined __aarch64__ \ 449 || defined __arm64__ || defined __aarch64__ \
449 || defined __powerpc__ || defined __powerpc \ 450 || defined __powerpc__ || defined __powerpc \
450 || defined __ppc__ || defined __ppc \ 451 || defined __ppc__ || defined __ppc \
451 || defined __s390__ || defined __s390x__ 452 || defined __s390__ || defined __s390x__) \
453 && defined __OPTIMIZE__
452#define HAVE_FAST_UNALIGNED_ACCESS 1 454#define HAVE_FAST_UNALIGNED_ACCESS 1
455
456/* Load a word from a possibly unaligned address. */
457static inline size_t
458load_unaligned_size_t (const void *p)
459{
460 size_t x;
461 memcpy (&x, p, sizeof x);
462 return x;
463}
464
453#else 465#else
454#define HAVE_FAST_UNALIGNED_ACCESS 0 466#define HAVE_FAST_UNALIGNED_ACCESS 0
455#endif 467#endif
@@ -497,17 +509,12 @@ Symbols are also allowed; their print names are used instead. */)
497 if (HAVE_FAST_UNALIGNED_ACCESS) 509 if (HAVE_FAST_UNALIGNED_ACCESS)
498 { 510 {
499 /* First compare entire machine words. */ 511 /* First compare entire machine words. */
500 typedef size_t word_t; 512 int ws = sizeof (size_t);
501 int ws = sizeof (word_t); 513 const char *w1 = SSDATA (string1);
502 const word_t *w1 = (const word_t *) SDATA (string1); 514 const char *w2 = SSDATA (string2);
503 const word_t *w2 = (const word_t *) SDATA (string2); 515 while (b < nb - ws + 1 && load_unaligned_size_t (w1 + b)
504 while (b < nb - ws + 1) 516 == load_unaligned_size_t (w2 + b))
505 { 517 b += ws;
506 if (UNALIGNED_LOAD_SIZE (w1, b / ws)
507 != UNALIGNED_LOAD_SIZE (w2, b / ws))
508 break;
509 b += ws;
510 }
511 } 518 }
512 519
513 /* Scan forward to the differing byte. */ 520 /* Scan forward to the differing byte. */
diff --git a/src/lisp.h b/src/lisp.h
index cacd318c26f..165fa47b0b3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -5305,26 +5305,6 @@ __lsan_ignore_object (void const *p)
5305} 5305}
5306#endif 5306#endif
5307 5307
5308/* If built with USE_SANITIZER_UNALIGNED_LOAD defined, use compiler
5309 provided ASan functions to perform unaligned loads, allowing ASan
5310 to catch bugs which it might otherwise miss. */
5311#if defined HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H \
5312 && defined ADDRESS_SANITIZER \
5313 && defined USE_SANITIZER_UNALIGNED_LOAD
5314# include <sanitizer/common_interface_defs.h>
5315# if (SIZE_MAX == UINT64_MAX)
5316# define UNALIGNED_LOAD_SIZE(a, i) \
5317 (size_t) __sanitizer_unaligned_load64 ((void *) ((a) + (i)))
5318# elif (SIZE_MAX == UINT32_MAX)
5319# define UNALIGNED_LOAD_SIZE(a, i) \
5320 (size_t) __sanitizer_unaligned_load32 ((void *) ((a) + (i)))
5321# else
5322# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
5323# endif
5324#else
5325# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
5326#endif
5327
5328extern void xputenv (const char *); 5308extern void xputenv (const char *);
5329 5309
5330extern char *egetenv_internal (const char *, ptrdiff_t); 5310extern char *egetenv_internal (const char *, ptrdiff_t);