https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119016

Tamar Christina <tnfchris at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P1
   Last reconfirmed|                            |2025-02-26
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1

--- Comment #5 from Tamar Christina <tnfchris at gcc dot gnu.org> ---
Confirmed.

Slightly easier to digest case:

---
#include <stddef.h>
#include <stdint.h>

__attribute__((noipa)) char *svn_eol__find_eol_start(char *buf, size_t len) {

  for (; len > sizeof(uintptr_t);
       buf += sizeof(uintptr_t), len -= sizeof(uintptr_t)) {
    uintptr_t chunk = *(const uintptr_t *)buf;

    uintptr_t r_test = chunk ^ 0x0a0a0a0a0a0a0a0a;
    uintptr_t n_test = chunk ^ 0x0d0d0d0d0d0d0d0d;

    r_test |= (r_test & 0x7f7f7f7f7f7f7f7f) + 0x7f7f7f7f7f7f7f7f;
    n_test |= (n_test & 0x7f7f7f7f7f7f7f7f) + 0x7f7f7f7f7f7f7f7f;

    if ((r_test & n_test & 0x8080808080808080) != 0x8080808080808080)
      break;
  }

#pragma GCC novector
  for (; len > 0; ++buf, --len) {
    if (*buf == '\n' || *buf == '\r')
      return buf;
  }

  return ((void *)0);
}

int main() {
  char p[] = {
      0x2f, 0x2a, 0xa,  0x20, 0x20, 0x20, 0x62, 0x75, 0x67, 0x33, 0x33, 0x37,
      0x39, 0x37, 0x32, 0x33, 0x2e, 0x63, 0xa,  0x2a, 0x2f, 0xa,  0xa,  0x23,
      0x69, 0x6e, 0x63,
  };

  size_t len;
  char *end = p + (sizeof(p) / sizeof(p[0]));
  int i = 0;
  do {
    char *start = p + len;

    const char *eol = svn_eol__find_eol_start(start, end - start);
    len += (eol ? eol : end) - start;
    i++;
  } while (((end - p) > len + 2) && i < 100);
}#include <stddef.h>
#include <stdint.h>

__attribute__((noipa)) char *svn_eol__find_eol_start(char *buf, size_t len) {

  for (; len > sizeof(uintptr_t);
       buf += sizeof(uintptr_t), len -= sizeof(uintptr_t)) {
    uintptr_t chunk = *(const uintptr_t *)buf;

    uintptr_t r_test = chunk ^ 0x0a0a0a0a0a0a0a0a;
    uintptr_t n_test = chunk ^ 0x0d0d0d0d0d0d0d0d;

    r_test |= (r_test & 0x7f7f7f7f7f7f7f7f) + 0x7f7f7f7f7f7f7f7f;
    n_test |= (n_test & 0x7f7f7f7f7f7f7f7f) + 0x7f7f7f7f7f7f7f7f;

    if ((r_test & n_test & 0x8080808080808080) != 0x8080808080808080)
      break;
  }

#pragma GCC novector
  for (; len > 0; ++buf, --len) {
    if (*buf == '\n' || *buf == '\r')
      return buf;
  }

  return ((void *)0);
}

int main() {
  char p[] = {
      0x2f, 0x2a, 0xa,  0x20, 0x20, 0x20, 0x62, 0x75, 0x67, 0x33, 0x33, 0x37,
      0x39, 0x37, 0x32, 0x33, 0x2e, 0x63, 0xa,  0x2a, 0x2f, 0xa,  0xa,  0x23,
      0x69, 0x6e, 0x63,
  };

  size_t len;
  char *end = p + (sizeof(p) / sizeof(p[0]));
  int i = 0;
  do {
    char *start = p + len;

    const char *eol = svn_eol__find_eol_start(start, end - start);
    len += (eol ? eol : end) - start;
    i++;
  } while (((end - p) > len + 2) && i < 100);
}

---
The code is peeled but the address ends up being not aligned:

Program received signal SIGSEGV, Segmentation fault.
0x000000000040135f in svn_eol__find_eol_start (buf=<optimized out>,
buf@entry=0x7fffffffe2f2 "\n   bug3379723.c\n*/\n\n#inc\027", len=<optimized
out>, len@entry=25) at oel.c:8
8           uintptr_t chunk = *(const uintptr_t *)buf;
(gdb) display/i $pc
1: x/i $pc
=> 0x40135f <svn_eol__find_eol_start+351>:      movdqa (%rdi,%rsi,1),%xmm10
(gdb) p/x $rdi+$rsi
$1 = 0x7fffffffe2f2

which is not 16-bytes aligned, hence the alignment fault.

Reply via email to