@@ -20,6 +20,17 @@
#include <stdint.h>
#include "string-endian.h"
+static uintptr_t
+saturating_add (uintptr_t p, size_t n)
+{
+#ifdef _LP64
+ uintptr_t result = p + n;
+ return __glibc_likely (result >= p) ? result : UINTPTR_MAX;
+#else
+ return __insn_addxsc (p, n);
+#endif
+}
+
void *
__memchr (const void *s, int c, size_t n)
{
@@ -49,7 +60,7 @@ __memchr (const void *s, int c, size_t n)
v = (*p | before_mask) ^ (goal & before_mask);
/* Compute the address of the last byte. */
- last_byte_ptr = (const char *) s + n - 1;
+ last_byte_ptr = (const char *) saturating_add ((uintptr_t) s, n - 1);
/* Compute the address of the word containing the last byte. */
last_word_ptr = (const uint64_t *) ((uintptr_t) last_byte_ptr & -8);
@@ -48,8 +48,8 @@ __memchr (const void *s, int c, size_t n)
before_mask = (1 << (s_int << 3)) - 1;
v = (*p | before_mask) ^ (goal & before_mask);
- /* Compute the address of the last byte. */
- last_byte_ptr = (const char *) s + n - 1;
+ /* Compute the address of the last byte using a saturating add. */
+ last_byte_ptr = (const char *) __insn_adds ((uintptr_t) s, n - 1);
/* Compute the address of the word containing the last byte. */
last_word_ptr = (const uint32_t *) ((uintptr_t) last_byte_ptr & -4);