Fix out of memory hang. Add sanity checks

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-12 17:47:14 +01:00
parent 8468cbeccd
commit 1d24828f20

View file

@ -22,6 +22,10 @@
#include <grub/misc.h> #include <grub/misc.h>
/* TODO: use more efficient data structures if necessary. */ /* TODO: use more efficient data structures if necessary. */
/* FIXME: implement unload. */
/* FIXME: check memory map. */
/* FIXME: try to request memory from firmware. */
/* FIXME: sort chunk when programming relocators. */
struct grub_relocator * struct grub_relocator *
grub_relocator_new (void) grub_relocator_new (void)
@ -180,11 +184,13 @@ malloc_in_range (struct grub_relocator *rel,
grub_size_t size, grub_addr_t *res, int from_low_priv, grub_size_t size, grub_addr_t *res, int from_low_priv,
int collisioncheck) int collisioncheck)
{ {
grub_mm_region_t rb = NULL, rbp = NULL; grub_mm_region_t rb, rbp;
grub_mm_header_t hb = NULL, hbp = NULL; grub_mm_header_t hb = NULL, hbp = NULL;
grub_addr_t best_addr; grub_addr_t best_addr;
again: again:
rb = NULL, rbp = NULL;
{ {
grub_mm_region_t r, rp; grub_mm_region_t r, rp;
@ -344,6 +350,9 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src,
grub_addr_t start; grub_addr_t start;
grub_addr_t min_addr = 0, max_addr; grub_addr_t min_addr = 0, max_addr;
if (target > ~size)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "address is out of range");
adjust_limits (rel, &min_addr, &max_addr, target, target); adjust_limits (rel, &min_addr, &max_addr, target, target);
for (chunk = rel->chunks; chunk; chunk = chunk->next) for (chunk = rel->chunks; chunk; chunk = chunk->next)
@ -356,8 +365,10 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src,
if (!chunk) if (!chunk)
return grub_errno; return grub_errno;
grub_dprintf ("relocator", "min_addr = 0x%llx, max_addr = 0x%llx\n", grub_dprintf ("relocator",
(unsigned long long) min_addr, (unsigned long long) max_addr); "min_addr = 0x%llx, max_addr = 0x%llx, target = 0x%llx\n",
(unsigned long long) min_addr, (unsigned long long) max_addr,
(unsigned long long) target);
do do
{ {
@ -441,6 +452,9 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
struct grub_relocator_chunk *chunk; struct grub_relocator_chunk *chunk;
grub_addr_t start; grub_addr_t start;
if (max_addr > ~size)
max_addr = ~size;
grub_dprintf ("relocator", "chunks = %p\n", rel->chunks); grub_dprintf ("relocator", "chunks = %p\n", rel->chunks);
chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); chunk = grub_malloc (sizeof (struct grub_relocator_chunk));