diff options
author | Paul R. Tagliamonte <paultag@gmail.com> | 2024-03-10 08:35:10 +0100 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-03-10 08:53:33 +0100 |
commit | 14759ded57447345ba11c11a99fd84344797862c (patch) | |
tree | df5ee1f770eb20b1f050f3e0d6a76845b5c6357b /src | |
parent | ca0e0d2708eded356e9c14cbc22578b9a1b62181 (diff) |
patch 9.1.0162: problem with writing extended attributes on failurev9.1.0162
Problem: problem with writing extended attributes on failure
Solution: Change return type to ssize_t and check listxattr's return
value correctly on failure (Paul Tagliamonte)
The existing logic will return when the listxattr call returns with the
errno set to ENOTSUP (or a size of 0 bytes), without checking to see if
listxattr actually failed. listxattr can fail with at least E2BIG,
ENOTSUP, ERANGE, or anything that `stat(2)` can fail with (in my case;
ENOENT from stat).
The returned size is stored to a size_t, but the return type is a
ssize_t. On failure, listxattr returns -1, which will get translated to
size_t's MAX. If the listxattr call failed with anything other than
ENOTSUP, this triggers a request for size_t MAX bytes.
This means that, if the listxattr call fails with anything other than
ENOTSUP on save, vim will error with
`E342: Out of memory! (allocating 18446744073709551615 bytes)`
(keen observers will note 18446744073709551615 is 0xffffffffffffffff)
In reality, this is likely masking a different (usually filesystem?)
error -- but at least it's an error being pushed to the user now, and we
don't try to allocate size_t MAX bytes.
I've opted to change the type that we store listxattr to from size_t to
ssize_t, to match listxattr(2)'s signature, and to check for the -1
return value. Additionally, I've removed the errno check -- if we get a
listxattr failure for any reason, we may as well bail without trying;
it's not like we can even recover.
closes: #14169
Signed-off-by: Paul Tagliamonte <paultag@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/os_unix.c | 8 | ||||
-rw-r--r-- | src/version.c | 2 |
2 files changed, 6 insertions, 4 deletions
diff --git a/src/os_unix.c b/src/os_unix.c index dae5bbe827..e98911e0f8 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3048,7 +3048,7 @@ mch_copy_sec(char_u *from_file, char_u *to_file) size = listxattr((char *)from_file, NULL, 0); // not supported or no attributes to copy - if (errno == ENOTSUP || size == 0) + if (size <= 0) return; for (index = 0 ; index < (int)(sizeof(smack_copied_attributes) @@ -3112,8 +3112,8 @@ mch_copy_sec(char_u *from_file, char_u *to_file) mch_copy_xattr(char_u *from_file, char_u *to_file) { char *xattr_buf; - size_t size; - size_t tsize; + ssize_t size; + ssize_t tsize; ssize_t keylen, vallen, max_vallen = 0; char *key; char *val = NULL; @@ -3125,7 +3125,7 @@ mch_copy_xattr(char_u *from_file, char_u *to_file) // get the length of the extended attributes size = listxattr((char *)from_file, NULL, 0); // not supported or no attributes to copy - if (errno == ENOTSUP || size == 0) + if (size <= 0) return; xattr_buf = (char*)alloc(size); if (xattr_buf == NULL) diff --git a/src/version.c b/src/version.c index 8f28596f05..cc63356153 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 162, +/**/ 161, /**/ 160, |