Repository: neovim/neovim
File: src/nvim/spellfile.c (C)

Code before:
  if (aspath) {
    xmemcpyz(buf, curbuf->b_s.b_p_spl, (size_t)(lstart - curbuf->b_s.b_p_spl - 1));
  } else {
    buf = get_xdg_home(kXDGDataHome);
  }

  if (os_file_is_writable(buf) == 2) {
    if (aspath) {
      xmemcpyz(buf, curbuf->b_s.b_p_spl, (size_t)(lend - curbuf->b_s.b_p_spl));
    } else {
      // Create the "spell" directory if it doesn't exist yet.
      l = (int)strlen(buf);
      vim_snprintf(buf + l, MAXPATHL - (size_t)l, "/spell");
      if (os_file_is_writable(buf) != 2) {
        os_mkdir(buf, 0755);
      }

      l = (int)strlen(buf);
      vim_snprintf(buf + l, MAXPATHL - (size_t)l,
                    "/%.*s", (int)(lend - lstart), lstart);
    }

    l = (int)strlen(buf);
    char *fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
      ->lp_slang->sl_fname;
    vim_snprintf(buf + l, MAXPATHL - (size_t)l, ".%s.add",
        ((fname != NULL
          && strstr(path_tail(fname), ".ascii.") != NULL)
          ? "ascii"
          : spell_enc()));
    set_option_value_give_err(kOptSpellfile, CSTR_AS_OPTVAL(buf), OPT_LOCAL);
  }

  xfree(buf);
}

/// Set the spell character tables from strings in the .spl file.
///
/// @param cnt  length of "flags"
static void set_spell_charflags(const char *flags_in, int cnt, const char *fol)
{
  const uint8_t *flags = (uint8_t *)flags_in;
  // We build the new tables here first, so that we can compare with the
  // previous one.
  spelltab_T new_st;
  const char *p = fol;

  clear_spell_chartab(&new_st);

  for (int i = 0; i < 128; i++) {
    if (i < cnt) {

Review comment (suggestion):
would need to free `buf` before reassigning it here. But instead of doing that, change this to:

```suggestion
  char *buf = aspath? xmalloc(MAXPATHL) : get_xdg_home(kXDGDataHome);
```

Code after:
  size_t buf_len = MAXPATHL;

  if (!aspath) {
    char *xdg_path = get_xdg_home(kXDGDataHome);
    xstrlcpy(buf, xdg_path, buf_len);
    xfree(xdg_path);

    xstrlcat(buf, "/spell", buf_len);

    char *failed_dir;
    if (os_mkdir_recurse(buf, 0755, &failed_dir, NULL) != 0) {
      xfree(buf);
      xfree(failed_dir);
      return;
    }
  } else {
    if ((size_t)(lend - curbuf->b_s.b_p_spl) >= buf_len) {
      xfree(buf);
      return;
    }
    xmemcpyz(buf, curbuf->b_s.b_p_spl, (size_t)(lend - curbuf->b_s.b_p_spl));
  }

  // Append spelllang
  vim_snprintf(buf + strlen(buf), buf_len - strlen(buf), "/%.*s", (int)(lend - lstart), lstart);

  // Append ".ascii.add" or ".{enc}.add"
  char *fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)->lp_slang->sl_fname;
  const char *enc_suffix =
    (fname != NULL && strstr(path_tail(fname), ".ascii.") != NULL) ? "ascii" : spell_enc();
  vim_snprintf(buf + strlen(buf), buf_len - strlen(buf), ".%s.add", enc_suffix);

  set_option_value_give_err(kOptSpellfile, CSTR_AS_OPTVAL(buf), OPT_LOCAL);
  xfree(buf);
}

/// Set the spell character tables from strings in the .spl file.
///
/// @param cnt  length of "flags"
static void set_spell_charflags(const char *flags_in, int cnt, const char *fol)
{
  const uint8_t *flags = (uint8_t *)flags_in;
  // We build the new tables here first, so that we can compare with the
  // previous one.
  spelltab_T new_st;
  const char *p = fol;

  clear_spell_chartab(&new_st);

  for (int i = 0; i < 128; i++) {
    if (i < cnt) {