Win32: Fix reparse point fixup bugs
authorEric Biggers <ebiggers3@gmail.com>
Sat, 18 May 2013 04:25:42 +0000 (23:25 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sat, 18 May 2013 04:25:42 +0000 (23:25 -0500)
include/wimlib/reparse.h
src/reparse.c
src/win32_apply.c
src/win32_capture.c

index ff422a1..577e932 100644 (file)
@@ -58,7 +58,8 @@ parse_reparse_data(const u8 * restrict rpbuf, u16 rpbuflen,
 
 extern int
 make_reparse_buffer(const struct reparse_data * restrict rpdata,
-                   u8 * restrict rpbuf);
+                   u8 * restrict rpbuf,
+                   u16 * restrict rpbuflen_ret);
 
 extern int
 wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
index b097212..4659001 100644 (file)
@@ -215,7 +215,8 @@ out_invalid:
  */
 int
 make_reparse_buffer(const struct reparse_data * restrict rpdata,
-                   u8 * restrict rpbuf)
+                   u8 * restrict rpbuf,
+                   u16 * restrict rpbuflen_ret)
 {
        struct reparse_buffer_disk *rpbuf_disk =
                (struct reparse_buffer_disk*)rpbuf;
@@ -252,6 +253,7 @@ make_reparse_buffer(const struct reparse_data * restrict rpdata,
        *(utf16lechar*)data = cpu_to_le16(0);
        data += 2;
        rpbuf_disk->rpdatalen = cpu_to_le16(data - rpbuf - 8);
+       *rpbuflen_ret = data - rpbuf;
        return 0;
 }
 
@@ -399,6 +401,7 @@ wim_inode_set_symlink(struct wim_inode *inode,
        utf16lechar *name_utf16le;
        size_t name_utf16le_nbytes;
        int ret;
+       u16 rpbuflen;
 
        DEBUG("Creating reparse point data buffer for UNIX "
              "symlink target \"%s\"", target);
@@ -481,11 +484,11 @@ wim_inode_set_symlink(struct wim_inode *inode,
                rpdata.rpflags = SYMBOLIC_LINK_RELATIVE;
        }
 
-       ret = make_reparse_buffer(&rpdata, (u8*)&rpbuf_disk);
+       ret = make_reparse_buffer(&rpdata, (u8*)&rpbuf_disk, &rpbuflen);
        if (ret == 0) {
                ret = inode_set_unnamed_stream(inode,
                                               (u8*)&rpbuf_disk + 8,
-                                              le16_to_cpu(rpbuf_disk.rpdatalen),
+                                              rpbuflen - 8,
                                               lookup_table);
        }
        FREE(name_utf16le);
index c91315c..010b9be 100644 (file)
@@ -57,6 +57,7 @@ L"If you are not running this program as the administrator, you may\n"
 
 static int
 win32_extract_try_rpfix(u8 *rpbuf,
+                       u16 *rpbuflen_p,
                        const wchar_t *extract_root_realpath,
                        unsigned extract_root_realpath_nchars)
 {
@@ -74,8 +75,7 @@ win32_extract_try_rpfix(u8 *rpbuf,
        size_t new_print_name_nchars;
        utf16lechar *p;
 
-       ret = parse_reparse_data(rpbuf, 8 + le16_to_cpu(*(u16*)(rpbuf + 4)),
-                                &rpdata);
+       ret = parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata);
        if (ret)
                return ret;
 
@@ -119,12 +119,10 @@ win32_extract_try_rpfix(u8 *rpbuf,
                *p++ = extract_root_realpath[1];
        }
        /* Copy the rest of the extract root */
-       wmemcpy(p, extract_root_realpath + 2, extract_root_realpath_nchars - 2);
-       p += extract_root_realpath_nchars - 2;
+       p = wmempcpy(p, extract_root_realpath + 2, extract_root_realpath_nchars - 2);
 
        /* Append the stripped target */
-       wmemcpy(p, stripped_target, stripped_target_nchars);
-       p += stripped_target_nchars;
+       p = wmempcpy(p, stripped_target, stripped_target_nchars);
        new_target_nchars = p - new_target;
        new_print_name_nchars = p - new_print_name;
 
@@ -138,7 +136,7 @@ win32_extract_try_rpfix(u8 *rpbuf,
        rpdata.substitute_name_nbytes = new_target_nchars * sizeof(utf16lechar);
        rpdata.print_name = new_print_name;
        rpdata.print_name_nbytes = new_print_name_nchars * sizeof(utf16lechar);
-       return make_reparse_buffer(&rpdata, rpbuf);
+       return make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p);
 }
 
 /* Wrapper around the FSCTL_SET_REPARSE_POINT ioctl to set the reparse data on
@@ -151,7 +149,7 @@ win32_set_reparse_data(HANDLE h,
                       struct apply_args *args)
 {
        int ret;
-       u8 rpbuf[REPARSE_POINT_MAX_SIZE];
+       u8 rpbuf[REPARSE_POINT_MAX_SIZE] _aligned_attribute(8);
        DWORD bytesReturned;
        u16 rpbuflen;
 
@@ -167,6 +165,7 @@ win32_set_reparse_data(HANDLE h,
            !inode->i_not_rpfixed)
        {
                ret = win32_extract_try_rpfix(rpbuf,
+                                             &rpbuflen,
                                              args->target_realpath,
                                              args->target_realpath_len);
                if (ret)
index c05eb19..a2d6797 100644 (file)
@@ -506,12 +506,10 @@ win32_capture_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                        const wchar_t *path)
 {
        struct reparse_data rpdata;
-       DWORD rpbuflen;
        int ret;
        enum rp_status rp_status;
 
-       rpbuflen = *rpbuflen_p;
-       ret = parse_reparse_data(rpbuf, rpbuflen, &rpdata);
+       ret = parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata);
        if (ret)
                return -ret;
 
@@ -535,7 +533,7 @@ win32_capture_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                        rpdata.print_name += 4;
                        rpdata.print_name_nbytes -= 8;
                }
-               ret = make_reparse_buffer(&rpdata, rpbuf);
+               ret = make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p);
                if (ret == 0)
                        ret = rp_status;
                else