btrfs: Fix stack corruption on MakeReference()...

because it needs extra space for storing data, and flexible array member o
doesn't do this.
I thought it was...

Change-Id: If64c06827809a4e021581c6adf8e0f198cf47450
This commit is contained in:
hyche 2017-12-16 03:47:17 +07:00 committed by Adrien Destugues
parent c101b57682
commit 0a4cbf0d1e

View File

@ -440,55 +440,66 @@ Inode::MakeReference(Transaction& transaction, BTree::Path* path,
BTree* tree = fVolume->FSTree(); BTree* tree = fVolume->FSTree();
uint16 nameLength = strlen(name); uint16 nameLength = strlen(name);
uint64 index = parent->FindNextIndex(path); uint64 index = parent->FindNextIndex(path);
void* data[1];
// insert inode_ref // insert inode_ref
btrfs_inode_ref* inodeRef = (btrfs_inode_ref*)malloc(sizeof(btrfs_inode_ref)
+ nameLength);
if (inodeRef == NULL)
return B_NO_MEMORY;
inodeRef->index = index;
inodeRef->SetName(name, nameLength);
btrfs_entry entry; btrfs_entry entry;
btrfs_inode_ref inodeRef;
inodeRef.index = index;
inodeRef.SetName(name, nameLength);
data[0] = (void*)&inodeRef;
entry.key.SetObjectID(fID); entry.key.SetObjectID(fID);
entry.key.SetType(BTRFS_KEY_TYPE_INODE_REF); entry.key.SetType(BTRFS_KEY_TYPE_INODE_REF);
entry.key.SetOffset(parent->ID()); entry.key.SetOffset(parent->ID());
entry.SetSize(inodeRef.Length()); entry.SetSize(inodeRef->Length());
status_t status = tree->InsertEntries(transaction, path, &entry, data, 1); status_t status = tree->InsertEntries(transaction, path, &entry,
(void**)&inodeRef, 1);
free(inodeRef);
if (status != B_OK) if (status != B_OK)
return status; return status;
// insert dir_entry // insert dir_entry
uint32 hash = calculate_crc((uint32)~1, (uint8*)name, nameLength); uint32 hash = calculate_crc((uint32)~1, (uint8*)name, nameLength);
btrfs_dir_entry directoryEntry; btrfs_dir_entry* directoryEntry =
directoryEntry.location.SetObjectID(fID); (btrfs_dir_entry*)malloc(sizeof(btrfs_dir_entry) + nameLength);
directoryEntry.location.SetType(BTRFS_KEY_TYPE_INODE_ITEM); if (directoryEntry == NULL)
directoryEntry.location.SetOffset(0); return B_NO_MEMORY;
directoryEntry.SetTransactionID(transaction.SystemID()); directoryEntry->location.SetObjectID(fID);
directoryEntry->location.SetType(BTRFS_KEY_TYPE_INODE_ITEM);
directoryEntry->location.SetOffset(0);
directoryEntry->SetTransactionID(transaction.SystemID());
// TODO: xattribute, 0 for standard directory // TODO: xattribute, 0 for standard directory
directoryEntry.SetAttributeData(NULL, 0); directoryEntry->SetName(name, nameLength);
directoryEntry.SetName(name, nameLength); directoryEntry->SetAttributeData(NULL, 0);
directoryEntry.type = get_filetype(mode); directoryEntry->type = get_filetype(mode);
data[0] = (void*)&directoryEntry;
entry.key.SetObjectID(parent->ID()); entry.key.SetObjectID(parent->ID());
entry.key.SetType(BTRFS_KEY_TYPE_DIR_ITEM); entry.key.SetType(BTRFS_KEY_TYPE_DIR_ITEM);
entry.key.SetOffset(hash); entry.key.SetOffset(hash);
entry.SetSize(directoryEntry.Length()); entry.SetSize(directoryEntry->Length());
status = tree->InsertEntries(transaction, path, &entry, data, 1); status = tree->InsertEntries(transaction, path, &entry,
if (status != B_OK) (void**)&directoryEntry, 1);
if (status != B_OK) {
free(directoryEntry);
return status; return status;
}
// insert dir_index (has same data with dir_entry) // insert dir_index (has same data with dir_entry)
entry.key.SetType(BTRFS_KEY_TYPE_DIR_INDEX); entry.key.SetType(BTRFS_KEY_TYPE_DIR_INDEX);
entry.key.SetOffset(index); entry.key.SetOffset(index);
status = tree->InsertEntries(transaction, path, &entry, data, 1); status = tree->InsertEntries(transaction, path, &entry,
if (status != B_OK) (void**)&directoryEntry, 1);
if (status != B_OK) {
free(directoryEntry);
return status; return status;
}
free(directoryEntry);
return B_OK; return B_OK;
} }