Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested.
* grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate types. (grub_hfsplus_btree_recoffset): Likewise. (grub_hfsplus_btree_recptr): Likewise. (grub_hfsplus_find_block): Likewise. (grub_hfsplus_btree_search): Likewise. (grub_hfsplus_read_block): Likewise. (grub_hfsplus_read_file): Likewise. (grub_hfsplus_mount): Likewise. (grub_hfsplus_btree_iterate_node): Likewise. (grub_hfsplus_btree_search): Likewise. (grub_hfsplus_iterate_dir): Likewise. (grub_hfsplus_read): A small code simplification.
This commit is contained in:
parent
c81296b65f
commit
d891955241
2 changed files with 43 additions and 27 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested.
|
||||||
|
|
||||||
|
* grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate
|
||||||
|
types.
|
||||||
|
(grub_hfsplus_btree_recoffset): Likewise.
|
||||||
|
(grub_hfsplus_btree_recptr): Likewise.
|
||||||
|
(grub_hfsplus_find_block): Likewise.
|
||||||
|
(grub_hfsplus_btree_search): Likewise.
|
||||||
|
(grub_hfsplus_read_block): Likewise.
|
||||||
|
(grub_hfsplus_read_file): Likewise.
|
||||||
|
(grub_hfsplus_mount): Likewise.
|
||||||
|
(grub_hfsplus_btree_iterate_node): Likewise.
|
||||||
|
(grub_hfsplus_btree_search): Likewise.
|
||||||
|
(grub_hfsplus_iterate_dir): Likewise.
|
||||||
|
(grub_hfsplus_read): A small code simplification.
|
||||||
|
|
||||||
2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/kern/emu/hostdisk.c
|
* grub-core/kern/emu/hostdisk.c
|
||||||
|
|
|
@ -214,7 +214,7 @@ struct grub_fshelp_node
|
||||||
struct grub_hfsplus_btree
|
struct grub_hfsplus_btree
|
||||||
{
|
{
|
||||||
grub_uint32_t root;
|
grub_uint32_t root;
|
||||||
int nodesize;
|
grub_size_t nodesize;
|
||||||
|
|
||||||
/* Catalog file node. */
|
/* Catalog file node. */
|
||||||
struct grub_fshelp_node file;
|
struct grub_fshelp_node file;
|
||||||
|
@ -236,7 +236,7 @@ struct grub_hfsplus_data
|
||||||
|
|
||||||
/* This is the offset into the physical disk for an embedded HFS+
|
/* This is the offset into the physical disk for an embedded HFS+
|
||||||
filesystem (one inside a plain HFS wrapper). */
|
filesystem (one inside a plain HFS wrapper). */
|
||||||
int embedded_offset;
|
grub_disk_addr_t embedded_offset;
|
||||||
int case_sensitive;
|
int case_sensitive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ static grub_dl_t my_mod;
|
||||||
|
|
||||||
/* Return the offset of the record with the index INDEX, in the node
|
/* Return the offset of the record with the index INDEX, in the node
|
||||||
NODE which is part of the B+ tree BTREE. */
|
NODE which is part of the B+ tree BTREE. */
|
||||||
static inline unsigned int
|
static inline grub_off_t
|
||||||
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
|
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
|
||||||
struct grub_hfsplus_btnode *node, int index)
|
struct grub_hfsplus_btnode *node, int index)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +263,7 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
|
||||||
struct grub_hfsplus_btnode *node, int index)
|
struct grub_hfsplus_btnode *node, int index)
|
||||||
{
|
{
|
||||||
char *cnode = (char *) node;
|
char *cnode = (char *) node;
|
||||||
unsigned int offset;
|
grub_off_t offset;
|
||||||
offset = grub_hfsplus_btree_recoffset (btree, node, index);
|
offset = grub_hfsplus_btree_recoffset (btree, node, index);
|
||||||
return (struct grub_hfsplus_key *) &cnode[offset];
|
return (struct grub_hfsplus_key *) &cnode[offset];
|
||||||
}
|
}
|
||||||
|
@ -272,12 +272,12 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
|
||||||
/* Find the extent that points to FILEBLOCK. If it is not in one of
|
/* Find the extent that points to FILEBLOCK. If it is not in one of
|
||||||
the 8 extents described by EXTENT, return -1. In that case set
|
the 8 extents described by EXTENT, return -1. In that case set
|
||||||
FILEBLOCK to the next block. */
|
FILEBLOCK to the next block. */
|
||||||
static int
|
static grub_disk_addr_t
|
||||||
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
|
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
|
||||||
int *fileblock)
|
grub_disk_addr_t *fileblock)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
grub_size_t blksleft = *fileblock;
|
grub_disk_addr_t blksleft = *fileblock;
|
||||||
|
|
||||||
/* First lookup the file in the given extents. */
|
/* First lookup the file in the given extents. */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
|
@ -288,7 +288,7 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
|
||||||
}
|
}
|
||||||
|
|
||||||
*fileblock = blksleft;
|
*fileblock = blksleft;
|
||||||
return -1;
|
return 0xffffffffffffffffULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -296,7 +296,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
|
||||||
struct grub_hfsplus_key_internal *key,
|
struct grub_hfsplus_key_internal *key,
|
||||||
int (*compare_keys) (struct grub_hfsplus_key *keya,
|
int (*compare_keys) (struct grub_hfsplus_key *keya,
|
||||||
struct grub_hfsplus_key_internal *keyb),
|
struct grub_hfsplus_key_internal *keyb),
|
||||||
struct grub_hfsplus_btnode **matchnode, int *keyoffset);
|
struct grub_hfsplus_btnode **matchnode,
|
||||||
|
grub_off_t *keyoffset);
|
||||||
|
|
||||||
static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
|
static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
|
||||||
struct grub_hfsplus_key_internal *keyb);
|
struct grub_hfsplus_key_internal *keyb);
|
||||||
|
@ -307,15 +308,15 @@ static grub_disk_addr_t
|
||||||
grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
{
|
{
|
||||||
struct grub_hfsplus_btnode *nnode = 0;
|
struct grub_hfsplus_btnode *nnode = 0;
|
||||||
int blksleft = fileblock;
|
grub_disk_addr_t blksleft = fileblock;
|
||||||
struct grub_hfsplus_extent *extents = &node->extents[0];
|
struct grub_hfsplus_extent *extents = &node->extents[0];
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
struct grub_hfsplus_extkey *key;
|
struct grub_hfsplus_extkey *key;
|
||||||
struct grub_hfsplus_extkey_internal extoverflow;
|
struct grub_hfsplus_extkey_internal extoverflow;
|
||||||
int blk;
|
grub_disk_addr_t blk;
|
||||||
int ptr;
|
grub_off_t ptr;
|
||||||
|
|
||||||
/* Try to find this block in the current set of extents. */
|
/* Try to find this block in the current set of extents. */
|
||||||
blk = grub_hfsplus_find_block (extents, &blksleft);
|
blk = grub_hfsplus_find_block (extents, &blksleft);
|
||||||
|
@ -325,7 +326,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
grub_free (nnode);
|
grub_free (nnode);
|
||||||
nnode = 0;
|
nnode = 0;
|
||||||
|
|
||||||
if (blk != -1)
|
if (blk != 0xffffffffffffffffULL)
|
||||||
return (blk
|
return (blk
|
||||||
+ (node->data->embedded_offset >> (node->data->log2blksize
|
+ (node->data->embedded_offset >> (node->data->log2blksize
|
||||||
- GRUB_DISK_SECTOR_BITS)));
|
- GRUB_DISK_SECTOR_BITS)));
|
||||||
|
@ -376,7 +377,7 @@ static grub_ssize_t
|
||||||
grub_hfsplus_read_file (grub_fshelp_node_t node,
|
grub_hfsplus_read_file (grub_fshelp_node_t node,
|
||||||
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
||||||
unsigned offset, unsigned length),
|
unsigned offset, unsigned length),
|
||||||
int pos, grub_size_t len, char *buf)
|
grub_off_t pos, grub_size_t len, char *buf)
|
||||||
{
|
{
|
||||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
||||||
pos, len, buf, grub_hfsplus_read_block,
|
pos, len, buf, grub_hfsplus_read_block,
|
||||||
|
@ -411,9 +412,9 @@ grub_hfsplus_mount (grub_disk_t disk)
|
||||||
data->embedded_offset = 0;
|
data->embedded_offset = 0;
|
||||||
if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
|
if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
|
||||||
{
|
{
|
||||||
int extent_start;
|
grub_disk_addr_t extent_start;
|
||||||
int ablk_size;
|
grub_disk_addr_t ablk_size;
|
||||||
int ablk_start;
|
grub_disk_addr_t ablk_start;
|
||||||
|
|
||||||
/* See if there's an embedded HFS+ filesystem. */
|
/* See if there's an embedded HFS+ filesystem. */
|
||||||
if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
|
if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
|
||||||
|
@ -601,10 +602,10 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
|
||||||
static int
|
static int
|
||||||
grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
|
grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
|
||||||
struct grub_hfsplus_btnode *first_node,
|
struct grub_hfsplus_btnode *first_node,
|
||||||
int first_rec,
|
grub_disk_addr_t first_rec,
|
||||||
int (*hook) (void *record))
|
int (*hook) (void *record))
|
||||||
{
|
{
|
||||||
int rec;
|
grub_disk_addr_t rec;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -642,12 +643,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
|
||||||
struct grub_hfsplus_key_internal *key,
|
struct grub_hfsplus_key_internal *key,
|
||||||
int (*compare_keys) (struct grub_hfsplus_key *keya,
|
int (*compare_keys) (struct grub_hfsplus_key *keya,
|
||||||
struct grub_hfsplus_key_internal *keyb),
|
struct grub_hfsplus_key_internal *keyb),
|
||||||
struct grub_hfsplus_btnode **matchnode, int *keyoffset)
|
struct grub_hfsplus_btnode **matchnode,
|
||||||
|
grub_off_t *keyoffset)
|
||||||
{
|
{
|
||||||
grub_uint64_t currnode;
|
grub_uint64_t currnode;
|
||||||
char *node;
|
char *node;
|
||||||
struct grub_hfsplus_btnode *nodedesc;
|
struct grub_hfsplus_btnode *nodedesc;
|
||||||
int rec;
|
grub_disk_addr_t rec;
|
||||||
|
|
||||||
node = grub_malloc (btree->nodesize);
|
node = grub_malloc (btree->nodesize);
|
||||||
if (! node)
|
if (! node)
|
||||||
|
@ -825,7 +827,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
|
||||||
struct grub_hfsplus_key_internal intern;
|
struct grub_hfsplus_key_internal intern;
|
||||||
struct grub_hfsplus_btnode *node;
|
struct grub_hfsplus_btnode *node;
|
||||||
int ptr;
|
grub_disk_addr_t ptr;
|
||||||
|
|
||||||
/* Create a key that points to the first entry in the directory. */
|
/* Create a key that points to the first entry in the directory. */
|
||||||
intern.catkey.parent = dir->fileid;
|
intern.catkey.parent = dir->fileid;
|
||||||
|
@ -894,7 +896,6 @@ grub_hfsplus_close (grub_file_t file)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read LEN bytes data from FILE into BUF. */
|
/* Read LEN bytes data from FILE into BUF. */
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
|
grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
|
@ -902,13 +903,10 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
struct grub_hfsplus_data *data =
|
struct grub_hfsplus_data *data =
|
||||||
(struct grub_hfsplus_data *) file->data;
|
(struct grub_hfsplus_data *) file->data;
|
||||||
|
|
||||||
int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook,
|
return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
|
||||||
file->offset, len, buf);
|
file->offset, len, buf);
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_hfsplus_dir (grub_device_t device, const char *path,
|
grub_hfsplus_dir (grub_device_t device, const char *path,
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
|
|
Loading…
Reference in a new issue