// https://syzkaller.appspot.com/bug?id=a74718ca902617e6aa7327aa008b25844eccf2d3
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <endian.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <termios.h>
#include <unistd.h>
#include <util.h>

static __thread int skip_segv;
static __thread jmp_buf segv_env;

static void segv_handler(int sig, siginfo_t* info, void* ctx)
{
  uintptr_t addr = (uintptr_t)info->si_addr;
  const uintptr_t prog_start = 1 << 20;
  const uintptr_t prog_end = 100 << 20;
  if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) &&
      (addr < prog_start || addr > prog_end)) {
    _longjmp(segv_env, 1);
  }
  exit(sig);
}

static void install_segv_handler(void)
{
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_sigaction = segv_handler;
  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
  sigaction(SIGSEGV, &sa, NULL);
  sigaction(SIGBUS, &sa, NULL);
}

#define NONFAILING(...)                                                        \
  {                                                                            \
    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
    if (_setjmp(segv_env) == 0) {                                              \
      __VA_ARGS__;                                                             \
    }                                                                          \
    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
  }

static void use_temporary_dir(void)
{
  char tmpdir_template[] = "./syzkaller.XXXXXX";
  char* tmpdir = mkdtemp(tmpdir_template);
  if (!tmpdir)
    exit(1);
  if (chmod(tmpdir, 0777))
    exit(1);
  if (chdir(tmpdir))
    exit(1);
}

#define __syscall syscall

static uintptr_t syz_open_pts(void)
{
  int master, slave;
  if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
    return -1;
  if (dup2(master, master + 100) != -1)
    close(master);
  return slave;
}

uint64_t r[1] = {0xffffffffffffffff};

int main(void)
{
  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 3ul, 0x1012ul, -1, 0ul, 0ul);
  install_segv_handler();
  use_temporary_dir();
  intptr_t res = 0;
  res = syz_open_pts();
  if (res != -1)
    r[0] = res;
  NONFAILING(*(uint64_t*)0x200001c0 = 0x20000080);
  NONFAILING(memcpy(
      (void*)0x20000080,
      "\x1a\x2e\xee\xa8\x5f\x96\x5e\x1c\x7c\xf2\x0e\x2d\xa9\x43\x34\x9f\x13\x07"
      "\x7f\x9c\x2c\x18\x70\x5c\xa7\x5e\x9c\xa5\xa7\x21\x1b\x26\x5f\x7d\x7e\x65"
      "\x93\x46\xd3\x04\xf8\x46\x97\xb9\x54\xf5\xc5\x20\xc4\x6b\x7f\x12\xd2\x6b"
      "\x1b\x2b\xd9\x73\x7b\x6e\xe0\x41\x51\x98\xf8\x3d\x6e\xd4\x10\xa2\x5e\xe1"
      "\xd9\xe6\xae\x4a\xae\xc9\xd2\x0c\x75\x76\x97\xad\x09\xb7\xab\x45\xfd\xbe"
      "\xb4\x71\x24\x2d\xc8\xf0\xd7\x60\x2a\x47\x81\xf9\xd5\x36\x1f\x20\x7a\x2d"
      "\xed\x39\x60\x8f\xbf\x0f\xa2\x9b\x98\x30\xbd\xa3\x8f\x7b\x47\x23\xf0\x6c"
      "\x67\x56\x72\xaf\xbb\x17\xeb\xd3\x7a\xf1\x53\x39\xb2\xe4\x25\x93\x33\x06"
      "\x52\xf4\xca\xf5\x73\x31\x81\xea\x72\x90\xab\xd7\x45\x41\x5b\xab\x90\x70"
      "\x06\x6b\x88\x57\xa3\x29\x98\xfa\x5c\x35\xc2\x48\xdf\x95\x4b\xa1\x6f\x9e"
      "\x75\xd1\x99\x67\x82\x9a\x5c\xde",
      188));
  NONFAILING(*(uint64_t*)0x200001c8 = 0xbc);
  syscall(SYS_writev, r[0], 0x200001c0ul, 1ul);
  return 0;
}