]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Fix handling of objects with many xattrs on FreeBSD
authorPeter Eriksson <peter.x.eriksson@liu.se>
Tue, 13 May 2025 12:01:01 +0000 (14:01 +0200)
committerAndrew Tridgell <andrew@tridgell.net>
Sat, 23 Aug 2025 07:31:28 +0000 (17:31 +1000)
lib/sysxattrs.c

index ca08d1319614323e801f573757ba55aa6c50b178..5a6aeaad982992c9c557ab7f49f8dae265c3399d 100644 (file)
@@ -126,9 +126,18 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
        unsigned char keylen;
        ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
 
-       if (len <= 0 || (size_t)len > size)
+       if (len <= 0 || size == 0)
                return len;
 
+       if ((size_t)len >= size) {
+               /* FreeBSD extattr_list_xx() returns 'size' as 'len' in case there are                                                              
+                   more data available, truncating the output, we solve this by signalling                                                          
+                   ERANGE in case len == size so that the code in xattrs.c will retry with                                                          
+                   a bigger buffer */
+               errno = ERANGE;
+               return -1;
+       }
+
        /* FreeBSD puts a single-byte length before each string, with no '\0'
         * terminator.  We need to change this into a series of null-terminted
         * strings.  Since the size is the same, we can simply transform the
@@ -136,7 +145,7 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
        for (off = 0; off < len; off += keylen + 1) {
                keylen = ((unsigned char*)list)[off];
                if (off + keylen >= len) {
-                       /* Should be impossible, but kernel bugs happen! */
+                       /* Should be impossible, but bugs happen! */
                        errno = EINVAL;
                        return -1;
                }