Commit 3edabee2 authored by Chris Metcalf's avatar Chris Metcalf

arch/tile: fix memchr() not to dereference memory for zero length

This change fixes a bug that memchr() will read the first word
of the source even if the length is zero.  Ironically, the code
was originally written with a test to avoid exactly this problem,
but to make the code conform to Linux coding standards with all
declarations preceding all statements, the first load from memory
was moved up above that test as the initial value for a variable.

The change just moves all the variable declarations to the top
of the file, with no initializers, so that the test can also be
at the top of the file.
Signed-off-by: default avatarChris Metcalf <cmetcalf@tilera.com>
parent 4d658d13
...@@ -18,12 +18,24 @@ ...@@ -18,12 +18,24 @@
void *memchr(const void *s, int c, size_t n) void *memchr(const void *s, int c, size_t n)
{ {
const uint32_t *last_word_ptr;
const uint32_t *p;
const char *last_byte_ptr;
uintptr_t s_int;
uint32_t goal, before_mask, v, bits;
char *ret;
if (__builtin_expect(n == 0, 0)) {
/* Don't dereference any memory if the array is empty. */
return NULL;
}
/* Get an aligned pointer. */ /* Get an aligned pointer. */
const uintptr_t s_int = (uintptr_t) s; s_int = (uintptr_t) s;
const uint32_t *p = (const uint32_t *)(s_int & -4); p = (const uint32_t *)(s_int & -4);
/* Create four copies of the byte for which we are looking. */ /* Create four copies of the byte for which we are looking. */
const uint32_t goal = 0x01010101 * (uint8_t) c; goal = 0x01010101 * (uint8_t) c;
/* Read the first word, but munge it so that bytes before the array /* Read the first word, but munge it so that bytes before the array
* will not match goal. * will not match goal.
...@@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n) ...@@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n)
* Note that this shift count expression works because we know * Note that this shift count expression works because we know
* shift counts are taken mod 32. * shift counts are taken mod 32.
*/ */
const uint32_t before_mask = (1 << (s_int << 3)) - 1; before_mask = (1 << (s_int << 3)) - 1;
uint32_t v = (*p | before_mask) ^ (goal & before_mask); v = (*p | before_mask) ^ (goal & before_mask);
/* Compute the address of the last byte. */ /* Compute the address of the last byte. */
const char *const last_byte_ptr = (const char *)s + n - 1; last_byte_ptr = (const char *)s + n - 1;
/* Compute the address of the word containing the last byte. */ /* Compute the address of the word containing the last byte. */
const uint32_t *const last_word_ptr = last_word_ptr = (const uint32_t *)((uintptr_t) last_byte_ptr & -4);
(const uint32_t *)((uintptr_t) last_byte_ptr & -4);
uint32_t bits;
char *ret;
if (__builtin_expect(n == 0, 0)) {
/* Don't dereference any memory if the array is empty. */
return NULL;
}
while ((bits = __insn_seqb(v, goal)) == 0) { while ((bits = __insn_seqb(v, goal)) == 0) {
if (__builtin_expect(p == last_word_ptr, 0)) { if (__builtin_expect(p == last_word_ptr, 0)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment