Skip to content

Commit

Permalink
Cleanup and better safety checks, 2
Browse files Browse the repository at this point in the history
  • Loading branch information
aaaaaa123456789 committed Jan 19, 2022
1 parent 109d37e commit dc135bd
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 35 deletions.
22 changes: 11 additions & 11 deletions src/bmpread.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void load_BMP_bitmasks (struct context * context, size_t headersize, uint8_t * b
}

uint8_t * load_monochrome_BMP (struct context * context, size_t offset, int inverted) {
size_t rowsize = ((context -> image -> width + 31) >> 3) & ~3u;
size_t rowsize = ((context -> image -> width + 31) >> 3) & bitnegate(3);
size_t imagesize = rowsize * context -> image -> height;
if (imagesize > (context -> size - offset)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
uint8_t * frame = ctxmalloc(context, (size_t) context -> image -> width * context -> image -> height);
Expand Down Expand Up @@ -172,7 +172,7 @@ uint8_t * load_monochrome_BMP (struct context * context, size_t offset, int inve
}

uint8_t * load_halfbyte_BMP (struct context * context, size_t offset, int inverted) {
size_t rowsize = ((context -> image -> width + 7) >> 1) & ~3u;
size_t rowsize = ((context -> image -> width + 7) >> 1) & bitnegate(3);
size_t imagesize = rowsize * context -> image -> height;
if (imagesize > (context -> size - offset)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
uint8_t * frame = ctxmalloc(context, (size_t) context -> image -> width * context -> image -> height);
Expand All @@ -195,7 +195,7 @@ uint8_t * load_halfbyte_BMP (struct context * context, size_t offset, int invert
}

uint8_t * load_byte_BMP (struct context * context, size_t offset, int inverted) {
size_t rowsize = (context -> image -> width + 3) & ~3u;
size_t rowsize = (context -> image -> width + 3) & bitnegate(3);
size_t imagesize = rowsize * context -> image -> height;
if (imagesize > (context -> size - offset)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
uint8_t * frame = ctxmalloc(context, (size_t) context -> image -> width * context -> image -> height);
Expand Down Expand Up @@ -294,19 +294,19 @@ uint8_t * load_byte_compressed_BMP (struct context * context, size_t offset, int
break;
default:
if ((col + databyte) > context -> image -> width) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (remaining < ((1 + (size_t) databyte) & ~1)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (remaining < ((databyte + 1) & ~1u)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
memcpy(frame + (size_t) row * context -> image -> width + col, data, databyte);
col += databyte;
data += (databyte + 1) & ~1;
remaining -= (databyte + 1) & ~1;
data += (databyte + 1) & ~1u;
remaining -= (databyte + 1) & ~1u;
}
}
throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
}

uint64_t * load_BMP_pixels (struct context * context, size_t offset, int inverted, size_t bytes,
uint64_t (* loader) (const unsigned char *, const void *), const void * loaderdata) {
size_t rowsize = (context -> image -> width * bytes + 3) & ~3u;
size_t rowsize = (context -> image -> width * bytes + 3) & bitnegate(3);
size_t imagesize = rowsize * context -> image -> height;
if (imagesize > (context -> size - offset)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
const unsigned char * rowdata = context -> data + offset + (inverted ? rowsize * (context -> image -> height - 1) : 0);
Expand Down Expand Up @@ -342,9 +342,9 @@ uint64_t load_BMP_RGB_pixel (const unsigned char * data, const void * bitmasks)

uint64_t load_BMP_bitmasked_pixel (uint_fast32_t pixel, const uint8_t * bitmasks) {
uint64_t result = 0;
if (bitmasks[1]) result |= bitextend((pixel >> *bitmasks) & (((uint_fast32_t) 1 << bitmasks[1]) - 1), bitmasks[1]);
if (bitmasks[3]) result |= (uint64_t) bitextend((pixel >> bitmasks[2]) & (((uint_fast32_t) 1 << bitmasks[3]) - 1), bitmasks[3]) << 16;
if (bitmasks[5]) result |= (uint64_t) bitextend((pixel >> bitmasks[4]) & (((uint_fast32_t) 1 << bitmasks[5]) - 1), bitmasks[5]) << 32;
if (bitmasks[7]) result |= (~(uint64_t) bitextend((pixel >> bitmasks[6]) & (((uint_fast32_t) 1 << bitmasks[7]) - 1), bitmasks[7])) << 48;
if (bitmasks[1]) result |= bitextend((pixel >> *bitmasks) & (((uint64_t) 1 << bitmasks[1]) - 1), bitmasks[1]);
if (bitmasks[3]) result |= (uint64_t) bitextend((pixel >> bitmasks[2]) & (((uint64_t) 1 << bitmasks[3]) - 1), bitmasks[3]) << 16;
if (bitmasks[5]) result |= (uint64_t) bitextend((pixel >> bitmasks[4]) & (((uint64_t) 1 << bitmasks[5]) - 1), bitmasks[5]) << 32;
if (bitmasks[7]) result |= (~(uint64_t) bitextend((pixel >> bitmasks[6]) & (((uint64_t) 1 << bitmasks[7]) - 1), bitmasks[7])) << 48;
return result;
}
21 changes: 8 additions & 13 deletions src/bmpwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ void generate_BMP_data (struct context * context) {
if (context -> source -> frames > 1) throw(context, PLUM_ERR_NO_MULTI_FRAME);
if ((context -> source -> width > 0x7fffffffu) || (context -> source -> height > 0x7fffffffu)) throw(context, PLUM_ERR_IMAGE_TOO_LARGE);
unsigned char * header = append_output_node(context, 14);
*header = 0x42;
header[1] = 0x4d;
memset(header + 2, 0, 8);
bytewrite(header, 0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
uint32_t depth = get_true_color_depth(context -> source);
if (depth >= 0x1000000u)
generate_BMP_bitmasked_data(context, depth, header + 10);
else if (context -> source -> palette && (context -> source -> max_palette_index < 16))
generate_BMP_palette_halfbyte_data(context, header + 10);
else if (context -> source -> palette)
generate_BMP_palette_byte_data(context, header + 10);
else if (!bit_depth_less_than(depth, 0x80808u))
generate_BMP_bitmasked_data(context, depth, header + 10);
else
else if (bit_depth_less_than(depth, 0x80808u))
generate_BMP_RGB_data(context, header + 10);
else
generate_BMP_bitmasked_data(context, depth, header + 10);
size_t filesize = get_total_output_size(context);
if (filesize <= 0x7fffffffu) write_le32_unaligned(header + 2, filesize);
}
Expand Down Expand Up @@ -46,7 +44,7 @@ void generate_BMP_bitmasked_data (struct context * context, uint32_t depth, unsi
write_le32_unaligned(attributes + 4, context -> source -> width);
write_le32_unaligned(attributes + 8, context -> source -> height);
attributes[12] = 1;
attributes[14] = ((reddepth + greendepth + bluedepth + alphadepth) <= 16) ? 16 : 32;
attributes[14] = (p <= 16) ? 16 : 32;
attributes[16] = 3;
write_le32_unaligned(attributes + 40, ((uint32_t) 1 << reddepth) - 1);
write_le32_unaligned(attributes + 44, (((uint32_t) 1 << greendepth) - 1) << reddepth);
Expand Down Expand Up @@ -89,10 +87,7 @@ void generate_BMP_bitmasked_data (struct context * context, uint32_t depth, unsi
data += 4;
}
}
if ((attributes[14] == 16) && (context -> source -> width & 1)) {
write_le16_unaligned(data, 0);
data += 2;
}
if ((attributes[14] == 16) && (context -> source -> width & 1)) data += byteappend(data, 0x00, 0x00);
} while (row --);
}

Expand All @@ -108,7 +103,7 @@ void generate_BMP_palette_halfbyte_data (struct context * context, unsigned char
write_le32_unaligned(attributes + 32, context -> source -> max_palette_index + 1);
append_BMP_palette(context);
size_t rowsize = ((context -> source -> width + 7) & ~7u) >> 1;
if (context -> source -> max_palette_index < 2) rowsize = ((rowsize >> 2) + 3) & ~3u;
if (context -> source -> max_palette_index < 2) rowsize = ((rowsize >> 2) + 3) & bitnegate(3);
size_t imagesize = rowsize * context -> source -> height;
unsigned char * data = append_output_node(context, imagesize);
size_t compressed = try_compress_BMP(context, imagesize, &compress_BMP_halfbyte_row);
Expand Down Expand Up @@ -155,7 +150,7 @@ void generate_BMP_palette_byte_data (struct context * context, unsigned char * o
attributes[14] = 8;
write_le32_unaligned(attributes + 32, context -> source -> max_palette_index + 1);
append_BMP_palette(context);
size_t rowsize = (context -> source -> width + 3) & ~3u, imagesize = rowsize * context -> source -> height;
size_t rowsize = (context -> source -> width + 3) & bitnegate(3), imagesize = rowsize * context -> source -> height;
unsigned char * data = append_output_node(context, imagesize);
size_t compressed = try_compress_BMP(context, imagesize, &compress_BMP_byte_row);
if (compressed) {
Expand Down
5 changes: 5 additions & 0 deletions src/inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ static inline void ctxfree (struct context * context, void * buffer) {
deallocate(&(context -> allocator), buffer);
}

static inline uintmax_t bitnegate (uintmax_t value) {
// ensure that the value is negated correctly, without accidental unsigned-to-signed conversions getting in the way
return ~value;
}

static inline uint16_t bitextend (uint16_t value, unsigned width) {
uint_fast32_t result = value;
while (width < 16) {
Expand Down
8 changes: 4 additions & 4 deletions src/jpegread.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct JPEG_marker_layout * load_JPEG_marker_layout (struct context * context) {
if ((++ next_restart_marker) == 0xd8) next_restart_marker = 0xd0;
restart_offset = offset;
continue;
} else if ((marker & ~7) == 0xd0)
} else if ((marker & ~7u) == 0xd0)
throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
// if we find a marker other than RST, we're definitely ending the current scan, and the marker definitely has a size
if (next_restart_marker) {
Expand Down Expand Up @@ -247,7 +247,7 @@ unsigned char process_JPEG_metadata_until_offset (struct context * context, cons
switch (layout -> markertype[*index]) {
case 0xc4: // DHT
while (markersize) {
if (*markerdata & ~0x13) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (*markerdata & ~0x13u) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
unsigned char target = (*markerdata & 3) | (*markerdata >> 2);
markerdata ++;
markersize --;
Expand All @@ -259,7 +259,7 @@ unsigned char process_JPEG_metadata_until_offset (struct context * context, cons
if (markersize % 2) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
for (count = markersize / 2; count; count --) {
unsigned char destination = *(markerdata ++);
if (destination & ~0x13) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (destination & ~0x13u) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
destination = (destination >> 2) | (destination & 3);
if (destination & 4) {
if (!*markerdata || (*markerdata > 63)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
Expand All @@ -270,7 +270,7 @@ unsigned char process_JPEG_metadata_until_offset (struct context * context, cons
break;
case 0xdb: // DQT
while (markersize) {
if (*markerdata & ~0x13) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
if (*markerdata & ~0x13u) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
unsigned char target = *markerdata & 3, type = *markerdata >> 4, p = type ? 128 : 64;
markerdata ++;
if ((-- markersize) < p) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
Expand Down
14 changes: 7 additions & 7 deletions src/pnmread.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void load_PNM_header (struct context * context, size_t offset, struct PNM_image_
}

void load_PAM_header (struct context * context, size_t offset, struct PNM_image_header * restrict header) {
int fields = 15; // bits 0-3: width, height, max, depth
unsigned fields = 15; // bits 0-3: width, height, max, depth
uint32_t value, depth;
while (1) {
skip_PNM_line(context, &offset);
Expand All @@ -81,26 +81,26 @@ void load_PAM_header (struct context * context, size_t offset, struct PNM_image_
read_PNM_numbers(context, &offset, &value, 1);
if (!value) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
header -> width = value;
fields &= ~1;
fields &= ~1u;
} else if ((length == 6) && bytematch(context -> data + offset, 0x48, 0x45, 0x49, 0x47, 0x48, 0x54)) { // HEIGHT
offset += 6;
if (!(fields & 2)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
read_PNM_numbers(context, &offset, &value, 1);
if (!value) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
header -> height = value;
fields &= ~2;
fields &= ~2u;
} else if ((length == 6) && bytematch(context -> data + offset, 0x4d, 0x41, 0x58, 0x56, 0x41, 0x4c)) { // MAXVAL
offset += 6;
if (!(fields & 4)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
read_PNM_numbers(context, &offset, &value, 1);
if (!value || (value > 0xffffu)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
header -> maxvalue = value;
fields &= ~4;
fields &= ~4u;
} else if ((length == 5) && bytematch(context -> data + offset, 0x44, 0x45, 0x50, 0x54, 0x48)) { // DEPTH
offset += 5;
if (!(fields & 8)) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
read_PNM_numbers(context, &offset, &depth, 1);
fields &= ~8;
fields &= ~8u;
} else if ((length == 8) && bytematch(context -> data + offset, 0x54, 0x55, 0x50, 0x4c, 0x54, 0x59, 0x50, 0x45)) { // TUPLTYPE
if (header -> type != 7) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
offset += 8;
Expand Down Expand Up @@ -214,7 +214,7 @@ void load_PNM_frame (struct context * context, const struct PNM_image_header * h
switch (header -> type) {
case 1:
// sometimes the 0s and 1s are not delimited at all here, so it needs a special parser
while ((offset < (context -> size)) && ((context -> data[offset] & ~1) != 0x30)) offset ++;
while ((offset < (context -> size)) && ((context -> data[offset] & ~1u) != 0x30)) offset ++;
if (offset >= context -> size) throw(context, PLUM_ERR_INVALID_FILE_FORMAT);
values[2] = values[1] = *values = ~context -> data[offset ++] & 1;
break;
Expand Down Expand Up @@ -267,7 +267,7 @@ void load_PNM_bit_frame (struct context * context, size_t width, size_t height,
for (row = 0; row < height; row ++) {
uint_fast8_t value, bit;
size_t p = (size_t) context -> image -> width * row;
for (col = 0; col < (width & ~7); col += 8) {
for (col = 0; col < (width & bitnegate(7)); col += 8) {
value = context -> data[offset ++];
for (bit = 0; bit < 8; bit ++) {
buffer[p ++] = (value & 0x80) ? 0xffff000000000000u : 0xffffffffffffffffu;
Expand Down

0 comments on commit dc135bd

Please sign in to comment.