+ u32 owner_offset, group_offset, dacl_offset, sacl_offset;
+ bool owner_valid, group_valid;
+ size_t size = *size_p;
+ const wimlib_SECURITY_DESCRIPTOR_RELATIVE *desc = _desc;
+ wimlib_SECURITY_DESCRIPTOR_RELATIVE *desc_new;
+ const wimlib_SID *owner, *group, *sid;
+
+ /* Don't attempt to fix clearly invalid security descriptors. */
+ if (size < sizeof(wimlib_SECURITY_DESCRIPTOR_RELATIVE))
+ return NULL;
+
+ if (le16_to_cpu(desc->control) & wimlib_SE_DACL_PRESENT)
+ dacl_offset = le32_to_cpu(desc->dacl_offset);
+ else
+ dacl_offset = 0;
+
+ if (le16_to_cpu(desc->control) & wimlib_SE_SACL_PRESENT)
+ sacl_offset = le32_to_cpu(desc->sacl_offset);
+ else
+ sacl_offset = 0;
+
+ /* Check if the security descriptor will be affected by one of the bugs.
+ * If not, do nothing and return. */
+ if (!((sacl_offset != 0 && sacl_offset == size - sizeof(wimlib_ACL)) ||
+ (dacl_offset != 0 && dacl_offset == size - sizeof(wimlib_ACL))))
+ return NULL;
+
+ owner_offset = le32_to_cpu(desc->owner_offset);
+ group_offset = le32_to_cpu(desc->group_offset);
+ owner = (const wimlib_SID*)((const u8*)desc + owner_offset);
+ group = (const wimlib_SID*)((const u8*)desc + group_offset);
+
+ /* We'll try to move the owner or group SID to the end of the security
+ * descriptor to avoid the bug. This is only possible if at least one
+ * is valid. */
+ owner_valid = (owner_offset != 0) &&
+ (owner_offset % 4 == 0) &&
+ (owner_offset <= size - sizeof(SID)) &&
+ (owner_offset + sid_size(owner) <= size) &&
+ (owner_offset >= sizeof(wimlib_SECURITY_DESCRIPTOR_RELATIVE));
+ group_valid = (group_offset != 0) &&
+ (group_offset % 4 == 0) &&
+ (group_offset <= size - sizeof(SID)) &&
+ (group_offset + sid_size(group) <= size) &&
+ (group_offset >= sizeof(wimlib_SECURITY_DESCRIPTOR_RELATIVE));
+ if (owner_valid) {
+ sid = owner;
+ } else if (group_valid) {
+ sid = group;
+ } else {
+ return NULL;
+ }