]> wimlib.net Git - wimlib/blobdiff - src/reparse.c
Prevent huge memory allocations from fuzzed header fields
[wimlib] / src / reparse.c
index 284398ac0d672a610e82858b2af684801a3615c6..74bb56fd22e258a71d9e4105430d4b2206405794 100644 (file)
 #include "wimlib/endianness.h"
 #include "wimlib/encoding.h"
 #include "wimlib/error.h"
+#include "wimlib/guid.h"
 #include "wimlib/inode.h"
 #include "wimlib/reparse.h"
 #include "wimlib/resource.h"
 
-/* Reconstruct the header of a reparse point buffer.  This is necessary because
+/*
+ * Reconstruct the header of a reparse point buffer.  This is necessary because
  * only reparse data is stored in WIM files.  The reparse tag is instead stored
  * in the on-disk WIM dentry, and the reparse data length is equal to the size
- * of the blob in which the reparse data was stored.  */
+ * of the blob in which the reparse data was stored, minus the size of a GUID
+ * (16 bytes) if the reparse tag does not have the "Microsoft" bit set.
+ */
 void
 complete_reparse_point(struct reparse_buffer_disk *rpbuf,
                       const struct wim_inode *inode, u16 blob_size)
 {
        rpbuf->rptag = cpu_to_le32(inode->i_reparse_tag);
+       if (blob_size >= GUID_SIZE && !(inode->i_reparse_tag & 0x80000000))
+               blob_size -= GUID_SIZE;
        rpbuf->rpdatalen = cpu_to_le16(blob_size);
        rpbuf->rpreserved = cpu_to_le16(inode->i_rp_reserved);
 }
@@ -150,7 +156,7 @@ make_link_reparse_point(const struct link_reparse_point *link,
 }
 
 /* UNIX symlink <=> Windows reparse point translation  */
-#ifndef __WIN32__
+#ifndef _WIN32
 
 /* Retrieve the inode's reparse point buffer into @rpbuf and @rpbuflen_ret.
  * This gets the reparse data from @blob if specified, otherwise from the
@@ -246,7 +252,7 @@ wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t bufsize,
        if (parse_link_reparse_point(&rpbuf, rpbuflen, &link))
                return -EINVAL;
 
-       /* Translate the substitute name to the current multibyte encoding.  */
+       /* Translate the substitute name to a multibyte string.  */
        if (utf16le_to_tstr(link.substitute_name, link.substitute_name_nbytes,
                            &target_buffer, &target_len))
                return -errno;
@@ -436,4 +442,4 @@ out_free_target:
        return ret;
 }
 
-#endif /* !__WIN32__ */
+#endif /* !_WIN32 */