Skip to content

Commit 3d6014f

Browse files
committed
patch 8.1.0470: pointer ownership around fname_expand() is unclear
Problem: Pointer ownership around fname_expand() is unclear. Solution: Allow b_ffname and b_sfname to point to the same allocated memory, only free one. Update comments.
1 parent 108e7b4 commit 3d6014f

5 files changed

Lines changed: 55 additions & 28 deletions

File tree

src/buffer.c

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,11 @@ close_buffer(
663663
workshop_file_closed_lineno((char *)buf->b_ffname,
664664
(int)buf->b_last_cursor.lnum);
665665
#endif
666-
vim_free(buf->b_ffname);
667-
vim_free(buf->b_sfname);
666+
if (buf->b_sfname != buf->b_ffname)
667+
VIM_CLEAR(buf->b_sfname);
668+
else
669+
buf->b_sfname = NULL;
670+
VIM_CLEAR(buf->b_ffname);
668671
if (buf->b_prev == NULL)
669672
firstbuf = buf->b_next;
670673
else
@@ -1877,11 +1880,13 @@ curbuf_reusable(void)
18771880
*/
18781881
buf_T *
18791882
buflist_new(
1880-
char_u *ffname, /* full path of fname or relative */
1881-
char_u *sfname, /* short fname or NULL */
1882-
linenr_T lnum, /* preferred cursor line */
1883-
int flags) /* BLN_ defines */
1883+
char_u *ffname_arg, // full path of fname or relative
1884+
char_u *sfname_arg, // short fname or NULL
1885+
linenr_T lnum, // preferred cursor line
1886+
int flags) // BLN_ defines
18841887
{
1888+
char_u *ffname = ffname_arg;
1889+
char_u *sfname = sfname_arg;
18851890
buf_T *buf;
18861891
#ifdef UNIX
18871892
stat_T st;
@@ -1890,7 +1895,7 @@ buflist_new(
18901895
if (top_file_num == 1)
18911896
hash_init(&buf_hashtab);
18921897

1893-
fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */
1898+
fname_expand(curbuf, &ffname, &sfname); // will allocate ffname
18941899

18951900
/*
18961901
* If file name already exists in the list, update the entry.
@@ -1997,8 +2002,11 @@ buflist_new(
19972002
if ((ffname != NULL && (buf->b_ffname == NULL || buf->b_sfname == NULL))
19982003
|| buf->b_wininfo == NULL)
19992004
{
2005+
if (buf->b_sfname != buf->b_ffname)
2006+
VIM_CLEAR(buf->b_sfname);
2007+
else
2008+
buf->b_sfname = NULL;
20002009
VIM_CLEAR(buf->b_ffname);
2001-
VIM_CLEAR(buf->b_sfname);
20022010
if (buf != curbuf)
20032011
free_buffer(buf);
20042012
return NULL;
@@ -3103,18 +3111,21 @@ buflist_name_nr(
31033111
}
31043112

31053113
/*
3106-
* Set the file name for "buf"' to 'ffname', short file name to 'sfname'.
3114+
* Set the file name for "buf"' to "ffname_arg", short file name to
3115+
* "sfname_arg".
31073116
* The file name with the full path is also remembered, for when :cd is used.
31083117
* Returns FAIL for failure (file name already in use by other buffer)
31093118
* OK otherwise.
31103119
*/
31113120
int
31123121
setfname(
31133122
buf_T *buf,
3114-
char_u *ffname,
3115-
char_u *sfname,
3123+
char_u *ffname_arg,
3124+
char_u *sfname_arg,
31163125
int message) /* give message when buffer already exists */
31173126
{
3127+
char_u *ffname = ffname_arg;
3128+
char_u *sfname = sfname_arg;
31183129
buf_T *obuf = NULL;
31193130
#ifdef UNIX
31203131
stat_T st;
@@ -3123,8 +3134,11 @@ setfname(
31233134
if (ffname == NULL || *ffname == NUL)
31243135
{
31253136
/* Removing the name. */
3137+
if (buf->b_sfname != buf->b_ffname)
3138+
VIM_CLEAR(buf->b_sfname);
3139+
else
3140+
buf->b_sfname = NULL;
31263141
VIM_CLEAR(buf->b_ffname);
3127-
VIM_CLEAR(buf->b_sfname);
31283142
#ifdef UNIX
31293143
st.st_dev = (dev_T)-1;
31303144
#endif
@@ -3175,8 +3189,9 @@ setfname(
31753189
# endif
31763190
fname_case(sfname, 0); /* set correct case for short file name */
31773191
#endif
3192+
if (buf->b_sfname != buf->b_ffname)
3193+
vim_free(buf->b_sfname);
31783194
vim_free(buf->b_ffname);
3179-
vim_free(buf->b_sfname);
31803195
buf->b_ffname = ffname;
31813196
buf->b_sfname = sfname;
31823197
}
@@ -3210,7 +3225,8 @@ buf_set_name(int fnum, char_u *name)
32103225
buf = buflist_findnr(fnum);
32113226
if (buf != NULL)
32123227
{
3213-
vim_free(buf->b_sfname);
3228+
if (buf->b_sfname != buf->b_ffname)
3229+
vim_free(buf->b_sfname);
32143230
vim_free(buf->b_ffname);
32153231
buf->b_ffname = vim_strsave(name);
32163232
buf->b_sfname = NULL;
@@ -4820,27 +4836,31 @@ fix_fname(char_u *fname)
48204836
}
48214837

48224838
/*
4823-
* Make "ffname" a full file name, set "sfname" to "ffname" if not NULL.
4824-
* "ffname" becomes a pointer to allocated memory (or NULL).
4839+
* Make "*ffname" a full file name, set "*sfname" to "*ffname" if not NULL.
4840+
* "*ffname" becomes a pointer to allocated memory (or NULL).
4841+
* When resolving a link both "*sfname" and "*ffname" will point to the same
4842+
* allocated memory.
4843+
* The "*ffname" and "*sfname" pointer values on call will not be freed.
4844+
* Note that the resulting "*ffname" pointer should be considered not allocaed.
48254845
*/
48264846
void
48274847
fname_expand(
48284848
buf_T *buf UNUSED,
48294849
char_u **ffname,
48304850
char_u **sfname)
48314851
{
4832-
if (*ffname == NULL) /* if no file name given, nothing to do */
4852+
if (*ffname == NULL) // no file name given, nothing to do
48334853
return;
4834-
if (*sfname == NULL) /* if no short file name given, use ffname */
4854+
if (*sfname == NULL) // no short file name given, use ffname
48354855
*sfname = *ffname;
4836-
*ffname = fix_fname(*ffname); /* expand to full path */
4856+
*ffname = fix_fname(*ffname); // expand to full path
48374857

48384858
#ifdef FEAT_SHORTCUT
48394859
if (!buf->b_p_bin)
48404860
{
48414861
char_u *rfname;
48424862

4843-
/* If the file name is a shortcut file, use the file it links to. */
4863+
// If the file name is a shortcut file, use the file it links to.
48444864
rfname = mch_resolve_shortcut(*ffname);
48454865
if (rfname != NULL)
48464866
{

src/ex_cmds.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,8 +3648,8 @@ check_readonly(int *forceit, buf_T *buf)
36483648
}
36493649

36503650
/*
3651-
* Try to abandon current file and edit a new or existing file.
3652-
* "fnum" is the number of the file, if zero use ffname/sfname.
3651+
* Try to abandon the current file and edit a new or existing file.
3652+
* "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg".
36533653
* "lnum" is the line number for the cursor in the new file (if non-zero).
36543654
*
36553655
* Return:
@@ -3661,12 +3661,14 @@ check_readonly(int *forceit, buf_T *buf)
36613661
int
36623662
getfile(
36633663
int fnum,
3664-
char_u *ffname,
3665-
char_u *sfname,
3664+
char_u *ffname_arg,
3665+
char_u *sfname_arg,
36663666
int setpm,
36673667
linenr_T lnum,
36683668
int forceit)
36693669
{
3670+
char_u *ffname = ffname_arg;
3671+
char_u *sfname = sfname_arg;
36703672
int other;
36713673
int retval;
36723674
char_u *free_me = NULL;

src/fileio.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6187,7 +6187,8 @@ shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
61876187
|| buf->b_sfname == NULL
61886188
|| mch_isFullName(buf->b_sfname)))
61896189
{
6190-
VIM_CLEAR(buf->b_sfname);
6190+
if (buf->b_sfname != buf->b_ffname)
6191+
VIM_CLEAR(buf->b_sfname);
61916192
p = shorten_fname(buf->b_ffname, dirname);
61926193
if (p != NULL)
61936194
{

src/structs.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,9 +1972,11 @@ struct file_buffer
19721972
* b_fname is the same as b_sfname, unless ":cd" has been done,
19731973
* then it is the same as b_ffname (NULL for no name).
19741974
*/
1975-
char_u *b_ffname; /* full path file name */
1976-
char_u *b_sfname; /* short file name */
1977-
char_u *b_fname; /* current file name */
1975+
char_u *b_ffname; // full path file name, allocated
1976+
char_u *b_sfname; // short file name, allocated, may be equal to
1977+
// b_ffname
1978+
char_u *b_fname; // current file name, points to b_ffname or
1979+
// b_sfname
19781980

19791981
#ifdef UNIX
19801982
int b_dev_valid; /* TRUE when b_dev has a valid number */

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,8 @@ static char *(features[]) =
792792

793793
static int included_patches[] =
794794
{ /* Add new patch number below this line */
795+
/**/
796+
470,
795797
/**/
796798
469,
797799
/**/

0 commit comments

Comments
 (0)