diff options
author | James McCoy <jamessan@jamessan.com> | 2017-08-08 22:18:50 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2017-08-10 00:56:07 +0200 |
commit | ac055d677aa9eff9fca11cecb5ac7f7a4edb0265 (patch) | |
tree | 4b0b0a74ae39fc3cdad55f244fc2142618e1ceae /test/unit | |
parent | 085102fadf1c1371e863c0e9af8240038ce641e2 (diff) | |
download | rneovim-ac055d677aa9eff9fca11cecb5ac7f7a4edb0265.tar.gz rneovim-ac055d677aa9eff9fca11cecb5ac7f7a4edb0265.tar.bz2 rneovim-ac055d677aa9eff9fca11cecb5ac7f7a4edb0265.zip |
os_stat: return ENOENT on NULL filename arg
Closes #4370
Explication:
In the backtrace in #4370, we see that `buf_write()` was called with
non-NULL `fname` and `sfname` arguments, but they've since _become_
NULL.
#7 0x00000000004de09d in buf_write (buf=0x1dee040, fname=0x0, fname@entry=0x1e985b0 "/home/sean/src/github.com/snczl/virta/pkg/meld/segment.go",
sfname=0x0, sfname@entry=0x1ddfa60 "segment.go", start=1, end=72, eap=eap@entry=0x7ffc6b032e60, append=0,
forceit=0, reset_changed=1, filtering=0)
at /home/travis/build/neovim/bot-ci/build/neovim/src/nvim/fileio.c:2576
This is most likely due to the code that restores those values from
`buf`, which happens just before the fatal call to `os_fileinfo`
```c
/*
* The autocommands may have changed the name of the buffer, which may
* be kept in fname, ffname and sfname.
*/
if (buf_ffname)
ffname = buf->b_ffname;
if (buf_sfname)
sfname = buf->b_sfname;
if (buf_fname_f)
fname = buf->b_ffname;
if (buf_fname_s)
fname = buf->b_sfname;
```
It's worth noting that at this point `ffname` is still non-NULL, so
it _could_ be used. However, our current code is purely more strict
than Vim in this area, which has caused us problems before (e.g.,
`getdigits()`). The commentary for `struct file_buffer` clearly
indicate that all of `b_ffname`, `b_sfname`, and `b_fname` may be
NULL:
```c
/*
* b_ffname has the full path of the file (NULL for no name).
* b_sfname is the name as the user typed it (or NULL).
* b_fname is the same as b_sfname, unless ":cd" has been done,
* then it is the same as b_ffname (NULL for no name).
*/
char_u *b_ffname; /* full path file name */
char_u *b_sfname; /* short file name */
char_u *b_fname; /* current file name */
```
Vim directly calls `stat(2)` which, although it is annotated to tell
the compiler that the path argument is non-NULL, does handle a NULL
pointer by returning a `-1` value and setting `errno` to `EFAULT`.
This satisfies Vim's check, since it treats any `-1` return from
`stat(2)` to mean the file doesn't exist (at least in this code
path).
Note that Vim's mch_stat() implementations on win32 and solaris
clearly cannot accept NULL `name`. But the codepaths that call
mch_stat will NULL `name` tend to be unix-only (eg: u_read_undo)!
Diffstat (limited to 'test/unit')
-rw-r--r-- | test/unit/os/fs_spec.lua | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index 23eb05b4b8..bc39507c08 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -862,6 +862,11 @@ describe('fs.c', function() end describe('os_fileinfo', function() + itp('returns false if path=NULL', function() + local file_info = file_info_new() + assert.is_false((fs.os_fileinfo(nil, file_info))) + end) + itp('returns false if given a non-existing file', function() local file_info = file_info_new() assert.is_false((fs.os_fileinfo('/non-existent', file_info))) |