Skip to content

Commit

Permalink
Cleanup and better safety checks, 3
Browse files Browse the repository at this point in the history
  • Loading branch information
aaaaaa123456789 committed Jan 19, 2022
1 parent dc135bd commit 41f87cc
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 70 deletions.
82 changes: 27 additions & 55 deletions src/bmpwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,7 @@ size_t compress_BMP_halfbyte_row (uint8_t * result, const uint8_t * data, size_t
if ((*data == data[2]) && (data[1] == data[3])) {
uint_fast8_t length;
for (length = 4; (length < 0xff) && (length < count) && (data[length] == data[length - 2]); length ++);
*(result ++) = length;
*(result ++) = (*data << 4) | data[1];
result += byteappend(result, length, (*data << 4) | data[1]);
size += 2;
data += length;
count -= length;
Expand All @@ -213,32 +212,21 @@ size_t compress_BMP_halfbyte_row (uint8_t * result, const uint8_t * data, size_t
}
while (length > 2) {
uint_fast8_t block = (length > 0xff) ? 0xfc : length;
*(result ++) = 0;
*(result ++) = block;
result += byteappend(result, 0, block);
size += (block + 7) >> 2 << 1;
length -= block;
count -= block;
while (block >= 4) {
*(result ++) = (*data << 4) | data[1];
*(result ++) = (data[2] << 4) | data[3];
result += byteappend(result, (*data << 4) | data[1], (data[2] << 4) | data[3]);
data += 4;
block -= 4;
}
switch (block) {
case 1:
*(result ++) = *(data ++) << 4;
*(result ++) = 0;
break;
case 2:
*(result ++) = (*data << 4) | data[1];
*(result ++) = 0;
data += 2;
break;
case 3:
*(result ++) = (*data << 4) | data[1];
data += 2;
*(result ++) = *(data ++) << 4;
case 1: result += byteappend(result, *data << 4, 0); break;
case 2: result += byteappend(result, (*data << 4) | data[1], 0); break;
case 3: result += byteappend(result, (*data << 4) | data[1], data[2] << 4);
}
data += block;
}
matches = emit_BMP_compressed_halfbyte_remainder(result, data, length);
result += matches;
Expand All @@ -254,22 +242,19 @@ size_t compress_BMP_halfbyte_row (uint8_t * result, const uint8_t * data, size_t
unsigned emit_BMP_compressed_halfbyte_remainder (uint8_t * result, const uint8_t * data, unsigned count) {
switch (count) {
case 1:
*(result ++) = 1;
*result = *data << 4;
bytewrite(result, 1, *data << 4);
return 2;
case 2:
*(result ++) = 2;
*result = (*data << 4) | data[1];
bytewrite(result, 2, (*data << 4) | data[1]);
return 2;
case 3:
*(result ++) = 2 + (*data == data[2]);
*(result ++) = (*data << 4) | data[1];
result += byteappend(result, 2 + (*data == data[2]), (*data << 4) | data[1]);
if (*data == data[2]) return 2;
*(result ++) = 1;
*result = data[2] << 4;
bytewrite(result, 1, data[2] << 4);
return 4;
default:
return 0;
}
return 0;
}

size_t compress_BMP_byte_row (uint8_t * result, const uint8_t * data, size_t count) {
Expand All @@ -278,8 +263,7 @@ size_t compress_BMP_byte_row (uint8_t * result, const uint8_t * data, size_t cou
if (*data == data[1]) {
uint_fast8_t length;
for (length = 2; (length < 0xff) && (length < count) && (*data == data[length]); length ++);
*(result ++) = length;
*(result ++) = *data;
result += byteappend(result, length, *data);
size += 2;
data += length;
count -= length;
Expand All @@ -298,8 +282,7 @@ size_t compress_BMP_byte_row (uint8_t * result, const uint8_t * data, size_t cou
}
while (length > 2) {
uint_fast8_t block = (length > 0xff) ? 0xfe : length;
*(result ++) = 0;
*(result ++) = block;
result += byteappend(result, 0, block);
memcpy(result, data, block);
result += block;
data += block;
Expand All @@ -312,27 +295,25 @@ size_t compress_BMP_byte_row (uint8_t * result, const uint8_t * data, size_t cou
}
}
if (length == 2) {
count -= 1 + (*data == data[1]);
length -= 1 + (*data == data[1]);
*(result ++) = 1 + (*data == data[1]);
if (*data == data[1]) data ++;
*(result ++) = *(data ++);
matches = 1 + (*data == data[1]);
result += byteappend(result, matches, *data);
size += 2;
data += matches;
count -= matches;
length -= matches;
}
if (length == 1) {
*(result ++) = 1;
*(result ++) = *(data ++);
result += byteappend(result, 1, *data);
data ++;
size += 2;
count -= 1;
count --;
}
}
if (count == 1) {
*(result ++) = 1;
*(result ++) = *data;
result += byteappend(result, 1, *data);
size += 2;
}
*(result ++) = 0;
*result = 0;
bytewrite(result, 0, 0);
return size;
}

Expand All @@ -341,12 +322,7 @@ void append_BMP_palette (struct context * context) {
uint32_t * colors = ctxmalloc(context, sizeof *colors * (context -> source -> max_palette_index + 1));
plum_convert_colors(colors, context -> source -> palette, context -> source -> max_palette_index + 1, PLUM_COLOR_32, context -> source -> color_format);
unsigned pos;
for (pos = 0; pos <= context -> source -> max_palette_index; pos ++) {
*(data ++) = colors[pos] >> 16;
*(data ++) = colors[pos] >> 8;
*(data ++) = colors[pos];
*(data ++) = 0;
}
for (pos = 0; pos <= context -> source -> max_palette_index; pos ++) data += byteappend(data, colors[pos] >> 16, colors[pos] >> 8, colors[pos], 0);
ctxfree(context, colors);
}

Expand Down Expand Up @@ -375,11 +351,7 @@ void generate_BMP_RGB_data (struct context * context, unsigned char * offset_poi
uint_fast32_t remaining, row = context -> source -> height - 1;
do {
size_t pos = (size_t) row * context -> source -> width;
for (remaining = context -> source -> width; remaining; pos ++, remaining --) {
*(out ++) = data[pos] >> 16;
*(out ++) = data[pos] >> 8;
*(out ++) = data[pos];
}
for (remaining = context -> source -> width; remaining; pos ++, remaining --) out += byteappend(out, data[pos] >> 16, data[pos] >> 8, data[pos]);
for (remaining = padding; remaining; remaining --) *(out ++) = 0;
} while (row --);
if (data != context -> source -> data) ctxfree(context, data);
Expand Down
2 changes: 1 addition & 1 deletion src/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,5 @@ uint32_t get_true_color_depth (const struct plum_image * image) {
if (green > 16) green = 16;
if (blue > 16) blue = 16;
if (alpha > 16) alpha = 16;
return ((uint32_t) red) | ((uint32_t) green << 8) | ((uint32_t) blue << 16) | ((uint32_t) alpha << 24);
return (uint32_t) red | ((uint32_t) green << 8) | ((uint32_t) blue << 16) | ((uint32_t) alpha << 24);
}
4 changes: 2 additions & 2 deletions src/framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ void allocate_framebuffers (struct context * context, unsigned flags, int palett
}

void write_framebuffer_to_image (struct plum_image * image, const uint64_t * framebuffer, uint32_t frame, unsigned flags) {
size_t framesize = plum_color_buffer_size((size_t) image -> width * image -> height, flags);
plum_convert_colors(image -> data8 + framesize * frame, framebuffer, (size_t) image -> width * image -> height, flags, PLUM_COLOR_64);
size_t pixels = (size_t) image -> width * image -> height, framesize = plum_color_buffer_size(pixels, flags);
plum_convert_colors(image -> data8 + framesize * frame, framebuffer, pixels, flags, PLUM_COLOR_64);
}

void write_palette_framebuffer_to_image (struct context * context, const uint8_t * framebuffer, const uint64_t * palette, uint32_t frame, unsigned flags,
Expand Down
25 changes: 13 additions & 12 deletions src/gifread.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ void load_GIF_data (struct context * context, unsigned flags, size_t limit) {
context -> image -> height = read_le16_unaligned(context -> data + 8);
size_t offset = 13;
uint64_t transparent = 0xffff000000000000u;
// note: load_GIF_palettes also initializes context -> image -> frames (and context -> image -> palette) and validates the image's structure
uint64_t ** palettes = load_GIF_palettes(context, flags, &offset, &transparent); // will be leaked (collected at the end)
validate_image_size(context, limit);
load_GIF_loop_count(context, &offset);
Expand Down Expand Up @@ -59,8 +60,8 @@ uint64_t ** load_GIF_palettes (struct context * context, unsigned flags, size_t
skip_GIF_data_blocks(context, &scan_offset);
} break;
case 0x2c: {
if (scan_offset > (context -> size - 9)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
scan_offset += 9;
if (scan_offset > context -> size) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
context -> image -> frames ++;
if (!(context -> image -> frames)) throw(context, PLUM_ERR_IMAGE_TOO_LARGE);
int smaller_size = read_le16_unaligned(context -> data + scan_offset - 9) || read_le16_unaligned(context -> data + scan_offset - 7) ||
Expand Down Expand Up @@ -132,20 +133,20 @@ uint64_t ** load_GIF_palettes (struct context * context, unsigned flags, size_t
}
throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
done:
if (!(context -> image -> frames)) throw(context, PLUM_ERR_NO_DATA);
if (!context -> image -> frames) throw(context, PLUM_ERR_NO_DATA);
if (!result) {
if (transparent_index < global_palette_size) global_palette[transparent_index] = *transparent_color;
context -> image -> max_palette_index = global_palette_size - 1;
context -> image -> palette = plum_malloc(context -> image, plum_color_buffer_size(global_palette_size, flags));
if (!(context -> image -> palette)) throw(context, PLUM_ERR_OUT_OF_MEMORY);
if (!context -> image -> palette) throw(context, PLUM_ERR_OUT_OF_MEMORY);
plum_convert_colors(context -> image -> palette, global_palette, global_palette_size, flags, PLUM_COLOR_64);
}
ctxfree(context, global_palette);
return result;
}

void load_GIF_palette (struct context * context, uint64_t * palette, size_t * offset, unsigned size) {
if ((*offset + 3 * size) > context -> size) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if ((3 * size) > (context -> size - *offset)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
uint64_t color;
while (size --) {
color = context -> data[(*offset) ++];
Expand Down Expand Up @@ -175,21 +176,21 @@ void * load_GIF_data_blocks (struct context * context, size_t * restrict offset,
}

void skip_GIF_data_blocks (struct context * context, size_t * offset) {
while (*offset < context -> size) {
uint8_t skip = context -> data[(*offset) ++];
if (!skip) return;
uint_fast8_t skip;
do {
if (*offset >= context -> size) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
skip = context -> data[(*offset) ++];
if ((context -> size < skip) || (*offset > (context -> size - skip))) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
*offset += skip;
}
throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
} while (skip);
}

void load_GIF_loop_count (struct context * context, size_t * offset) {
if (((*offset + 2) >= context -> size) || (context -> data[*offset] != 0x21) || (context -> data[*offset + 1] != 0xff)) {
if ((*offset >= (context -> size - 2)) || (context -> data[*offset] != 0x21) || (context -> data[*offset + 1] != 0xff)) {
add_loop_count_metadata(context, 1);
return;
}
size_t newoffset = *offset + 2;
size_t size;
size_t size, newoffset = *offset + 2;
unsigned char * data = load_GIF_data_blocks(context, &newoffset, &size);
if ((size == 14) && bytematch(data, 0x4e, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30, 0x01)) {
add_loop_count_metadata(context, read_le16_unaligned(data + 12));
Expand Down

0 comments on commit 41f87cc

Please sign in to comment.