Skip to content

Commit d209e6f

Browse files
committed
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].
1 parent a8ba2b2 commit d209e6f

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

string.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ VALUE rb_fs;
716716
static inline const char *
717717
search_nonascii(const char *p, const char *e)
718718
{
719-
const uintptr_t *s, *t;
719+
const char *s, *t;
720720

721721
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
722722
# if SIZEOF_UINTPTR_T == 8
@@ -760,17 +760,19 @@ search_nonascii(const char *p, const char *e)
760760
#define aligned_ptr(value) \
761761
__builtin_assume_aligned((value), sizeof(uintptr_t))
762762
#else
763-
#define aligned_ptr(value) (uintptr_t *)(value)
763+
#define aligned_ptr(value) (value)
764764
#endif
765765
s = aligned_ptr(p);
766-
t = (uintptr_t *)(e - (SIZEOF_VOIDP-1));
766+
t = (e - (SIZEOF_VOIDP-1));
767767
#undef aligned_ptr
768-
for (;s < t; s++) {
769-
if (*s & NONASCII_MASK) {
768+
for (;s < t; s += sizeof(uintptr_t)) {
769+
uintptr_t word;
770+
memcpy(&word, s, sizeof(word));
771+
if (word & NONASCII_MASK) {
770772
#ifdef WORDS_BIGENDIAN
771-
return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3);
773+
return (const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
772774
#else
773-
return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
775+
return (const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
774776
#endif
775777
}
776778
}

0 commit comments

Comments
 (0)