merge patched into master

This commit is contained in:
Julian Andres Klode 2022-06-10 10:30:47 +02:00
commit 574e41e0da
19 changed files with 503 additions and 169 deletions

2
debian/.git-dpm vendored
View File

@ -1,6 +1,6 @@
# see git-dpm(1) from git-dpm package
dbcbb3e5b9fac665b92d630eb24de7bd8c43652e
dbcbb3e5b9fac665b92d630eb24de7bd8c43652e
589500ad3777d1335c8e5cb139f7c0c6089112a8
21f954425ffe2a934b6b26c0c948d340c91a16bb
21f954425ffe2a934b6b26c0c948d340c91a16bb
grub2_2.06.orig.tar.xz

View File

@ -27,10 +27,20 @@
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void);
static grub_err_t (*grub_loader_boot_func) (void *);
static grub_err_t (*grub_loader_unload_func) (void *);
static void *grub_loader_context;
static int grub_loader_flags;
struct grub_simple_loader_hooks
{
grub_err_t (*boot) (void);
grub_err_t (*unload) (void);
};
/* Don't heap allocate this to avoid making grub_loader_set fallible. */
static struct grub_simple_loader_hooks simple_loader_hooks;
struct grub_preboot
{
grub_err_t (*preboot_func) (int);
@ -44,6 +54,29 @@ static int grub_loader_loaded;
static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0;
static grub_err_t
grub_simple_boot_hook (void *context)
{
struct grub_simple_loader_hooks *hooks;
hooks = (struct grub_simple_loader_hooks *) context;
return hooks->boot ();
}
static grub_err_t
grub_simple_unload_hook (void *context)
{
struct grub_simple_loader_hooks *hooks;
grub_err_t ret;
hooks = (struct grub_simple_loader_hooks *) context;
ret = hooks->unload ();
grub_memset (hooks, 0, sizeof (*hooks));
return ret;
}
int
grub_loader_is_loaded (void)
{
@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
}
void
grub_loader_set (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int flags)
grub_loader_set_ex (grub_err_t (*boot) (void *),
grub_err_t (*unload) (void *),
void *context,
int flags)
{
if (grub_loader_loaded && grub_loader_unload_func)
grub_loader_unload_func ();
grub_loader_unload_func (grub_loader_context);
grub_loader_boot_func = boot;
grub_loader_unload_func = unload;
grub_loader_context = context;
grub_loader_flags = flags;
grub_loader_loaded = 1;
}
void
grub_loader_set (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int flags)
{
grub_loader_set_ex (grub_simple_boot_hook,
grub_simple_unload_hook,
&simple_loader_hooks,
flags);
simple_loader_hooks.boot = boot;
simple_loader_hooks.unload = unload;
}
void
grub_loader_unset(void)
{
if (grub_loader_loaded && grub_loader_unload_func)
grub_loader_unload_func ();
grub_loader_unload_func (grub_loader_context);
grub_loader_boot_func = 0;
grub_loader_unload_func = 0;
grub_loader_context = 0;
grub_loader_loaded = 0;
}
@ -158,7 +208,7 @@ grub_loader_boot (void)
return err;
}
}
err = (grub_loader_boot_func) ();
err = (grub_loader_boot_func) (grub_loader_context);
for (cur = preboots_tail; cur; cur = cur->prev)
if (! err)

View File

@ -912,6 +912,23 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
return grub_error (GRUB_ERR_BAD_FS,
"couldn't find the chunk descriptor");
if (!chsize)
{
grub_dprintf ("btrfs", "zero-size chunk\n");
return grub_error (GRUB_ERR_BAD_FS,
"got an invalid zero-size chunk");
}
/*
* The space being allocated for a chunk should at least be able to
* contain one chunk item.
*/
if (chsize < sizeof (struct grub_btrfs_chunk_item))
{
grub_dprintf ("btrfs", "chunk-size too small\n");
return grub_error (GRUB_ERR_BAD_FS,
"got an invalid chunk size");
}
chunk = grub_malloc (chsize);
if (!chunk)
return grub_errno;
@ -970,6 +987,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
nstripes,
NULL);
/* For single, there should be exactly 1 stripe. */
if (grub_le_to_cpu16 (chunk->nstripes) != 1)
{
grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n",
grub_le_to_cpu16 (chunk->nstripes));
return grub_error (GRUB_ERR_BAD_FS,
"invalid RAID_SINGLE: nstripes != 1 (%u)",
grub_le_to_cpu16 (chunk->nstripes));
}
if (stripe_length == 0)
stripe_length = 512;
stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
@ -989,6 +1016,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
stripen = 0;
stripe_offset = off;
csize = grub_le_to_cpu64 (chunk->size) - off;
/*
* Redundancy, and substripes only apply to RAID10, and there
* should be exactly 2 sub-stripes.
*/
if (grub_le_to_cpu16 (chunk->nstripes) != redundancy)
{
grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n",
redundancy, grub_le_to_cpu16 (chunk->nstripes));
return grub_error (GRUB_ERR_BAD_FS,
"invalid RAID1: nstripes != %u (%u)",
redundancy, grub_le_to_cpu16 (chunk->nstripes));
}
break;
}
case GRUB_BTRFS_CHUNK_TYPE_RAID0:
@ -1025,6 +1065,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
stripe_offset = low + chunk_stripe_length
* high;
csize = chunk_stripe_length - low;
/*
* Substripes only apply to RAID10, and there
* should be exactly 2 sub-stripes.
*/
if (grub_le_to_cpu16 (chunk->nsubstripes) != 2)
{
grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)",
grub_le_to_cpu16 (chunk->nsubstripes));
return grub_error (GRUB_ERR_BAD_FS,
"invalid RAID10: nsubstripes != 2 (%u)",
grub_le_to_cpu16 (chunk->nsubstripes));
}
break;
}
case GRUB_BTRFS_CHUNK_TYPE_RAID5:
@ -1122,8 +1176,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
if (csize > (grub_uint64_t) size)
csize = size;
/*
* The space for a chunk stripe is limited to the space provide in the super-block's
* bootstrap mapping with an initial btrfs key at the start of each chunk.
*/
grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
(sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe));
for (j = 0; j < 2; j++)
{
grub_size_t est_chunk_alloc = 0;
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
"+0x%" PRIxGRUB_UINT64_T
" (%d stripes (%d substripes) of %"
@ -1136,6 +1199,22 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n",
addr);
if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe),
grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) ||
grub_add (est_chunk_alloc,
sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) ||
est_chunk_alloc > chunk->size)
{
err = GRUB_ERR_BAD_FS;
break;
}
if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
{
err = GRUB_ERR_BAD_FS;
break;
}
if (is_raid56)
{
err = btrfs_read_from_chunk (data, chunk, stripen,
@ -1961,6 +2040,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
int r = 0;
grub_uint64_t tree;
grub_uint8_t type;
grub_size_t est_size = 0;
if (!data)
return grub_errno;
@ -2019,6 +2099,18 @@ grub_btrfs_dir (grub_device_t device, const char *path,
break;
}
if (direl == NULL ||
grub_add (grub_le_to_cpu16 (direl->n),
grub_le_to_cpu16 (direl->m), &est_size) ||
grub_add (est_size, sizeof (*direl), &est_size) ||
grub_sub (est_size, sizeof (direl->name), &est_size) ||
est_size > allocated)
{
grub_errno = GRUB_ERR_OUT_OF_RANGE;
r = -grub_errno;
goto out;
}
for (cdirel = direl;
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
< (grub_ssize_t) elemsize;
@ -2029,6 +2121,19 @@ grub_btrfs_dir (grub_device_t device, const char *path,
char c;
struct grub_btrfs_inode inode;
struct grub_dirhook_info info;
if (cdirel == NULL ||
grub_add (grub_le_to_cpu16 (cdirel->n),
grub_le_to_cpu16 (cdirel->m), &est_size) ||
grub_add (est_size, sizeof (*cdirel), &est_size) ||
grub_sub (est_size, sizeof (cdirel->name), &est_size) ||
est_size > allocated)
{
grub_errno = GRUB_ERR_OUT_OF_RANGE;
r = -grub_errno;
goto out;
}
err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
tree);
grub_memset (&info, 0, sizeof (info));

View File

@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */
#define MAX_VOLUME_NAME 512
#define MAX_NAT_BITMAP_SIZE 3900
enum FILE_TYPE
{
@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint
grub_uint32_t checksum_offset;
grub_uint64_t elapsed_time;
grub_uint8_t alloc_type[MAX_ACTIVE_LOGS];
grub_uint8_t sit_nat_version_bitmap[3900];
grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE];
grub_uint32_t checksum;
} GRUB_PACKED;
@ -302,6 +303,7 @@ struct grub_f2fs_data
struct grub_f2fs_nat_journal nat_j;
char *nat_bitmap;
grub_uint32_t nat_bitmap_size;
grub_disk_t disk;
struct grub_f2fs_node *inode;
@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
}
static void *
nat_bitmap_ptr (struct grub_f2fs_data *data)
nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size)
{
struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
grub_uint32_t offset;
*nat_bitmap_size = MAX_NAT_BITMAP_SIZE;
if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
return ckpt->sit_nat_version_bitmap;
offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
if (offset >= MAX_NAT_BITMAP_SIZE)
return NULL;
*nat_bitmap_size = *nat_bitmap_size - offset;
return ckpt->sit_nat_version_bitmap + offset;
}
@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
}
static int
grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len)
{
int mask;
grub_uint32_t shifted_nr = (nr >> 3);
p += (nr >> 3);
if (shifted_nr >= len)
return -1;
p += shifted_nr;
mask = 1 << (7 - (nr & 0x07));
return mask & *p;
@ -632,23 +643,27 @@ get_nat_journal (struct grub_f2fs_data *data)
return err;
}
static grub_uint32_t
get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
static grub_err_t
get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid,
grub_uint32_t *blkaddr)
{
grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
grub_uint32_t blkaddr = 0;
grub_uint16_t i;
if (n >= NAT_JOURNAL_ENTRIES)
return grub_error (GRUB_ERR_BAD_FS,
"invalid number of nat journal entries");
for (i = 0; i < n; i++)
{
if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
{
blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
*blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
break;
}
}
return blkaddr;
return GRUB_ERR_NONE;
}
static grub_uint32_t
@ -656,10 +671,14 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
{
struct grub_f2fs_nat_block *nat_block;
grub_uint32_t seg_off, block_off, entry_off, block_addr;
grub_uint32_t blkaddr;
grub_uint32_t blkaddr = 0;
grub_err_t err;
int result_bit;
err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
if (err != GRUB_ERR_NONE)
return 0;
blkaddr = get_blkaddr_from_nat_journal (data, nid);
if (blkaddr)
return blkaddr;
@ -675,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
((seg_off * data->blocks_per_seg) << 1) +
(block_off & (data->blocks_per_seg - 1));
if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap,
data->nat_bitmap_size);
if (result_bit > 0)
block_addr += data->blocks_per_seg;
else if (result_bit == -1)
{
grub_free (nat_block);
return 0;
}
err = grub_f2fs_block_read (data, block_addr, nat_block);
if (err)
@ -826,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk)
if (err)
goto fail;
data->nat_bitmap = nat_bitmap_ptr (data);
data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size);
if (data->nat_bitmap == NULL)
goto fail;
err = get_nat_journal (data);
if (err)
@ -975,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
ftype = ctx->dentry[i].file_type;
name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
if (name_len >= F2FS_NAME_LEN)
return 0;
filename = grub_malloc (name_len + 1);
if (!filename)
return 0;

View File

@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
void **context __attribute__ ((unused)),
enum grub_verify_flags *flags)
{
*flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
*flags = GRUB_VERIFY_FLAGS_NONE;
switch (type & GRUB_FILE_TYPE_MASK)
{
/* Files we check. */
case GRUB_FILE_TYPE_LINUX_KERNEL:
case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
case GRUB_FILE_TYPE_BSD_KERNEL:
@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
case GRUB_FILE_TYPE_PLAN9_KERNEL:
case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
*flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
/* Fall through. */
default:
return GRUB_ERR_NONE;
/* Files that do not affect secureboot state. */
case GRUB_FILE_TYPE_NONE:
case GRUB_FILE_TYPE_LOOPBACK:
case GRUB_FILE_TYPE_LINUX_INITRD:
case GRUB_FILE_TYPE_OPENBSD_RAMDISK:
case GRUB_FILE_TYPE_XNU_RAMDISK:
case GRUB_FILE_TYPE_SIGNATURE:
case GRUB_FILE_TYPE_PUBLIC_KEY:
case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST:
case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
case GRUB_FILE_TYPE_TESTLOAD:
case GRUB_FILE_TYPE_GET_SIZE:
case GRUB_FILE_TYPE_FONT:
case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
case GRUB_FILE_TYPE_CAT:
case GRUB_FILE_TYPE_HEXCAT:
case GRUB_FILE_TYPE_CMP:
case GRUB_FILE_TYPE_HASHLIST:
case GRUB_FILE_TYPE_TO_HASH:
case GRUB_FILE_TYPE_KEYBOARD_LAYOUT:
case GRUB_FILE_TYPE_PIXMAP:
case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
case GRUB_FILE_TYPE_CONFIG:
case GRUB_FILE_TYPE_THEME:
case GRUB_FILE_TYPE_GETTEXT_CATALOG:
case GRUB_FILE_TYPE_FS_SEARCH:
case GRUB_FILE_TYPE_LOADENV:
case GRUB_FILE_TYPE_SAVEENV:
case GRUB_FILE_TYPE_VERIFY_SIGNATURE:
*flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
return GRUB_ERR_NONE;
/* Other files. */
default:
return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy"));
}
}

View File

@ -79,6 +79,7 @@ grub_file_open (const char *name, enum grub_file_type type)
device = grub_device_open (device_name);
grub_free (device_name);
device_name = NULL;
if (! device)
goto fail;
@ -131,6 +132,7 @@ grub_file_open (const char *name, enum grub_file_type type)
return file;
fail:
grub_free (device_name);
if (device)
grub_device_close (device);

View File

@ -44,33 +44,28 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static grub_efi_physical_address_t address;
static grub_efi_uintn_t pages;
static grub_efi_device_path_t *file_path;
static grub_efi_handle_t image_handle;
static grub_efi_char16_t *cmdline;
static grub_err_t
grub_chainloader_unload (void)
grub_chainloader_unload (void *context)
{
grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
grub_efi_loaded_image_t *loaded_image;
grub_efi_boot_services_t *b;
loaded_image = grub_efi_get_loaded_image (image_handle);
if (loaded_image != NULL)
grub_free (loaded_image->load_options);
b = grub_efi_system_table->boot_services;
efi_call_1 (b->unload_image, image_handle);
efi_call_2 (b->free_pages, address, pages);
grub_free (file_path);
grub_free (cmdline);
cmdline = 0;
file_path = 0;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_chainloader_boot (void)
grub_chainloader_boot (void *context)
{
grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
grub_efi_boot_services_t *b;
grub_efi_status_t status;
grub_efi_uintn_t exit_data_size;
@ -140,7 +135,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
char *dir_start;
char *dir_end;
grub_size_t size;
grub_efi_device_path_t *d;
grub_efi_device_path_t *d, *file_path;
dir_start = grub_strchr (filename, ')');
if (! dir_start)
@ -222,11 +217,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_efi_status_t status;
grub_efi_boot_services_t *b;
grub_device_t dev = 0;
grub_efi_device_path_t *dp = 0;
grub_efi_device_path_t *dp = NULL, *file_path = NULL;
grub_efi_loaded_image_t *loaded_image;
char *filename;
void *boot_image = 0;
grub_efi_handle_t dev_handle = 0;
grub_efi_physical_address_t address = 0;
grub_efi_uintn_t pages = 0;
grub_efi_char16_t *cmdline = NULL;
grub_efi_handle_t image_handle = NULL;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@ -234,11 +233,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
/* Initialize some global variables. */
address = 0;
image_handle = 0;
file_path = 0;
b = grub_efi_system_table->boot_services;
file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE);
@ -408,7 +402,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_file_close (file);
grub_device_close (dev);
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
/* We're finished with the source image buffer and file path now. */
efi_call_2 (b->free_pages, address, pages);
grub_free (file_path);
grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0);
return 0;
fail:
@ -419,11 +417,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
if (file)
grub_file_close (file);
grub_free (cmdline);
grub_free (file_path);
if (address)
efi_call_2 (b->free_pages, address, pages);
if (image_handle != NULL)
efi_call_1 (b->unload_image, image_handle);
grub_dl_unref (my_mod);
return grub_errno;

View File

@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
int *length, char *set)
{
const char *readable_ptr = check_with;
int readable_len;
const grub_uint8_t *ptr;
char *optr = set;
int bytes_processed = 0;
if (length)
*length = 0;
if (readable_ptr != NULL)
readable_len = grub_strlen (readable_ptr);
else
readable_len = 0;
for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
{
/* End marker. */
@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
continue;
}
if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0))
return 0;
if (grub_memchr (ptr + 1, 0, *ptr)
|| grub_memchr (ptr + 1, '.', *ptr))
return 0;
if (readable_ptr)
readable_ptr += *ptr;
{
readable_ptr += *ptr;
readable_len -= *ptr;
}
if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
return 0;
bytes_processed += *ptr + 1;
@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
if (optr)
*optr++ = '.';
if (readable_ptr && *readable_ptr)
readable_ptr++;
{
readable_ptr++;
readable_len--;
}
ptr += *ptr + 1;
}
return 0;
@ -667,9 +680,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
grub_net_addr_to_str (&addresses[i], buf);
grub_printf ("%s\n", buf);
}
grub_free (addresses);
if (naddresses)
return GRUB_ERR_NONE;
{
grub_free (addresses);
return GRUB_ERR_NONE;
}
return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
}

View File

@ -68,7 +68,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
char *end = ptr + len;
while (end > ptr && *(end - 1) == '\r')
end--;
/* LF without CR. */
if (end == ptr + len)
{
data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR"));
return GRUB_ERR_NONE;
}
*end = 0;
/* Trailing CRLF. */
if (data->in_chunk_len == 1)
{
@ -190,9 +198,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
int have_line = 1;
char *t;
ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
if (ptr)
ptr++;
else
if (ptr == NULL)
{
have_line = 0;
ptr = (char *) nb->tail;
@ -422,7 +428,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
return err;
}
for (i = 0; !data->headers_recv && i < 100; i++)
for (i = 0; data->sock && !data->headers_recv && i < 100; i++)
{
grub_net_tcp_retransmit ();
grub_net_poll_cards (300, &data->headers_recv);
@ -430,7 +436,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
if (!data->headers_recv)
{
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
if (data->sock)
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
if (data->err)
{
char *str = data->errmsg;

View File

@ -25,6 +25,7 @@
#include <grub/net/netbuff.h>
#include <grub/mm.h>
#include <grub/priority_queue.h>
#include <grub/safemath.h>
#include <grub/time.h>
struct iphdr {
@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
{
rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK)
+ (nb->tail - nb->data));
rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t));
if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t),
&rsm->total_len))
{
grub_dprintf ("net", "IP reassembly size underflow\n");
return GRUB_ERR_NONE;
}
rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len);
if (!rsm->asm_netbuff)
{

View File

@ -1548,7 +1548,8 @@ grub_net_fs_close (grub_file_t file)
grub_netbuff_free (file->device->net->packs.first->nb);
grub_net_remove_packet (file->device->net->packs.first);
}
file->device->net->protocol->close (file);
if (!file->device->net->broken)
file->device->net->protocol->close (file);
grub_free (file->device->net->name);
return GRUB_ERR_NONE;
}
@ -1770,7 +1771,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
file->device->net->stall = 0;
err = file->device->net->protocol->open (file, file->device->net->name);
if (err)
return err;
{
file->device->net->broken = 1;
return err;
}
grub_net_fs_read_real (file, NULL, offset);
return grub_errno;
}
@ -1779,6 +1783,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
static grub_ssize_t
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
{
if (file->device->net->broken)
return -1;
if (file->offset != file->device->net->offset)
{
grub_err_t err;

View File

@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len)
COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0);
/*
* The largest size of a TCP packet is 64 KiB, and everything else
* should be a lot smaller - most MTUs are 1500 or less. Cap data
* size at 64 KiB + a buffer.
*/
if (len > 0xffffUL + 0x1000UL)
{
grub_error (GRUB_ERR_BUG,
"attempted to allocate a packet that is too big");
return NULL;
}
if (len < NETBUFFMINLEN)
len = NETBUFFMINLEN;
len = ALIGN_UP (len, NETBUFF_ALIGN);
#ifdef GRUB_MACHINE_EMU
data = grub_malloc (len + sizeof (*nb));
#else

View File

@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
return GRUB_ERR_NONE;
case TFTP_ERROR:
data->have_oack = 1;
grub_netbuff_free (nb);
grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
grub_error_save (&data->save_err);
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
default:
grub_netbuff_free (nb);
@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
{
grub_net_udp_close (data->sock);
grub_free (data);
file->data = NULL;
return grub_errno;
}

View File

@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c)
{
if (grub_unicode_get_comb_type (c->base))
return 0;
if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec))
return 1;
if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
return 2;
else

View File

@ -23,6 +23,7 @@
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/bufio.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -109,9 +110,17 @@ static grub_uint8_t
grub_jpeg_get_byte (struct grub_jpeg_data *data)
{
grub_uint8_t r;
grub_ssize_t bytes_read;
r = 0;
grub_file_read (data->file, &r, 1);
bytes_read = grub_file_read (data->file, &r, 1);
if (bytes_read != 1)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: unexpected end of data");
return 0;
}
return r;
}
@ -120,9 +129,17 @@ static grub_uint16_t
grub_jpeg_get_word (struct grub_jpeg_data *data)
{
grub_uint16_t r;
grub_ssize_t bytes_read;
r = 0;
grub_file_read (data->file, &r, sizeof (grub_uint16_t));
bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t));
if (bytes_read != sizeof (grub_uint16_t))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: unexpected end of data");
return 0;
}
return grub_be_to_cpu16 (r);
}
@ -135,6 +152,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
if (data->bit_mask == 0)
{
data->bit_save = grub_jpeg_get_byte (data);
if (grub_errno != GRUB_ERR_NONE) {
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: file read error");
return 0;
}
if (data->bit_save == JPEG_ESC_CHAR)
{
if (grub_jpeg_get_byte (data) != 0)
@ -143,6 +165,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
"jpeg: invalid 0xFF in data stream");
return 0;
}
if (grub_errno != GRUB_ERR_NONE)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error");
return 0;
}
}
data->bit_mask = 0x80;
}
@ -161,7 +188,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
return 0;
msb = value = grub_jpeg_get_bit (data);
for (i = 1; i < num; i++)
for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++)
value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
if (!msb)
value += 1 - (1 << num);
@ -202,6 +229,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
while (data->file->offset + sizeof (count) + 1 <= next_marker)
{
id = grub_jpeg_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
ac = (id >> 4) & 1;
id &= 0xF;
if (id > 1)
@ -217,6 +246,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
n += count[i];
id += ac * 2;
if (data->huff_value[id] != NULL)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: attempt to reallocate huffman table");
data->huff_value[id] = grub_malloc (n);
if (grub_errno)
return grub_errno;
@ -252,6 +284,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
next_marker = data->file->offset;
next_marker += grub_jpeg_get_word (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (next_marker > data->file->size)
{
@ -263,6 +297,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
<= next_marker)
{
id = grub_jpeg_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (id >= 0x10) /* Upper 4-bit is precision. */
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: only 8-bit precision is supported");
@ -294,6 +330,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
next_marker = data->file->offset;
next_marker += grub_jpeg_get_word (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (grub_jpeg_get_byte (data) != 8)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: only 8-bit precision is supported");
@ -319,6 +358,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
ss = grub_jpeg_get_byte (data); /* Sampling factor. */
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (!id)
{
grub_uint8_t vs, hs;
@ -498,7 +539,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du)
}
}
static void
static grub_err_t
grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
{
int h1, h2, qt;
@ -513,6 +554,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
data->dc_value[id] +=
grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
pos = 1;
while (pos < ARRAY_SIZE (data->quan_table[qt]))
@ -527,11 +571,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
num >>= 4;
pos += num;
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: invalid position in zigzag order!?");
return;
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: invalid position in zigzag order!?");
}
du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
@ -539,6 +585,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
}
grub_jpeg_idct_transform (du);
return GRUB_ERR_NONE;
}
static void
@ -597,7 +644,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
data_offset += grub_jpeg_get_word (data);
cc = grub_jpeg_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (cc != 3 && cc != 1)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: component count must be 1 or 3");
@ -610,7 +658,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
id = grub_jpeg_get_byte (data) - 1;
if ((id < 0) || (id >= 3))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
ht = grub_jpeg_get_byte (data);
data->comp_index[id][1] = (ht >> 4);
data->comp_index[id][2] = (ht & 0xF) + 2;
@ -618,14 +667,20 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) ||
(data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index");
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
}
grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */
grub_jpeg_get_word (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (data->file->offset != data_offset)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
if (*data->bitmap)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks");
if (grub_video_bitmap_create (data->bitmap, data->image_width,
data->image_height,
GRUB_VIDEO_BLIT_FORMAT_RGB_888))
@ -639,7 +694,9 @@ static grub_err_t
grub_jpeg_decode_data (struct grub_jpeg_data *data)
{
unsigned c1, vb, hb, nr1, nc1;
unsigned stride_a, stride_b, stride;
int rst = data->dri;
grub_err_t err = GRUB_ERR_NONE;
vb = 8 << data->log_vs;
hb = 8 << data->log_hs;
@ -647,11 +704,17 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs);
if (data->bitmap_ptr == NULL)
return grub_error(GRUB_ERR_BAD_FILE_TYPE,
"jpeg: attempted to decode data before start of stream");
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: attempted to decode data before start of stream");
if (grub_mul(vb, data->image_width, &stride_a) ||
grub_mul(hb, nc1, &stride_b) ||
grub_sub(stride_a, stride_b, &stride))
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: cannot decode image with these dimensions");
for (; data->r1 < nr1 && (!data->dri || rst);
data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
data->r1++, data->bitmap_ptr += stride * 3)
for (c1 = 0; c1 < nc1 && (!data->dri || rst);
c1++, rst--, data->bitmap_ptr += hb * 3)
{
@ -660,17 +723,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
for (r2 = 0; r2 < (1U << data->log_vs); r2++)
for (c2 = 0; c2 < (1U << data->log_hs); c2++)
grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
{
err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
if (err != GRUB_ERR_NONE)
return err;
}
if (data->color_components >= 3)
{
grub_jpeg_decode_du (data, 1, data->cbdu);
grub_jpeg_decode_du (data, 2, data->crdu);
err = grub_jpeg_decode_du (data, 1, data->cbdu);
if (err != GRUB_ERR_NONE)
return err;
err = grub_jpeg_decode_du (data, 2, data->crdu);
if (err != GRUB_ERR_NONE)
return err;
}
if (grub_errno)
return grub_errno;
nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;

View File

@ -100,7 +100,7 @@ struct grub_png_data
unsigned image_width, image_height;
int bpp, is_16bit;
int raw_bytes, is_gray, is_alpha, is_palette;
int raw_bytes, is_alpha, is_palette;
int row_bytes, color_bits;
grub_uint8_t *image_data;
@ -142,6 +142,7 @@ static grub_uint8_t
grub_png_get_byte (struct grub_png_data *data)
{
grub_uint8_t r;
grub_ssize_t bytes_read = 0;
if ((data->inside_idat) && (data->idat_remain == 0))
{
@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data)
}
r = 0;
grub_file_read (data->file, &r, 1);
bytes_read = grub_file_read (data->file, &r, 1);
if (bytes_read != 1)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: unexpected end of data");
return 0;
}
if (data->inside_idat)
data->idat_remain--;
@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data,
if (len == 0)
return GRUB_ERR_NONE;
for (i = 0; 3 * i < len && i < 256; i++)
grub_errno = GRUB_ERR_NONE;
for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++)
for (j = 0; j < 3; j++)
data->palette[i][j] = grub_png_get_byte (data);
for (i *= 3; i < len; i++)
for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++)
grub_png_get_byte (data);
grub_png_get_dword (data);
return GRUB_ERR_NONE;
return grub_errno;
}
static grub_err_t
@ -249,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data)
int color_bits;
enum grub_video_blit_format blt;
if (data->image_width || data->image_height)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found");
data->image_width = grub_png_get_dword (data);
data->image_height = grub_png_get_dword (data);
@ -256,9 +268,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
color_bits = grub_png_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
data->is_16bit = (color_bits == 16);
color_type = grub_png_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* According to PNG spec, no other types are valid. */
if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
@ -280,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
data->bpp = 3;
else
{
data->is_gray = 1;
data->bpp = 1;
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: color type not supported");
}
if ((color_bits != 8) && (color_bits != 16)
&& (color_bits != 4
|| !(data->is_gray || data->is_palette)))
|| !data->is_palette))
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: bit depth must be 8 or 16");
@ -315,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
}
#ifndef GRUB_CPU_WORDS_BIGENDIAN
if (data->is_16bit || data->is_gray || data->is_palette)
if (data->is_16bit || data->is_palette)
#endif
{
data->image_data = grub_calloc (data->image_height, data->row_bytes);
@ -340,14 +356,20 @@ grub_png_decode_image_header (struct grub_png_data *data)
if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: compression method not supported");
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: filter method not supported");
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: interlace method not supported");
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Skip crc checksum. */
grub_png_get_dword (data);
@ -416,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
for (i = len; i < ht->max_length; i++)
n += ht->maxval[i];
if (n > ht->num_values)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: out of range inserting huffman table item");
return;
}
for (i = 0; i < n; i++)
ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
@ -449,7 +478,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
int code, i;
code = 0;
for (i = 0; i < ht->max_length; i++)
for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++)
{
code = (code << 1) + grub_png_get_bits (data, 1);
if (code < ht->maxval[i])
@ -504,8 +533,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
grub_uint8_t lens[DEFLATE_HCLEN_MAX];
nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
(nb > DEFLATE_HCLEN_MAX))
@ -533,7 +568,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
data->dist_offset);
prev = 0;
for (i = 0; i < nl + nd; i++)
for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++)
{
int n, code;
struct huff_table *ht;
@ -718,20 +753,30 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
int len, dist, pos;
n -= 257;
if (((unsigned int) n) >= ARRAY_SIZE (cplens))
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: invalid huff code");
len = cplens[n];
if (cplext[n])
len += grub_png_get_bits (data, cplext[n]);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
n = grub_png_get_huff_code (data, &data->dist_table);
if (((unsigned int) n) >= ARRAY_SIZE (cpdist))
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"png: invalid huff code");
dist = cpdist[n];
if (cpdext[n])
dist += grub_png_get_bits (data, cpdext[n]);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
pos = data->wp - dist;
if (pos < 0)
pos += WSIZE;
while (len > 0)
while (len > 0 && grub_errno == GRUB_ERR_NONE)
{
data->slide[data->wp] = data->slide[pos];
grub_png_output_byte (data, data->slide[data->wp]);
@ -759,7 +804,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
int final;
cmf = grub_png_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
flg = grub_png_get_byte (data);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
if ((cmf & 0xF) != Z_DEFLATED)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
@ -774,7 +823,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
int block_type;
final = grub_png_get_bits (data, 1);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
block_type = grub_png_get_bits (data, 2);
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
switch (block_type)
{
@ -790,7 +843,7 @@ grub_png_decode_image_data (struct grub_png_data *data)
grub_png_get_byte (data);
grub_png_get_byte (data);
for (i = 0; i < len; i++)
for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++)
grub_png_output_byte (data, grub_png_get_byte (data));
break;
@ -859,27 +912,8 @@ grub_png_convert_image (struct grub_png_data *data)
int shift;
int mask = (1 << data->color_bits) - 1;
unsigned j;
if (data->is_gray)
{
/* Generic formula is
(0xff * i) / ((1U << data->color_bits) - 1)
but for allowed bit depth of 1, 2 and for it's
equivalent to
(0xff / ((1U << data->color_bits) - 1)) * i
Precompute the multipliers to avoid division.
*/
const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
for (i = 0; i < (1U << data->color_bits); i++)
{
grub_uint8_t col = multipliers[data->color_bits] * i;
palette[i][0] = col;
palette[i][1] = col;
palette[i][2] = col;
}
}
else
grub_memcpy (palette, data->palette, 3 << data->color_bits);
grub_memcpy (palette, data->palette, 3 << data->color_bits);
d1c = d1;
d2c = d2;
for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
@ -917,60 +951,6 @@ grub_png_convert_image (struct grub_png_data *data)
return;
}
if (data->is_gray)
{
switch (data->bpp)
{
case 4:
/* 16-bit gray with alpha. */
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 4)
{
d1[R4] = d2[3];
d1[G4] = d2[3];
d1[B4] = d2[3];
d1[A4] = d2[1];
}
break;
case 2:
if (data->is_16bit)
/* 16-bit gray without alpha. */
{
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 2)
{
d1[R3] = d2[1];
d1[G3] = d2[1];
d1[B3] = d2[1];
}
}
else
/* 8-bit gray with alpha. */
{
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 4, d2 += 2)
{
d1[R4] = d2[1];
d1[G4] = d2[1];
d1[B4] = d2[1];
d1[A4] = d2[0];
}
}
break;
/* 8-bit gray without alpha. */
case 1:
for (i = 0; i < (data->image_width * data->image_height);
i++, d1 += 3, d2++)
{
d1[R3] = d2[0];
d1[G3] = d2[0];
d1[B3] = d2[0];
}
break;
}
return;
}
{
/* Only copy the upper 8 bit. */
#ifndef GRUB_CPU_WORDS_BIGENDIAN
@ -1045,6 +1025,8 @@ grub_png_decode_png (struct grub_png_data *data)
len = grub_png_get_dword (data);
type = grub_png_get_dword (data);
if (grub_errno != GRUB_ERR_NONE)
break;
data->next_offset = data->file->offset + len + 4;
switch (type)

View File

@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int flags);
void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *),
grub_err_t (*unload) (void *),
void *context,
int flags);
/* Unset current loader, if any. */
void EXPORT_FUNC (grub_loader_unset) (void);

View File

@ -277,6 +277,7 @@ typedef struct grub_net
grub_fs_t fs;
int eof;
int stall;
int broken;
} *grub_net_t;
extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);

View File

@ -24,6 +24,7 @@
enum grub_verify_flags
{
GRUB_VERIFY_FLAGS_NONE = 0,
GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
/* Defer verification to another authority. */