[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
This commit is contained in:
John Mark Bell 2005-09-07 20:22:33 +00:00
parent 01153ef217
commit 5903845c4a
2 changed files with 98 additions and 58 deletions

View File

@ -73,12 +73,12 @@ struct bitmap_compressed_header {
char bitmap_filename[256]; char bitmap_filename[256];
bool bitmap_initialise(struct bitmap *bitmap, bool clear); static bool bitmap_initialise(struct bitmap *bitmap, bool clear);
void bitmap_decompress(struct bitmap *bitmap); static void bitmap_decompress(struct bitmap *bitmap);
void bitmap_compress(struct bitmap *bitmap); static void bitmap_compress(struct bitmap *bitmap);
void bitmap_load_file(struct bitmap *bitmap); static void bitmap_load_file(struct bitmap *bitmap);
void bitmap_save_file(struct bitmap *bitmap); static void bitmap_save_file(struct bitmap *bitmap);
void bitmap_delete_file(struct bitmap *bitmap); static void bitmap_delete_file(struct bitmap *bitmap);
/** /**
@ -127,7 +127,7 @@ void bitmap_initialise_memory(void)
} else { } else {
compressed_size = (option_image_memory_compressed << 10); compressed_size = (option_image_memory_compressed << 10);
} }
/* set our values. No fixed buffers here, ho hum. */ /* set our values. No fixed buffers here, ho hum. */
bitmap_direct_size = direct_size; bitmap_direct_size = direct_size;
bitmap_compressed_size = compressed_size; bitmap_compressed_size = compressed_size;
@ -145,10 +145,10 @@ void bitmap_initialise_memory(void)
void bitmap_quit(void) void bitmap_quit(void)
{ {
struct bitmap *bitmap; struct bitmap *bitmap;
for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next) for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next)
if ((bitmap->persistent) && (bitmap->filename[0] == '\0')) 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; return ((char *) (bitmap->sprite_area)) + 16 + 44;
/* load and/or decompress the image */ /* load and/or decompress the image */
if (bitmap->filename[0]) if (bitmap->filename && bitmap->filename[0])
bitmap_load_file(bitmap); bitmap_load_file(bitmap);
if (bitmap->compressed) if (bitmap->compressed)
bitmap_decompress(bitmap); bitmap_decompress(bitmap);
@ -409,9 +409,9 @@ size_t bitmap_get_rowstride(struct bitmap *bitmap)
void bitmap_destroy(struct bitmap *bitmap) void bitmap_destroy(struct bitmap *bitmap)
{ {
unsigned int area_size; unsigned int area_size;
assert(bitmap); assert(bitmap);
/* delink from list */ /* delink from list */
bitmap_maintenance = true; bitmap_maintenance = true;
if (bitmap_head == bitmap) if (bitmap_head == bitmap)
@ -424,12 +424,12 @@ void bitmap_destroy(struct bitmap *bitmap)
/* destroy bitmap */ /* destroy bitmap */
if (bitmap->sprite_area) { if (bitmap->sprite_area) {
area_size = 16 + 44 + bitmap->width * bitmap->height * 4; area_size = 16 + 44 + bitmap->width * bitmap->height * 4;
bitmap_direct_used -= area_size; bitmap_direct_used -= area_size;
free(bitmap->sprite_area); free(bitmap->sprite_area);
} }
if (bitmap->compressed) if (bitmap->compressed)
free(bitmap->compressed); free(bitmap->compressed);
if (bitmap->filename[0]) if (bitmap->filename && bitmap->filename[0])
bitmap_delete_file(bitmap); bitmap_delete_file(bitmap);
free(bitmap); free(bitmap);
} }
@ -536,7 +536,7 @@ void bitmap_maintain(void)
if (bitmap_maintenance_priority) { if (bitmap_maintenance_priority) {
if (bitmap->sprite_area) if (bitmap->sprite_area)
bitmap_save_file(bitmap); bitmap_save_file(bitmap);
} else { } else {
bitmap_save_file(bitmap); bitmap_save_file(bitmap);
return; return;
@ -574,7 +574,7 @@ void bitmap_decompress(struct bitmap *bitmap)
free(bitmap->sprite_area); free(bitmap->sprite_area);
bitmap->sprite_area = NULL; bitmap->sprite_area = NULL;
} else { } else {
// LOG(("Decompressed")); // LOG(("Decompressed"));
header = (struct bitmap_compressed_header *)bitmap->compressed; header = (struct bitmap_compressed_header *)bitmap->compressed;
area_size = header->input_size + area_size = header->input_size +
sizeof(struct bitmap_compressed_header); sizeof(struct bitmap_compressed_header);
@ -582,14 +582,14 @@ void bitmap_decompress(struct bitmap *bitmap)
free(bitmap->compressed); free(bitmap->compressed);
bitmap->compressed = NULL; bitmap->compressed = NULL;
area_size = 16 + 44 + bitmap->width * bitmap->height * 4; 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) void bitmap_compress(struct bitmap *bitmap)
{ {
unsigned int area_size; unsigned int area_size;
_kernel_oserror *error; _kernel_oserror *error;
char *output; char *output;
unsigned int output_size, new_size; unsigned int output_size, new_size;
@ -619,11 +619,11 @@ void bitmap_compress(struct bitmap *bitmap)
if (!bitmap->compressed) { if (!bitmap->compressed) {
free(output); free(output);
} else { } else {
bitmap_compressed_used += new_size; bitmap_compressed_used += new_size;
if (bitmap->sprite_area) { if (bitmap->sprite_area) {
area_size = 16 + 44 + bitmap->width * area_size = 16 + 44 + bitmap->width *
bitmap->height * 4; bitmap->height * 4;
bitmap_direct_used -= area_size; bitmap_direct_used -= area_size;
free(bitmap->sprite_area); free(bitmap->sprite_area);
} }
bitmap->sprite_area = NULL; bitmap->sprite_area = NULL;
@ -636,7 +636,7 @@ void bitmap_compress(struct bitmap *bitmap)
void bitmap_load_file(struct bitmap *bitmap) void bitmap_load_file(struct bitmap *bitmap)
{ {
unsigned int area_size; unsigned int area_size;
int len; int len;
fileswitch_object_type obj_type; fileswitch_object_type obj_type;
os_error *error; os_error *error;
@ -649,44 +649,69 @@ void bitmap_load_file(struct bitmap *bitmap)
&obj_type, 0, 0, &len, 0, 0); &obj_type, 0, 0, &len, 0, 0);
if ((error) || (obj_type != fileswitch_IS_FILE)) if ((error) || (obj_type != fileswitch_IS_FILE))
return; return;
bitmap->compressed = malloc(len); bitmap->compressed = malloc(len);
if (!bitmap->compressed) if (!bitmap->compressed)
return; return;
error = xosfile_load_stamped_no_path(bitmap_filename, error = xosfile_load_stamped_no_path(bitmap_filename,
bitmap->compressed, 0, 0, 0, 0, 0); bitmap->compressed, 0, 0, 0, 0, 0);
if (error) { if (error) {
free(bitmap->compressed); free(bitmap->compressed);
bitmap->compressed = NULL; bitmap->compressed = NULL;
return; 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) void bitmap_save_file(struct bitmap *bitmap)
{ {
unsigned int area_size; unsigned int area_size;
char *filename; char *filename;
os_error *error; os_error *error;
struct bitmap_compressed_header *header; struct bitmap_compressed_header *header;
assert(bitmap->compressed || bitmap->sprite_area); assert(bitmap->compressed || bitmap->sprite_area);
/* unmodified bitmaps will still have their file available */ /* 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) if (bitmap->sprite_area)
free(bitmap->sprite_area); free(bitmap->sprite_area);
bitmap->sprite_area = NULL; bitmap->sprite_area = NULL;
@ -722,12 +747,12 @@ void bitmap_save_file(struct bitmap *bitmap)
bitmap->filename[0] = 0; bitmap->filename[0] = 0;
} else { } else {
if (bitmap->sprite_area) { if (bitmap->sprite_area) {
bitmap_direct_used -= area_size; bitmap_direct_used -= area_size;
free(bitmap->sprite_area); free(bitmap->sprite_area);
} }
bitmap->sprite_area = NULL; bitmap->sprite_area = NULL;
if (bitmap->compressed) { if (bitmap->compressed) {
bitmap_compressed_used -= area_size; bitmap_compressed_used -= area_size;
free(bitmap->compressed); free(bitmap->compressed);
} }
bitmap->compressed = NULL; bitmap->compressed = NULL;

View File

@ -13,6 +13,7 @@
* page at a small scale. * page at a small scale.
*/ */
#include <assert.h>
#include <string.h> #include <string.h>
#include <swis.h> #include <swis.h>
#include "rufl.h" #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 * \param url the URL the thumnail belongs to, or NULL
*/ */
bool thumbnail_create(struct content *content, struct bitmap *bitmap, bool thumbnail_create(struct content *content, struct bitmap *bitmap,
const char *url) { const char *url)
{
float scale = 1.0; float scale = 1.0;
struct thumbnail_save_area *save_area; struct thumbnail_save_area *save_area;
osspriteop_area *sprite_area = NULL; osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL; osspriteop_header *sprite_header = NULL;
_kernel_oserror *error; _kernel_oserror *error;
assert(content);
assert(bitmap);
/* check if we have access to 32bpp sprites natively */ /* check if we have access to 32bpp sprites natively */
if (thumbnail_32bpp_available == -1) if (thumbnail_32bpp_available == -1)
thumbnail_test(); 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 /* if we don't support 32bpp sprites then we redirect to an 8bpp
* image and then convert back. */ * image and then convert back. */
if (thumbnail_32bpp_available != 1) { if (thumbnail_32bpp_available != 1) {
sprite_area = thumbnail_create_8bpp(bitmap); sprite_area = thumbnail_create_8bpp(bitmap);
if (!sprite_area) if (!sprite_area)
return false; return false;
sprite_header = (osspriteop_header *)(sprite_area + 1); sprite_header = (osspriteop_header *)(sprite_area + 1);
} else { } else {
bitmap_get_buffer(bitmap); char *pixbufp = bitmap_get_buffer(bitmap);
if (!pixbufp || !bitmap->sprite_area)
return false;
sprite_area = bitmap->sprite_area; sprite_area = bitmap->sprite_area;
sprite_header = (osspriteop_header *)(sprite_area + 1); sprite_header = (osspriteop_header *)(sprite_area + 1);
} }
@ -100,7 +107,7 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
/* switch output and redraw */ /* switch output and redraw */
save_area = thumbnail_switch_output(sprite_area, sprite_header); save_area = thumbnail_switch_output(sprite_area, sprite_header);
if (save_area == NULL) { if (!save_area) {
if (thumbnail_32bpp_available != 1) if (thumbnail_32bpp_available != 1)
free(sprite_area); free(sprite_area);
return false; 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 we changed to 8bpp then go back to 32bpp */
if (thumbnail_32bpp_available != 1) { 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), error = _swix(Tinct_ConvertSprite, _INR(2,3),
sprite_header, sprite_header,
(osspriteop_header *)(bitmap->sprite_area + 1)); (osspriteop_header *)(bitmap->sprite_area + 1));
@ -124,11 +135,11 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
if (error) if (error)
return false; return false;
} }
/* register the thumbnail with the URL */ /* register the thumbnail with the URL */
if (url) if (url)
url_store_add_thumbnail(url, bitmap); url_store_add_thumbnail(url, bitmap);
bitmap_modified(bitmap); bitmap_modified(bitmap);
bitmap->persistent = true; bitmap->persistent = true;
return true; return true;
@ -141,12 +152,13 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
* \param bitmap the bitmap to convert * \param bitmap the bitmap to convert
* \return a sprite area containing an 8bpp sprite * \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; struct thumbnail_save_area *save_area;
osspriteop_area *sprite_area = NULL; osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL; osspriteop_header *sprite_header = NULL;
sprite_area = thumbnail_create_8bpp(bitmap); sprite_area = thumbnail_create_8bpp(bitmap);
if (!sprite_area) if (!sprite_area)
return NULL; return NULL;
sprite_header = (osspriteop_header *)(sprite_area + 1); sprite_header = (osspriteop_header *)(sprite_area + 1);
@ -164,7 +176,7 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) {
0, 0, 0, 0,
tinct_ERROR_DIFFUSE); tinct_ERROR_DIFFUSE);
thumbnail_restore_output(save_area); thumbnail_restore_output(save_area);
return sprite_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 * \param bitmap the bitmap to clone the size of
* \return a sprite area containing an 8bpp sprite * \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; unsigned int area_size;
osspriteop_area *sprite_area = NULL; osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = 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 * Rather than using Wimp_ReadSysInfo we test if 32bpp sprites are available
* in case the user has a 3rd party patch to enable them. * 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; unsigned int area_size;
osspriteop_area *sprite_area; osspriteop_area *sprite_area;
@ -252,7 +266,8 @@ static void thumbnail_test(void) {
*/ */
static struct thumbnail_save_area* thumbnail_switch_output( static struct thumbnail_save_area* thumbnail_switch_output(
osspriteop_area *sprite_area, osspriteop_area *sprite_area,
osspriteop_header *sprite_header) { osspriteop_header *sprite_header)
{
struct thumbnail_save_area *save_area; struct thumbnail_save_area *save_area;
int size; int size;
@ -291,8 +306,8 @@ static struct thumbnail_save_area* thumbnail_switch_output(
/** /**
* Restores output to the specified context, and destroys it. * 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 */ /* we don't care if we err, as there's nothing we can do about it */
xosspriteop_switch_output_to_sprite(osspriteop_PTR, xosspriteop_switch_output_to_sprite(osspriteop_PTR,
(osspriteop_area *)save_area->context1, (osspriteop_area *)save_area->context1,