GIFTranslator: try hard to not throw an exception
... by calling new(std::nothrow) Also try really hard not to leak any memory in the process. Lots of error checking added to check if reads and writes fail returning B_IO_ERROR and if initialization fails returning B_NO_MEMORY
This commit is contained in:
@@ -22,6 +22,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
#include <InterfaceDefs.h>
|
#include <InterfaceDefs.h>
|
||||||
#include <TranslatorFormats.h>
|
#include <TranslatorFormats.h>
|
||||||
@@ -139,7 +141,10 @@ GIFLoad::ReadGIFHeader()
|
|||||||
fWidth = header[6] + (header[7] << 8);
|
fWidth = header[6] + (header[7] << 8);
|
||||||
fHeight = header[8] + (header[9] << 8);
|
fHeight = header[8] + (header[9] << 8);
|
||||||
|
|
||||||
fPalette = new LoadPalette();
|
fPalette = new(std::nothrow) LoadPalette();
|
||||||
|
if (fPalette == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Global palette
|
// Global palette
|
||||||
if (header[10] & GIF_LOCALCOLORMAP) {
|
if (header[10] & GIF_LOCALCOLORMAP) {
|
||||||
fPalette->size_in_bits = (header[10] & 0x07) + 1;
|
fPalette->size_in_bits = (header[10] & 0x07) + 1;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include "GIFPrivate.h"
|
#include "GIFPrivate.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -58,13 +60,21 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fatalerror = false;
|
fatalerror = false;
|
||||||
if (fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE) == OPTIMAL_PALETTE)
|
if (fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE) == OPTIMAL_PALETTE) {
|
||||||
palette = new SavePalette(bitmap,
|
palette = new(std::nothrow) SavePalette(bitmap,
|
||||||
fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE));
|
fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE));
|
||||||
else
|
} else {
|
||||||
palette = new SavePalette(
|
palette = new(std::nothrow) SavePalette(
|
||||||
fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE));
|
fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palette == NULL) {
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!palette->IsValid()) {
|
if (!palette->IsValid()) {
|
||||||
|
delete palette;
|
||||||
fatalerror = true;
|
fatalerror = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -80,13 +90,33 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
|||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_INFO, "GIFSave::GIFSave() - Using dithering\n");
|
syslog(LOG_INFO, "GIFSave::GIFSave() - Using dithering\n");
|
||||||
|
|
||||||
red_error = new int32[width + 2];
|
red_error = new(std::nothrow) int32[width + 2];
|
||||||
|
if (red_error == NULL) {
|
||||||
|
delete palette;
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
red_error = &red_error[1];
|
red_error = &red_error[1];
|
||||||
// Allow index of -1 too
|
// Allow index of -1 too
|
||||||
green_error = new int32[width + 2];
|
|
||||||
|
green_error = new(std::nothrow) int32[width + 2];
|
||||||
|
if (green_error == NULL) {
|
||||||
|
delete palette;
|
||||||
|
delete[] red_error;
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
green_error = &green_error[1];
|
green_error = &green_error[1];
|
||||||
// Allow index of -1 too
|
// Allow index of -1 too
|
||||||
blue_error = new int32[width + 2];
|
|
||||||
|
blue_error = new(std::nothrow) int32[width + 2];
|
||||||
|
if (blue_error == NULL) {
|
||||||
|
delete palette;
|
||||||
|
delete[] red_error;
|
||||||
|
delete[] green_error;
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
blue_error = &blue_error[1];
|
blue_error = &blue_error[1];
|
||||||
// Allow index of -1 too
|
// Allow index of -1 too
|
||||||
|
|
||||||
@@ -151,11 +181,29 @@ GIFSave::GIFSave(BBitmap* bitmap, BPositionIO* output,
|
|||||||
|
|
||||||
this->output = output;
|
this->output = output;
|
||||||
this->bitmap = bitmap;
|
this->bitmap = bitmap;
|
||||||
WriteGIFHeader();
|
|
||||||
|
if (WriteGIFHeader() != B_OK) {
|
||||||
|
delete palette;
|
||||||
|
delete[] red_error;
|
||||||
|
delete[] green_error;
|
||||||
|
delete[] blue_error;
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_INFO, "GIFSave::GIFSave() - Wrote gif header\n");
|
syslog(LOG_INFO, "GIFSave::GIFSave() - Wrote gif header\n");
|
||||||
|
|
||||||
hash = new SFHash(1 << 16);
|
hash = new(std::nothrow) SFHash(1 << 16);
|
||||||
|
if (hash == NULL) {
|
||||||
|
delete palette;
|
||||||
|
delete[] red_error;
|
||||||
|
delete[] green_error;
|
||||||
|
delete[] blue_error;
|
||||||
|
fatalerror = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteGIFControlBlock();
|
WriteGIFControlBlock();
|
||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_INFO, "GIFSave::GIFSave() - Wrote gif control block\n");
|
syslog(LOG_INFO, "GIFSave::GIFSave() - Wrote gif control block\n");
|
||||||
@@ -188,7 +236,7 @@ GIFSave::~GIFSave()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
GIFSave::WriteGIFHeader()
|
GIFSave::WriteGIFHeader()
|
||||||
{
|
{
|
||||||
// Standard header
|
// Standard header
|
||||||
@@ -200,19 +248,28 @@ GIFSave::WriteGIFHeader()
|
|||||||
header[9] = (height & 0xff00) >> 8;
|
header[9] = (height & 0xff00) >> 8;
|
||||||
header[10] = 0xf0 | (palette->SizeInBits() - 1);
|
header[10] = 0xf0 | (palette->SizeInBits() - 1);
|
||||||
header[11] = palette->BackgroundIndex();
|
header[11] = palette->BackgroundIndex();
|
||||||
output->Write(header, 13);
|
if (output->Write(header, 13) < 0)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
// global palette
|
// global palette
|
||||||
int size = (1 << palette->SizeInBits()) * 3;
|
int size = (1 << palette->SizeInBits()) * 3;
|
||||||
uint8* buffer = new uint8[size];
|
|
||||||
// can't be bigger than this
|
// can't be bigger than this
|
||||||
|
uint8* buffer = new(std::nothrow) uint8[size];
|
||||||
|
if (buffer == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
palette->GetColors(buffer, size);
|
palette->GetColors(buffer, size);
|
||||||
output->Write(buffer, size);
|
if (output->Write(buffer, size) < 0) {
|
||||||
|
delete[] buffer;
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
GIFSave::WriteGIFControlBlock()
|
GIFSave::WriteGIFControlBlock()
|
||||||
{
|
{
|
||||||
unsigned char b[8] = {
|
unsigned char b[8] = {
|
||||||
@@ -223,11 +280,11 @@ GIFSave::WriteGIFControlBlock()
|
|||||||
b[3] = b[3] | 1;
|
b[3] = b[3] | 1;
|
||||||
b[6] = palette->TransparentIndex();
|
b[6] = palette->TransparentIndex();
|
||||||
}
|
}
|
||||||
output->Write(b, 8);
|
return output->Write(b, 8) < 0 ? B_IO_ERROR : B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
GIFSave::WriteGIFImageHeader()
|
GIFSave::WriteGIFImageHeader()
|
||||||
{
|
{
|
||||||
unsigned char header[10];
|
unsigned char header[10];
|
||||||
@@ -245,21 +302,55 @@ GIFSave::WriteGIFImageHeader()
|
|||||||
else
|
else
|
||||||
header[9] = BLOCK_TERMINATOR;
|
header[9] = BLOCK_TERMINATOR;
|
||||||
|
|
||||||
output->Write(header, 10);
|
return output->Write(header, 10) < 0 ? B_IO_ERROR : B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
GIFSave::WriteGIFImageData()
|
GIFSave::WriteGIFImageData()
|
||||||
{
|
{
|
||||||
InitFrame();
|
InitFrame();
|
||||||
|
|
||||||
|
status_t result = B_OK;
|
||||||
|
|
||||||
code_value = (short*)malloc(HASHSIZE * 2);
|
code_value = (short*)malloc(HASHSIZE * 2);
|
||||||
|
if (code_value == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
prefix_code = (short*)malloc(HASHSIZE * 2);
|
prefix_code = (short*)malloc(HASHSIZE * 2);
|
||||||
|
if (prefix_code == NULL) {
|
||||||
|
free(code_value);
|
||||||
|
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
append_char = (unsigned char*)malloc(HASHSIZE);
|
append_char = (unsigned char*)malloc(HASHSIZE);
|
||||||
|
if (append_char == NULL) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
ResetHashtable();
|
ResetHashtable();
|
||||||
|
|
||||||
output->Write(&code_size, 1);
|
if (output->Write(&code_size, 1) < 0) {
|
||||||
OutputCode(clear_code, BITS);
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = OutputCode(clear_code, BITS);
|
||||||
|
if (result != B_OK) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
string_code = NextPixel(0);
|
string_code = NextPixel(0);
|
||||||
int area = height * width;
|
int area = height * width;
|
||||||
|
|
||||||
@@ -270,12 +361,27 @@ GIFSave::WriteGIFImageData()
|
|||||||
string_code = y;
|
string_code = y;
|
||||||
else {
|
else {
|
||||||
AddToHashtable(string_code, character);
|
AddToHashtable(string_code, character);
|
||||||
OutputCode(string_code, BITS);
|
result = OutputCode(string_code, BITS);
|
||||||
|
if (result != B_OK) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (next_code > max_code) {
|
if (next_code > max_code) {
|
||||||
BITS++;
|
BITS++;
|
||||||
if (BITS > LZ_MAX_BITS) {
|
if (BITS > LZ_MAX_BITS) {
|
||||||
OutputCode(clear_code, LZ_MAX_BITS);
|
result = OutputCode(clear_code, LZ_MAX_BITS);
|
||||||
|
if (result != B_OK) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
BITS = code_size + 1;
|
BITS = code_size + 1;
|
||||||
ResetHashtable();
|
ResetHashtable();
|
||||||
next_code = clear_code + 1;
|
next_code = clear_code + 1;
|
||||||
@@ -288,22 +394,55 @@ GIFSave::WriteGIFImageData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputCode(string_code, BITS);
|
result = OutputCode(string_code, BITS);
|
||||||
OutputCode(end_code, BITS);
|
if (result != B_OK) {
|
||||||
OutputCode(0, BITS, true);
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = OutputCode(end_code, BITS);
|
||||||
|
if (result != B_OK) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = OutputCode(0, BITS, true);
|
||||||
|
if (result != B_OK) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
char t = BLOCK_TERMINATOR;
|
char t = BLOCK_TERMINATOR;
|
||||||
output->Write(&t, 1);
|
if (output->Write(&t, 1) < 0) {
|
||||||
|
free(code_value);
|
||||||
|
free(prefix_code);
|
||||||
|
free(append_char);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
free(code_value);
|
free(code_value);
|
||||||
free(prefix_code);
|
free(prefix_code);
|
||||||
free(append_char);
|
free(append_char);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
GIFSave::OutputCode(short code, int BITS, bool flush)
|
GIFSave::OutputCode(short code, int BITS, bool flush)
|
||||||
{
|
{
|
||||||
if (!flush) {
|
if (!flush) {
|
||||||
bit_buffer |= (unsigned int) code << bit_count;
|
bit_buffer |= (unsigned int)code << bit_count;
|
||||||
bit_count += BITS;
|
bit_count += BITS;
|
||||||
while (bit_count >= 8) {
|
while (bit_count >= 8) {
|
||||||
byte_buffer[byte_count + 1] = (unsigned char)(bit_buffer & 0xff);
|
byte_buffer[byte_count + 1] = (unsigned char)(bit_buffer & 0xff);
|
||||||
@@ -313,7 +452,9 @@ GIFSave::OutputCode(short code, int BITS, bool flush)
|
|||||||
}
|
}
|
||||||
if (byte_count >= 255) {
|
if (byte_count >= 255) {
|
||||||
byte_buffer[0] = 255;
|
byte_buffer[0] = 255;
|
||||||
output->Write(byte_buffer, 256);
|
if (output->Write(byte_buffer, 256) < 0)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
if (byte_count == 256) {
|
if (byte_count == 256) {
|
||||||
byte_buffer[1] = byte_buffer[256];
|
byte_buffer[1] = byte_buffer[256];
|
||||||
byte_count = 1;
|
byte_count = 1;
|
||||||
@@ -331,9 +472,12 @@ GIFSave::OutputCode(short code, int BITS, bool flush)
|
|||||||
}
|
}
|
||||||
if (byte_count > 0) {
|
if (byte_count > 0) {
|
||||||
byte_buffer[0] = (unsigned char)byte_count;
|
byte_buffer[0] = (unsigned char)byte_count;
|
||||||
output->Write(byte_buffer, byte_count + 1);
|
if (output->Write(byte_buffer, byte_count + 1) < 0)
|
||||||
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ public:
|
|||||||
bool fatalerror;
|
bool fatalerror;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WriteGIFHeader();
|
status_t WriteGIFHeader();
|
||||||
void WriteGIFControlBlock();
|
status_t WriteGIFControlBlock();
|
||||||
void WriteGIFImageHeader();
|
status_t WriteGIFImageHeader();
|
||||||
void WriteGIFImageData();
|
status_t WriteGIFImageData();
|
||||||
void OutputCode(short code, int BITS,
|
status_t OutputCode(short code, int BITS,
|
||||||
bool flush = false);
|
bool flush = false);
|
||||||
|
|
||||||
unsigned char NextPixel(int pixel);
|
unsigned char NextPixel(int pixel);
|
||||||
|
|||||||
@@ -265,7 +265,13 @@ GIFTranslator::DerivedTranslate(BPositionIO* inSource,
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
GIFSave* gifSave = new GIFSave(bitmap, outDestination, fSettings);
|
GIFSave* gifSave = new(std::nothrow) GIFSave(bitmap, outDestination,
|
||||||
|
fSettings);
|
||||||
|
if (gifSave == NULL) {
|
||||||
|
delete bitmap;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if (gifSave->fatalerror) {
|
if (gifSave->fatalerror) {
|
||||||
delete gifSave;
|
delete gifSave;
|
||||||
delete bitmap;
|
delete bitmap;
|
||||||
@@ -275,7 +281,10 @@ GIFTranslator::DerivedTranslate(BPositionIO* inSource,
|
|||||||
delete bitmap;
|
delete bitmap;
|
||||||
} else {
|
} else {
|
||||||
// GIF to BBitmap
|
// GIF to BBitmap
|
||||||
GIFLoad* gifLoad = new GIFLoad(inSource, outDestination);
|
GIFLoad* gifLoad = new(std::nothrow) GIFLoad(inSource, outDestination);
|
||||||
|
if (gifLoad == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (gifLoad->fatalerror) {
|
if (gifLoad->fatalerror) {
|
||||||
delete gifLoad;
|
delete gifLoad;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -296,7 +305,7 @@ BTranslator*
|
|||||||
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
|
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
|
||||||
{
|
{
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return new GIFTranslator();
|
return new(std::nothrow) GIFTranslator();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -324,7 +333,7 @@ GIFTranslator::~GIFTranslator()
|
|||||||
BView*
|
BView*
|
||||||
GIFTranslator::NewConfigView(TranslatorSettings* settings)
|
GIFTranslator::NewConfigView(TranslatorSettings* settings)
|
||||||
{
|
{
|
||||||
return new GIFView(settings);
|
return new(std::nothrow) GIFView(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -332,7 +341,7 @@ int
|
|||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
BApplication app("application/x-vnd.Haiku-GIFTranslator");
|
BApplication app("application/x-vnd.Haiku-GIFTranslator");
|
||||||
status_t result = LaunchTranslatorWindow(new GIFTranslator,
|
status_t result = LaunchTranslatorWindow(new(std::nothrow) GIFTranslator,
|
||||||
B_TRANSLATE("GIF Settings"), kRectView);
|
B_TRANSLATE("GIF Settings"), kRectView);
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|||||||
Reference in New Issue
Block a user