+2011-11-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Put symlink at the end of the node and fix a potential
+ memory corruption.
+
+ * grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink.
+ Make symlink into an array.
+ (set_rockridge): Set have_symlink and alloc_dirents.
+ (grub_iso9660_read_symlink): Use new layout.
+ (grub_iso9660_iterate_dir): Fix memory corruption.
+ Use new layout.
+ (grub_iso9660_dir): Set have_symlink.
+ (grub_iso9660_open): Likewise.
+
2011-11-10 Vladimir Serbinenko <phcoder@gmail.com>
Remove local keyword.
{
struct grub_iso9660_data *data;
grub_size_t have_dirents, alloc_dirents;
- char *symlink;
+ int have_symlink;
struct grub_iso9660_dir dirents[8];
+ char symlink[0];
};
enum
struct grub_fshelp_node rootnode;
rootnode.data = data;
- rootnode.alloc_dirents = 0;
+ rootnode.alloc_dirents = ARRAY_SIZE (rootnode.dirents);
rootnode.have_dirents = 1;
- rootnode.symlink = 0;
+ rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* The 2nd data byte stored how many bytes are skipped every time
static char *
grub_iso9660_read_symlink (grub_fshelp_node_t node)
{
- return node->symlink ? grub_strdup (node->symlink) : grub_strdup ("");
+ return node->have_symlink
+ ? grub_strdup (node->symlink
+ + (node->have_dirents) * sizeof (node->dirents[0])
+ - sizeof (node->dirents)) : grub_strdup ("");
}
static grub_off_t
/* Setup a new node. */
node->data = dir->data;
- node->symlink = symlink;
+ node->have_symlink = 0;
/* If the filetype was not stored using rockridge, use
whatever is stored in the iso9660 filesystem. */
{
struct grub_fshelp_node *new_node;
node->alloc_dirents *= 2;
- new_node = grub_malloc (sizeof (struct grub_fshelp_node)
- + ((node->alloc_dirents
- - ARRAY_SIZE (node->dirents))
- * sizeof (node->dirents[0])));
+ new_node = grub_realloc (node,
+ sizeof (struct grub_fshelp_node)
+ + ((node->alloc_dirents
+ - ARRAY_SIZE (node->dirents))
+ * sizeof (node->dirents[0])));
if (!new_node)
{
if (filename_alloc)
grub_free (node);
return 0;
}
+ node = new_node;
}
node->dirents[node->have_dirents++] = dirent;
}
+ if (symlink)
+ {
+ if ((node->alloc_dirents - node->have_dirents)
+ * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1)
+ {
+ struct grub_fshelp_node *new_node;
+ new_node = grub_realloc (node,
+ sizeof (struct grub_fshelp_node)
+ + ((node->alloc_dirents
+ - ARRAY_SIZE (node->dirents))
+ * sizeof (node->dirents[0]))
+ + grub_strlen (symlink) + 1);
+ if (!new_node)
+ {
+ if (filename_alloc)
+ grub_free (filename);
+ grub_free (node);
+ return 0;
+ }
+ node = new_node;
+ }
+ node->have_symlink = 1;
+ grub_strcpy (node->symlink
+ + node->have_dirents * sizeof (node->dirents[0])
+ - sizeof (node->dirents), symlink);
+ grub_free (symlink);
+ }
if (hook (filename, type, node))
{
if (filename_alloc)
rootnode.data = data;
rootnode.alloc_dirents = 0;
rootnode.have_dirents = 1;
- rootnode.symlink = 0;
+ rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */
rootnode.data = data;
rootnode.alloc_dirents = 0;
rootnode.have_dirents = 1;
- rootnode.symlink = 0;
+ rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */