From 5903845c4a8d66d642205d46852a4555d2eedfdc Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 7 Sep 2005 20:22:33 +0000 Subject: [PATCH] [project @ 2005-09-07 20:22:33 by jmb] Tighten up error checking. When loading bitmaps from the disk cache, ensure they look valid. svn path=/import/netsurf/; revision=1862 --- riscos/bitmap.c | 107 ++++++++++++++++++++++++++++----------------- riscos/thumbnail.c | 49 ++++++++++++++------- 2 files changed, 98 insertions(+), 58 deletions(-) diff --git a/riscos/bitmap.c b/riscos/bitmap.c index 6652e4d68..0acfa35dc 100644 --- a/riscos/bitmap.c +++ b/riscos/bitmap.c @@ -73,12 +73,12 @@ struct bitmap_compressed_header { char bitmap_filename[256]; -bool bitmap_initialise(struct bitmap *bitmap, bool clear); -void bitmap_decompress(struct bitmap *bitmap); -void bitmap_compress(struct bitmap *bitmap); -void bitmap_load_file(struct bitmap *bitmap); -void bitmap_save_file(struct bitmap *bitmap); -void bitmap_delete_file(struct bitmap *bitmap); +static bool bitmap_initialise(struct bitmap *bitmap, bool clear); +static void bitmap_decompress(struct bitmap *bitmap); +static void bitmap_compress(struct bitmap *bitmap); +static void bitmap_load_file(struct bitmap *bitmap); +static void bitmap_save_file(struct bitmap *bitmap); +static void bitmap_delete_file(struct bitmap *bitmap); /** @@ -127,7 +127,7 @@ void bitmap_initialise_memory(void) } else { compressed_size = (option_image_memory_compressed << 10); } - + /* set our values. No fixed buffers here, ho hum. */ bitmap_direct_size = direct_size; bitmap_compressed_size = compressed_size; @@ -145,10 +145,10 @@ void bitmap_initialise_memory(void) void bitmap_quit(void) { struct bitmap *bitmap; - + for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next) if ((bitmap->persistent) && (bitmap->filename[0] == '\0')) - bitmap_save_file(bitmap); + bitmap_save_file(bitmap); } @@ -372,7 +372,7 @@ char *bitmap_get_buffer(struct bitmap *bitmap) return ((char *) (bitmap->sprite_area)) + 16 + 44; /* load and/or decompress the image */ - if (bitmap->filename[0]) + if (bitmap->filename && bitmap->filename[0]) bitmap_load_file(bitmap); if (bitmap->compressed) bitmap_decompress(bitmap); @@ -409,9 +409,9 @@ size_t bitmap_get_rowstride(struct bitmap *bitmap) void bitmap_destroy(struct bitmap *bitmap) { unsigned int area_size; - + assert(bitmap); - + /* delink from list */ bitmap_maintenance = true; if (bitmap_head == bitmap) @@ -424,12 +424,12 @@ void bitmap_destroy(struct bitmap *bitmap) /* destroy bitmap */ if (bitmap->sprite_area) { area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used -= area_size; + bitmap_direct_used -= area_size; free(bitmap->sprite_area); } if (bitmap->compressed) free(bitmap->compressed); - if (bitmap->filename[0]) + if (bitmap->filename && bitmap->filename[0]) bitmap_delete_file(bitmap); free(bitmap); } @@ -536,7 +536,7 @@ void bitmap_maintain(void) if (bitmap_maintenance_priority) { if (bitmap->sprite_area) bitmap_save_file(bitmap); - + } else { bitmap_save_file(bitmap); return; @@ -574,7 +574,7 @@ void bitmap_decompress(struct bitmap *bitmap) free(bitmap->sprite_area); bitmap->sprite_area = NULL; } else { -// LOG(("Decompressed")); +// LOG(("Decompressed")); header = (struct bitmap_compressed_header *)bitmap->compressed; area_size = header->input_size + sizeof(struct bitmap_compressed_header); @@ -582,14 +582,14 @@ void bitmap_decompress(struct bitmap *bitmap) free(bitmap->compressed); bitmap->compressed = NULL; area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used += area_size; + bitmap_direct_used += area_size; } } void bitmap_compress(struct bitmap *bitmap) { - unsigned int area_size; + unsigned int area_size; _kernel_oserror *error; char *output; unsigned int output_size, new_size; @@ -619,11 +619,11 @@ void bitmap_compress(struct bitmap *bitmap) if (!bitmap->compressed) { free(output); } else { - bitmap_compressed_used += new_size; - if (bitmap->sprite_area) { + bitmap_compressed_used += new_size; + if (bitmap->sprite_area) { area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used -= area_size; + bitmap_direct_used -= area_size; free(bitmap->sprite_area); } bitmap->sprite_area = NULL; @@ -636,7 +636,7 @@ void bitmap_compress(struct bitmap *bitmap) void bitmap_load_file(struct bitmap *bitmap) { - unsigned int area_size; + unsigned int area_size; int len; fileswitch_object_type obj_type; os_error *error; @@ -649,44 +649,69 @@ void bitmap_load_file(struct bitmap *bitmap) &obj_type, 0, 0, &len, 0, 0); if ((error) || (obj_type != fileswitch_IS_FILE)) return; + bitmap->compressed = malloc(len); if (!bitmap->compressed) return; + error = xosfile_load_stamped_no_path(bitmap_filename, bitmap->compressed, 0, 0, 0, 0, 0); if (error) { free(bitmap->compressed); bitmap->compressed = NULL; return; - } else { -// LOG(("Loaded file from disk")); - if (strncmp(bitmap->compressed + 8, "bitmap", 6)) { - bitmap->sprite_area = - (osspriteop_area *)bitmap->compressed; - bitmap->compressed = NULL; - area_size = 16 + 44 + - bitmap->width * bitmap->height * 4; - bitmap_direct_used += area_size; - } else { - bitmap_compressed_used -= len; - } - if (bitmap->modified) - bitmap_delete_file(bitmap); } + +// LOG(("Loaded file from disk")); + /* Sanity check the file we've just loaded: + * If it's an uncompressed buffer, then it's a raw sprite area, + * including the total size word at the start. Therefore, we check + * that: + * a) The declared total area size == file length + * b) The offset to the first free word == file length + * c) There is only 1 sprite in the area + * d) The name of the sprite in the area is "bitmap" + * + * If it's a compressed buffer, then we check that: + * a) The declared input size + header size == file length + * b) The name of the buffer is "bitmap" + * + * If it's neither of these, we fail. + */ + if ((*(int *)bitmap->compressed) == len && + (*(((int *)bitmap->compressed) + 3)) == len && + (*(((int *)bitmap->compressed) + 1)) == 1 && + strncmp(bitmap->compressed + 20, "bitmap", 6) == 0) { + bitmap->sprite_area = (osspriteop_area *)bitmap->compressed; + bitmap->compressed = NULL; + area_size = 16 + 44 + bitmap->width * bitmap->height * 4; + bitmap_direct_used += area_size; + } else if ((int)((*(((int *)bitmap->compressed) + 6)) + + sizeof(struct bitmap_compressed_header)) == len && + strncmp(bitmap->compressed + 8, "bitmap", 6) == 0) { + bitmap_compressed_used -= len; + } else { + free(bitmap->compressed); + bitmap->compressed = NULL; + return; + } + + if (bitmap->modified) + bitmap_delete_file(bitmap); } void bitmap_save_file(struct bitmap *bitmap) { - unsigned int area_size; - char *filename; + unsigned int area_size; + char *filename; os_error *error; struct bitmap_compressed_header *header; assert(bitmap->compressed || bitmap->sprite_area); /* unmodified bitmaps will still have their file available */ - if (!bitmap->modified && bitmap->filename[0]) { + if (!bitmap->modified && bitmap->filename && bitmap->filename[0]) { if (bitmap->sprite_area) free(bitmap->sprite_area); bitmap->sprite_area = NULL; @@ -722,12 +747,12 @@ void bitmap_save_file(struct bitmap *bitmap) bitmap->filename[0] = 0; } else { if (bitmap->sprite_area) { - bitmap_direct_used -= area_size; + bitmap_direct_used -= area_size; free(bitmap->sprite_area); } bitmap->sprite_area = NULL; if (bitmap->compressed) { - bitmap_compressed_used -= area_size; + bitmap_compressed_used -= area_size; free(bitmap->compressed); } bitmap->compressed = NULL; diff --git a/riscos/thumbnail.c b/riscos/thumbnail.c index 123e84d37..e1231cd2d 100644 --- a/riscos/thumbnail.c +++ b/riscos/thumbnail.c @@ -13,6 +13,7 @@ * page at a small scale. */ +#include #include #include #include "rufl.h" @@ -65,13 +66,17 @@ static void thumbnail_restore_output(struct thumbnail_save_area *save_area); * \param url the URL the thumnail belongs to, or NULL */ bool thumbnail_create(struct content *content, struct bitmap *bitmap, - const char *url) { + const char *url) +{ float scale = 1.0; struct thumbnail_save_area *save_area; osspriteop_area *sprite_area = NULL; osspriteop_header *sprite_header = NULL; _kernel_oserror *error; + assert(content); + assert(bitmap); + /* check if we have access to 32bpp sprites natively */ if (thumbnail_32bpp_available == -1) thumbnail_test(); @@ -79,12 +84,14 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap, /* if we don't support 32bpp sprites then we redirect to an 8bpp * image and then convert back. */ if (thumbnail_32bpp_available != 1) { - sprite_area = thumbnail_create_8bpp(bitmap); - if (!sprite_area) - return false; + sprite_area = thumbnail_create_8bpp(bitmap); + if (!sprite_area) + return false; sprite_header = (osspriteop_header *)(sprite_area + 1); } else { - bitmap_get_buffer(bitmap); + char *pixbufp = bitmap_get_buffer(bitmap); + if (!pixbufp || !bitmap->sprite_area) + return false; sprite_area = bitmap->sprite_area; sprite_header = (osspriteop_header *)(sprite_area + 1); } @@ -100,7 +107,7 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap, /* switch output and redraw */ save_area = thumbnail_switch_output(sprite_area, sprite_header); - if (save_area == NULL) { + if (!save_area) { if (thumbnail_32bpp_available != 1) free(sprite_area); return false; @@ -116,7 +123,11 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap, /* if we changed to 8bpp then go back to 32bpp */ if (thumbnail_32bpp_available != 1) { - bitmap_get_buffer(bitmap); + char *pixbufp = bitmap_get_buffer(bitmap); + if (!pixbufp || !bitmap->sprite_area) { + free(sprite_area); + return false; + } error = _swix(Tinct_ConvertSprite, _INR(2,3), sprite_header, (osspriteop_header *)(bitmap->sprite_area + 1)); @@ -124,11 +135,11 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap, if (error) return false; } - + /* register the thumbnail with the URL */ if (url) url_store_add_thumbnail(url, bitmap); - + bitmap_modified(bitmap); bitmap->persistent = true; return true; @@ -141,12 +152,13 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap, * \param bitmap the bitmap to convert * \return a sprite area containing an 8bpp sprite */ -osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) { +osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) +{ struct thumbnail_save_area *save_area; osspriteop_area *sprite_area = NULL; osspriteop_header *sprite_header = NULL; - sprite_area = thumbnail_create_8bpp(bitmap); + sprite_area = thumbnail_create_8bpp(bitmap); if (!sprite_area) return NULL; sprite_header = (osspriteop_header *)(sprite_area + 1); @@ -164,7 +176,7 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) { 0, 0, tinct_ERROR_DIFFUSE); thumbnail_restore_output(save_area); - + return sprite_area; } @@ -175,7 +187,8 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) { * \param bitmap the bitmap to clone the size of * \return a sprite area containing an 8bpp sprite */ -osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) { +osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) +{ unsigned int area_size; osspriteop_area *sprite_area = NULL; osspriteop_header *sprite_header = NULL; @@ -223,7 +236,8 @@ osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) { * Rather than using Wimp_ReadSysInfo we test if 32bpp sprites are available * in case the user has a 3rd party patch to enable them. */ -static void thumbnail_test(void) { +static void thumbnail_test(void) +{ unsigned int area_size; osspriteop_area *sprite_area; @@ -252,7 +266,8 @@ static void thumbnail_test(void) { */ static struct thumbnail_save_area* thumbnail_switch_output( osspriteop_area *sprite_area, - osspriteop_header *sprite_header) { + osspriteop_header *sprite_header) +{ struct thumbnail_save_area *save_area; int size; @@ -291,8 +306,8 @@ static struct thumbnail_save_area* thumbnail_switch_output( /** * Restores output to the specified context, and destroys it. */ -static void thumbnail_restore_output(struct thumbnail_save_area *save_area) { - +static void thumbnail_restore_output(struct thumbnail_save_area *save_area) +{ /* we don't care if we err, as there's nothing we can do about it */ xosspriteop_switch_output_to_sprite(osspriteop_PTR, (osspriteop_area *)save_area->context1,