1 /*
2  * pngxmem.c - libpng extension: memory allocation utilities.
3  *
4  * Copyright (C) 2003-2017 Cosmin Truta.
5  * This software is distributed under the same licensing and warranty terms
6  * as libpng.
7  */
8 
9 #include "pngxutil.h"
10 #include <string.h>
11 
12 
13 #ifdef PNG_INFO_IMAGE_SUPPORTED
14 
15 
16 png_bytepp PNGAPI
pngx_malloc_rows(png_structp png_ptr,png_infop info_ptr,int filler)17 pngx_malloc_rows(png_structp png_ptr, png_infop info_ptr, int filler)
18 {
19    return pngx_malloc_rows_extended(png_ptr, info_ptr, 0, filler);
20 }
21 
22 png_bytepp PNGAPI
pngx_malloc_rows_extended(png_structp png_ptr,png_infop info_ptr,pngx_alloc_size_t min_row_size,int filler)23 pngx_malloc_rows_extended(png_structp png_ptr, png_infop info_ptr,
24    pngx_alloc_size_t min_row_size, int filler)
25 {
26    pngx_alloc_size_t row_size;
27    png_bytep row;
28    png_bytepp rows;
29    png_uint_32 height, i;
30 
31    /* Check the image dimensions and calculate the row size. */
32    height = png_get_image_height(png_ptr, info_ptr);
33    if (height == 0)
34       png_error(png_ptr, "Missing IHDR");
35    row_size = png_get_rowbytes(png_ptr, info_ptr);
36    /* libpng sets row_size to 0 when the width is too large to process. */
37    if (row_size == 0 ||
38        (pngx_alloc_size_t)height > (pngx_alloc_size_t)(-1U) / sizeof(png_bytep))
39       png_error(png_ptr, "Can't handle exceedingly large image dimensions");
40    if (row_size < min_row_size)
41       row_size = min_row_size;
42 
43    /* Deallocate the currently-existing rows. */
44    png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
45 
46    /* Allocate memory for the row index. */
47    rows = (png_bytepp)png_malloc(png_ptr,
48       (pngx_alloc_size_t)(height * sizeof(png_bytep)));
49    if (rows == NULL)
50       return NULL;
51 
52    /* Allocate memory for each row. */
53    for (i = 0; i < height; ++i)
54    {
55       row = (png_bytep)png_malloc(png_ptr, row_size);
56       if (row == NULL)
57       {
58          /* Release the memory allocated up to the point of failure. */
59          while (i > 0)
60             png_free(png_ptr, rows[--i]);
61          png_free(png_ptr, rows);
62          return NULL;
63       }
64       if (filler >= 0)
65          memset(row, filler, row_size);
66       rows[i] = row;
67    }
68 
69    /* Set the row pointers. */
70    png_set_rows(png_ptr, info_ptr, rows);
71    return rows;
72 }
73 
74 #if 0  /* not necessary */
75 void PNGAPI
76 pngx_free_rows(png_structp png_ptr, png_infop info_ptr)
77 {
78    png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
79 }
80 #endif
81 
82 
83 #endif /* PNG_INFO_IMAGE_SUPPORTED */
84