summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2025-11-26 21:59:37 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2025-12-16 13:06:03 -0500
commitd209e6f1c0a93ad3ce1cc64dd165a6b67672614d (patch)
tree6217c896e2de8f91e657e09e0b066dda6f431a35 /string.c
parenta8ba2b295b73a116d24fe5602d892d4a2042cd08 (diff)
search_nonascii(): Replace UB pointer cast with memcpy
Casting a pointer to create an unaligned one is undefined behavior in C standards. Use memcpy to express the unaligned load instead to play by the rules. Practically, this yields the same binary output in many situations while fixing the crash in [Bug #21715].
Diffstat (limited to 'string.c')
-rw-r--r--string.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/string.c b/string.c
index 060a1467a0..9819a5910f 100644
--- a/string.c
+++ b/string.c
@@ -716,7 +716,7 @@ VALUE rb_fs;
static inline const char *
search_nonascii(const char *p, const char *e)
{
- const uintptr_t *s, *t;
+ const char *s, *t;
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# if SIZEOF_UINTPTR_T == 8
@@ -760,17 +760,19 @@ search_nonascii(const char *p, const char *e)
#define aligned_ptr(value) \
__builtin_assume_aligned((value), sizeof(uintptr_t))
#else
-#define aligned_ptr(value) (uintptr_t *)(value)
+#define aligned_ptr(value) (value)
#endif
s = aligned_ptr(p);
- t = (uintptr_t *)(e - (SIZEOF_VOIDP-1));
+ t = (e - (SIZEOF_VOIDP-1));
#undef aligned_ptr
- for (;s < t; s++) {
- if (*s & NONASCII_MASK) {
+ for (;s < t; s += sizeof(uintptr_t)) {
+ uintptr_t word;
+ memcpy(&word, s, sizeof(word));
+ if (word & NONASCII_MASK) {
#ifdef WORDS_BIGENDIAN
- return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
#else
- return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
#endif
}
}