vfs_fruit: fix offset and len handling for AFP_AfpInfo stream
authorRalph Boehme <slow@samba.org>
Sat, 19 Dec 2015 10:06:19 +0000 (11:06 +0100)
committerJeremy Allison <jra@samba.org>
Mon, 21 Dec 2015 22:21:18 +0000 (23:21 +0100)
When reading from the AFP_AfpInfo stream, OS X ignores the offset from
the request and always reads from offset=0.

The offset bounds check has a off-by-1 bug in OS X, so a request
offset=60 (AFP_AfpInfo stream has a ficed size of 60 bytes), len=1
returns 1 byte from offset 0 insteaf of returning 0.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11347

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_fruit.c

index 697783291ccfa60742e4c529db23d42e26dc0dc1..34b35247b0b670ca266b6b59fadb6659a2710566 100644 (file)
@@ -2700,13 +2700,19 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
                char afpinfo_buf[AFP_INFO_SIZE];
                size_t to_return;
 
-               if ((offset < 0) || (offset >= AFP_INFO_SIZE)) {
+               /*
+                * OS X has a off-by-1 error in the offset calculation, so we're
+                * bug compatible here. It won't hurt, as any relevant real
+                * world read requests from the AFP_AfpInfo stream will be
+                * offset=0 n=60. offset is ignored anyway, see below.
+                */
+               if ((offset < 0) || (offset >= AFP_INFO_SIZE + 1)) {
                        len = 0;
                        rc = 0;
                        goto exit;
                }
 
-               to_return = AFP_INFO_SIZE - offset;
+               to_return = MIN(n, AFP_INFO_SIZE);
 
                ai = afpinfo_new(talloc_tos());
                if (ai == NULL) {
@@ -2729,7 +2735,10 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
                        goto exit;
                }
 
-               memcpy(data, afpinfo_buf + offset, to_return);
+               /*
+                * OS X ignores offset when reading from AFP_AfpInfo stream!
+                */
+               memcpy(data, afpinfo_buf, to_return);
                len = to_return;
        } else {
                len = SMB_VFS_NEXT_PREAD(