1
0
mirror of https://git.code.sf.net/p/zint/code synced 2025-12-17 18:07:02 +00:00

- raster/BMP/GIF/PCX/TIF: fix dealing with very large data (use

`size_t` as appropriate)
- BMP: lessen heap memory usage by only `malloc()`ing a row, not
  whole file
- GIF: lessen heap memory usage by paging (also simplifies some
  function returns); use standard colour char map
- raster: add `raster_malloc()` to fail > 1GB (avoids very large
  output files that most systems can't handle; also lessens to
  some degree chances of being victim of OOM killer on Linux)
- GUI: printing scale dialog: set maxima on X-dim and resolution
  to keep scale <= 200
This commit is contained in:
gitlost
2023-12-22 21:29:54 +00:00
parent 6ff485e6fa
commit 070162214b
27 changed files with 354 additions and 370 deletions

View File

@@ -63,6 +63,17 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
static const char ultra_colour[] = "0CBMRYGKW";
/* Wrapper to pre-check `size` on `malloc()` isn't too big (`size2` given if doing X `malloc()`s in a row) */
static void *raster_malloc(size_t size, size_t size2) {
/* Check for large image `malloc`s, which produce very large files most systems can't handle anyway */
/* Also `malloc()` on Linux will (usually) succeed regardless of request, and then get untrappably killed on
access by OOM killer if too much, so this is a crude mitigation */
if (size + size2 > 0x40000000) { /* 1GB */
return NULL;
}
return malloc(size);
}
static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) {
/* Place pixelbuffer into symbol */
unsigned char alpha[2];
@@ -80,6 +91,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
int row;
int plot_alpha = 0;
const size_t bm_bitmap_width = (size_t) symbol->bitmap_width * 3;
const size_t bm_bitmap_size = bm_bitmap_width * symbol->bitmap_height;
if (out_colour_get_rgb(symbol->fgcolour, &map[DEFAULT_INK][0], &map[DEFAULT_INK][1], &map[DEFAULT_INK][2],
&alpha[0])) {
@@ -100,27 +112,28 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
symbol->alphamap = NULL;
}
symbol->bitmap = (unsigned char *) malloc(bm_bitmap_width * symbol->bitmap_height);
symbol->bitmap = (unsigned char *) raster_malloc(bm_bitmap_size, 0);
if (symbol->bitmap == NULL) {
strcpy(symbol->errtxt, "661: Insufficient memory for bitmap buffer");
return ZINT_ERROR_MEMORY;
}
if (plot_alpha) {
symbol->alphamap = (unsigned char *) malloc((size_t) symbol->bitmap_width * symbol->bitmap_height);
const size_t alpha_size = (size_t) symbol->bitmap_width * symbol->bitmap_height;
symbol->alphamap = (unsigned char *) raster_malloc(alpha_size, bm_bitmap_size);
if (symbol->alphamap == NULL) {
strcpy(symbol->errtxt, "662: Insufficient memory for alphamap buffer");
return ZINT_ERROR_MEMORY;
}
for (row = 0; row < symbol->bitmap_height; row++) {
int p = row * symbol->bitmap_width;
size_t p = (size_t) symbol->bitmap_width * row;
const unsigned char *pb = pixelbuf + p;
unsigned char *bitmap = symbol->bitmap + p * 3;
if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
memcpy(bitmap, bitmap - bm_bitmap_width, bm_bitmap_width);
memcpy(symbol->alphamap + p, symbol->alphamap + p - symbol->bitmap_width, symbol->bitmap_width);
} else {
const int pe = p + symbol->bitmap_width;
const size_t pe = p + symbol->bitmap_width;
for (; p < pe; p++, bitmap += 3) {
memcpy(bitmap, map[pixelbuf[p]], 3);
symbol->alphamap[p] = alpha[pixelbuf[p] == DEFAULT_PAPER];
@@ -129,7 +142,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
}
} else {
for (row = 0; row < symbol->bitmap_height; row++) {
const int r = row * symbol->bitmap_width;
const size_t r = (size_t) symbol->bitmap_width * row;
const unsigned char *pb = pixelbuf + r;
unsigned char *bitmap = symbol->bitmap + r * 3;
if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
@@ -169,7 +182,7 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
}
if (rotate_angle) {
if (!(rotated_pixbuf = (unsigned char *) malloc((size_t) image_width * image_height))) {
if (!(rotated_pixbuf = (unsigned char *) raster_malloc((size_t) image_width * image_height, 0 /*size2*/))) {
strcpy(symbol->errtxt, "650: Insufficient memory for pixel buffer");
return ZINT_ERROR_MEMORY;
}
@@ -182,25 +195,28 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
break;
case 90: /* Plot 90 degrees clockwise */
for (row = 0; row < image_width; row++) {
const size_t h_offset = (size_t) image_height * row;
for (column = 0; column < image_height; column++) {
rotated_pixbuf[(row * image_height) + column] =
*(pixelbuf + (image_width * (image_height - column - 1)) + row);
const size_t w_offset = (size_t) image_width * (image_height - column - 1);
rotated_pixbuf[h_offset + column] = *(pixelbuf + w_offset + row);
}
}
break;
case 180: /* Plot upside down */
for (row = 0; row < image_height; row++) {
const size_t w_offset = (size_t) image_width * row;
const size_t wh_offset = (size_t) image_width * (image_height - row - 1);
for (column = 0; column < image_width; column++) {
rotated_pixbuf[(row * image_width) + column] =
*(pixelbuf + (image_width * (image_height - row - 1)) + (image_width - column - 1));
rotated_pixbuf[w_offset + column] = *(pixelbuf + wh_offset + (image_width - column - 1));
}
}
break;
case 270: /* Plot 90 degrees anti-clockwise */
for (row = 0; row < image_width; row++) {
const size_t h_offset = (size_t) image_height * row;
for (column = 0; column < image_height; column++) {
rotated_pixbuf[(row * image_height) + column] =
*(pixelbuf + (image_width * column) + (image_width - row - 1));
const size_t w_offset = (size_t) image_width * column;
rotated_pixbuf[h_offset + column] = *(pixelbuf + w_offset + (image_width - row - 1));
}
}
break;
@@ -713,12 +729,14 @@ static void draw_bind_box(const struct zint_symbol *symbol, unsigned char *pixel
static int plot_raster_maxicode(struct zint_symbol *symbol, const int rotate_angle, const int file_type) {
int row, column;
int image_height, image_width;
size_t image_size;
unsigned char *pixelbuf;
int error_number;
float xoffset, yoffset, roffset, boffset;
float scaler = symbol->scale;
unsigned char *scaled_hexagon;
int hex_width, hex_height;
size_t hex_size;
int hx_start, hy_start, hx_end, hy_end;
int hex_image_width, hex_image_height;
int yposn_offset;
@@ -758,19 +776,21 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, const int rotate_ang
image_width = (int) ceilf(hex_image_width + xoffset_si + roffset_si);
image_height = (int) ceilf(hex_image_height + yoffset_si + boffset_si);
assert(image_width && image_height);
image_size = (size_t) image_width * image_height;
if (!(pixelbuf = (unsigned char *) malloc((size_t) image_width * image_height))) {
if (!(pixelbuf = (unsigned char *) raster_malloc(image_size, 0 /*size*/))) {
strcpy(symbol->errtxt, "655: Insufficient memory for pixel buffer");
return ZINT_ERROR_MEMORY;
}
memset(pixelbuf, DEFAULT_PAPER, (size_t) image_width * image_height);
memset(pixelbuf, DEFAULT_PAPER, image_size);
if (!(scaled_hexagon = (unsigned char *) malloc((size_t) hex_width * hex_height))) {
hex_size = (size_t) hex_width * hex_height;
if (!(scaled_hexagon = (unsigned char *) raster_malloc(hex_size, image_size))) {
strcpy(symbol->errtxt, "656: Insufficient memory for pixel buffer");
free(pixelbuf);
return ZINT_ERROR_MEMORY;
}
memset(scaled_hexagon, DEFAULT_PAPER, (size_t) hex_width * hex_height);
memset(scaled_hexagon, DEFAULT_PAPER, hex_size);
plot_hexagon(scaled_hexagon, hex_width, hex_height, hx_start, hy_start, hx_end, hy_end);
@@ -814,6 +834,7 @@ static int plot_raster_dotty(struct zint_symbol *symbol, const int rotate_angle,
unsigned char *scaled_pixelbuf;
int r, i;
int scale_width, scale_height;
size_t scale_size;
int error_number = 0;
float xoffset, yoffset, roffset, boffset;
float dot_offset_s;
@@ -848,13 +869,14 @@ static int plot_raster_dotty(struct zint_symbol *symbol, const int rotate_angle,
scale_width = (int) (symbol->width * scaler + xoffset_si + roffset_si + dot_overspill_si);
scale_height = (int) (symbol_height_si + yoffset_si + boffset_si + dot_overspill_si);
scale_size = (size_t) scale_width * scale_height;
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (unsigned char *) malloc((size_t) scale_width * scale_height))) {
/* Apply scale options by creating pixel buffer */
if (!(scaled_pixelbuf = (unsigned char *) raster_malloc(scale_size, 0 /*size2*/))) {
strcpy(symbol->errtxt, "657: Insufficient memory for pixel buffer");
return ZINT_ERROR_MEMORY;
}
memset(scaled_pixelbuf, DEFAULT_PAPER, (size_t) scale_width * scale_height);
memset(scaled_pixelbuf, DEFAULT_PAPER, scale_size);
/* Plot the body of the symbol to the pixel buffer */
for (r = 0; r < symbol->rows; r++) {
@@ -946,6 +968,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
int row_heights_si[200];
int symbol_height_si;
int image_width, image_height;
size_t image_size;
unsigned char *pixelbuf;
float scaler = symbol->scale;
int si;
@@ -1013,12 +1036,13 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
image_height = symbol_height_si + (int) ceilf(textoffset * si) + yoffset_si + boffset_si;
assert(image_width && image_height);
image_size = (size_t) image_width * image_height;
if (!(pixelbuf = (unsigned char *) malloc((size_t) image_width * image_height))) {
if (!(pixelbuf = (unsigned char *) raster_malloc(image_size, 0 /*size2*/))) {
strcpy(symbol->errtxt, "658: Insufficient memory for pixel buffer");
return ZINT_ERROR_MEMORY;
}
memset(pixelbuf, DEFAULT_PAPER, (size_t) image_width * image_height);
memset(pixelbuf, DEFAULT_PAPER, image_size);
yposn_si = yoffset_si;
@@ -1341,7 +1365,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
const int scale_height = (int) stripf(image_height * scaler);
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (unsigned char *) malloc((size_t) scale_width * scale_height))) {
if (!(scaled_pixelbuf = (unsigned char *) raster_malloc((size_t) scale_width * scale_height, image_size))) {
free(pixelbuf);
strcpy(symbol->errtxt, "659: Insufficient memory for scaled pixel buffer");
return ZINT_ERROR_MEMORY;
@@ -1350,7 +1374,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
/* Interpolate */
for (r = 0; r < scale_height; r++) {
size_t scaled_row = r * scale_width;
size_t scaled_row = (size_t) scale_width * r;
size_t image_row = (size_t) stripf(r / scaler) * image_width;
if (r && (image_row == prev_image_row
|| memcmp(pixelbuf + image_row, pixelbuf + prev_image_row, image_width) == 0)) {