Abbruch anstelle von Segfault mit klarer Speicherverletzung

Ich bin auf dieses seltsame Verhalten gestoßen, als ich mich mit C-Strings befasste. Dies ist eine Übung aus dem K & R-Buch, in der ich eine Funktion schreiben sollte, die eine Zeichenfolge an das Ende einer anderen Zeichenfolge anfügt. Dies erfordert offensichtlich, dass der Zielzeichenfolge genügend Speicher zugewiesen ist, damit die Quellzeichenfolge passt. Hier ist der Code:

 /* strcat: Copies contents of source at the end of dest */
 char *strcat(char *dest, const char* source) {
  char *d = dest;
  // Move to the end of dest
  while (*dest != '\0') {
    dest++;
  } // *dest is now '\0'

  while (*source != '\0') {
    *dest++ = *source++;
  }
  *dest = '\0';
  return d;
}

Während des Tests habe ich Folgendes geschrieben, wobei ich davon ausgegangen bin, dass ein Segfault auftritt, während das Programm ausgeführt wird:

int main() {
  char s1[] = "hello";
  char s2[] = "eheheheheheh"; 
  printf("%s\n", strcat(s1, s2));
}

Soweit ich weiß, bekommt s1 ein Array von 6chars zugewiesen und s2 ein Array von 13chars. Ich dachte das wennstrcat versucht, bei Indizes über 6 in s1 zu schreiben, würde das Programm einen Fehler verursachen. Stattdessen funktioniert alles einwandfrei, aber das Programm wird nicht sauber beendet. Stattdessen geschieht Folgendes:

helloeheheheheheh
zsh: abort      ./a.out

und beendet mit Code 134, was meiner Meinung nach nur Abbruch bedeutet.

Warum erhalte ich keinen Segfault (oder überschreibe s2 nicht, wenn die Strings auf dem Stack zugewiesen sind)? Wo befinden sich diese Zeichenfolgen im Speicher (der Stapel oder der Haufen)?

Danke für Ihre Hilfe.