| OLD | NEW | 
|     1  |     1  | 
|     2 /* pngset.c - storage of image information into info struct |     2 /* pngset.c - storage of image information into info struct | 
|     3  * |     3  * | 
|     4  * Last changed in libpng 1.2.43 [February 25, 2010] |     4  * Last changed in libpng 1.6.3 [July 18, 2013] | 
|     5  * Copyright (c) 1998-2010 Glenn Randers-Pehrson |     5  * Copyright (c) 1998-2013 Glenn Randers-Pehrson | 
|     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 
|     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 
|     8  * |     8  * | 
|     9  * This code is released under the libpng license. |     9  * This code is released under the libpng license. | 
|    10  * For conditions of distribution and use, see the disclaimer |    10  * For conditions of distribution and use, see the disclaimer | 
|    11  * and license in png.h |    11  * and license in png.h | 
|    12  * |    12  * | 
|    13  * The functions here are used during reads to store data from the file |    13  * The functions here are used during reads to store data from the file | 
|    14  * into the info struct, and during writes to store application data |    14  * into the info struct, and during writes to store application data | 
|    15  * into the info struct for writing into the file.  This abstracts the |    15  * into the info struct for writing into the file.  This abstracts the | 
|    16  * info struct and allows us to change the structure in the future. |    16  * info struct and allows us to change the structure in the future. | 
|    17  */ |    17  */ | 
|    18  |    18  | 
|    19 #define PNG_INTERNAL |    19 #include "pngpriv.h" | 
|    20 #define PNG_NO_PEDANTIC_WARNINGS |    20  | 
|    21 #include "png.h" |  | 
|    22 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) |    21 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) | 
|    23  |    22  | 
|    24 #ifdef PNG_bKGD_SUPPORTED |    23 #ifdef PNG_bKGD_SUPPORTED | 
|    25 void PNGAPI |    24 void PNGAPI | 
|    26 png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) |    25 png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |    26     png_const_color_16p background) | 
|    27 { |    27 { | 
|    28    png_debug1(1, "in %s storage function", "bKGD"); |    28    png_debug1(1, "in %s storage function", "bKGD"); | 
|    29  |    29  | 
|    30    if (png_ptr == NULL || info_ptr == NULL) |    30    if (png_ptr == NULL || info_ptr == NULL || background == NULL) | 
|    31       return; |    31       return; | 
|    32  |    32  | 
|    33    png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); |    33    info_ptr->background = *background; | 
|    34    info_ptr->valid |= PNG_INFO_bKGD; |    34    info_ptr->valid |= PNG_INFO_bKGD; | 
|    35 } |    35 } | 
|    36 #endif |    36 #endif | 
|    37  |    37  | 
|    38 #ifdef PNG_cHRM_SUPPORTED |    38 #ifdef PNG_cHRM_SUPPORTED | 
|    39 #ifdef PNG_FLOATING_POINT_SUPPORTED |    39 void PNGFAPI | 
|    40 void PNGAPI |    40 png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr, | 
|    41 png_set_cHRM(png_structp png_ptr, png_infop info_ptr, |    41     png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, | 
|    42    double white_x, double white_y, double red_x, double red_y, |    42     png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, | 
|    43    double green_x, double green_y, double blue_x, double blue_y) |    43     png_fixed_point blue_x, png_fixed_point blue_y) | 
|    44 { |    44 { | 
|    45    png_debug1(1, "in %s storage function", "cHRM"); |    45    png_xy xy; | 
|    46  |    46  | 
|    47    if (png_ptr == NULL || info_ptr == NULL) |  | 
|    48       return; |  | 
|    49  |  | 
|    50    info_ptr->x_white = (float)white_x; |  | 
|    51    info_ptr->y_white = (float)white_y; |  | 
|    52    info_ptr->x_red   = (float)red_x; |  | 
|    53    info_ptr->y_red   = (float)red_y; |  | 
|    54    info_ptr->x_green = (float)green_x; |  | 
|    55    info_ptr->y_green = (float)green_y; |  | 
|    56    info_ptr->x_blue  = (float)blue_x; |  | 
|    57    info_ptr->y_blue  = (float)blue_y; |  | 
|    58 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|    59    info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); |  | 
|    60    info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); |  | 
|    61    info_ptr->int_x_red   = (png_fixed_point)(  red_x*100000.+0.5); |  | 
|    62    info_ptr->int_y_red   = (png_fixed_point)(  red_y*100000.+0.5); |  | 
|    63    info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); |  | 
|    64    info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); |  | 
|    65    info_ptr->int_x_blue  = (png_fixed_point)( blue_x*100000.+0.5); |  | 
|    66    info_ptr->int_y_blue  = (png_fixed_point)( blue_y*100000.+0.5); |  | 
|    67 #endif |  | 
|    68    info_ptr->valid |= PNG_INFO_cHRM; |  | 
|    69 } |  | 
|    70 #endif /* PNG_FLOATING_POINT_SUPPORTED */ |  | 
|    71  |  | 
|    72 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|    73 void PNGAPI |  | 
|    74 png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, |  | 
|    75    png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, |  | 
|    76    png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, |  | 
|    77    png_fixed_point blue_x, png_fixed_point blue_y) |  | 
|    78 { |  | 
|    79    png_debug1(1, "in %s storage function", "cHRM fixed"); |    47    png_debug1(1, "in %s storage function", "cHRM fixed"); | 
|    80  |    48  | 
|    81    if (png_ptr == NULL || info_ptr == NULL) |    49    if (png_ptr == NULL || info_ptr == NULL) | 
|    82       return; |    50       return; | 
|    83  |    51  | 
|    84 #ifdef PNG_CHECK_cHRM_SUPPORTED |    52    xy.redx = red_x; | 
|    85    if (png_check_cHRM_fixed(png_ptr, |    53    xy.redy = red_y; | 
|    86       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) |    54    xy.greenx = green_x; | 
|    87 #endif |    55    xy.greeny = green_y; | 
|    88    { |    56    xy.bluex = blue_x; | 
|    89       info_ptr->int_x_white = white_x; |    57    xy.bluey = blue_y; | 
|    90       info_ptr->int_y_white = white_y; |    58    xy.whitex = white_x; | 
|    91       info_ptr->int_x_red   = red_x; |    59    xy.whitey = white_y; | 
|    92       info_ptr->int_y_red   = red_y; |    60  | 
|    93       info_ptr->int_x_green = green_x; |    61    if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy, | 
|    94       info_ptr->int_y_green = green_y; |    62       2/* override with app values*/)) | 
|    95       info_ptr->int_x_blue  = blue_x; |    63       info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; | 
|    96       info_ptr->int_y_blue  = blue_y; |    64  | 
|    97 #ifdef  PNG_FLOATING_POINT_SUPPORTED |    65    png_colorspace_sync_info(png_ptr, info_ptr); | 
|    98       info_ptr->x_white = (float)(white_x/100000.); |  | 
|    99       info_ptr->y_white = (float)(white_y/100000.); |  | 
|   100       info_ptr->x_red   = (float)(  red_x/100000.); |  | 
|   101       info_ptr->y_red   = (float)(  red_y/100000.); |  | 
|   102       info_ptr->x_green = (float)(green_x/100000.); |  | 
|   103       info_ptr->y_green = (float)(green_y/100000.); |  | 
|   104       info_ptr->x_blue  = (float)( blue_x/100000.); |  | 
|   105       info_ptr->y_blue  = (float)( blue_y/100000.); |  | 
|   106 #endif |  | 
|   107       info_ptr->valid |= PNG_INFO_cHRM; |  | 
|   108    } |  | 
|   109 } |    66 } | 
|   110 #endif /* PNG_FIXED_POINT_SUPPORTED */ |    67  | 
 |    68 void PNGFAPI | 
 |    69 png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |    70     png_fixed_point int_red_X, png_fixed_point int_red_Y, | 
 |    71     png_fixed_point int_red_Z, png_fixed_point int_green_X, | 
 |    72     png_fixed_point int_green_Y, png_fixed_point int_green_Z, | 
 |    73     png_fixed_point int_blue_X, png_fixed_point int_blue_Y, | 
 |    74     png_fixed_point int_blue_Z) | 
 |    75 { | 
 |    76    png_XYZ XYZ; | 
 |    77  | 
 |    78    png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); | 
 |    79  | 
 |    80    if (png_ptr == NULL || info_ptr == NULL) | 
 |    81       return; | 
 |    82  | 
 |    83    XYZ.red_X = int_red_X; | 
 |    84    XYZ.red_Y = int_red_Y; | 
 |    85    XYZ.red_Z = int_red_Z; | 
 |    86    XYZ.green_X = int_green_X; | 
 |    87    XYZ.green_Y = int_green_Y; | 
 |    88    XYZ.green_Z = int_green_Z; | 
 |    89    XYZ.blue_X = int_blue_X; | 
 |    90    XYZ.blue_Y = int_blue_Y; | 
 |    91    XYZ.blue_Z = int_blue_Z; | 
 |    92  | 
 |    93    if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2)) | 
 |    94       info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; | 
 |    95  | 
 |    96    png_colorspace_sync_info(png_ptr, info_ptr); | 
 |    97 } | 
 |    98  | 
 |    99 #  ifdef PNG_FLOATING_POINT_SUPPORTED | 
 |   100 void PNGAPI | 
 |   101 png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |   102     double white_x, double white_y, double red_x, double red_y, | 
 |   103     double green_x, double green_y, double blue_x, double blue_y) | 
 |   104 { | 
 |   105    png_set_cHRM_fixed(png_ptr, info_ptr, | 
 |   106       png_fixed(png_ptr, white_x, "cHRM White X"), | 
 |   107       png_fixed(png_ptr, white_y, "cHRM White Y"), | 
 |   108       png_fixed(png_ptr, red_x, "cHRM Red X"), | 
 |   109       png_fixed(png_ptr, red_y, "cHRM Red Y"), | 
 |   110       png_fixed(png_ptr, green_x, "cHRM Green X"), | 
 |   111       png_fixed(png_ptr, green_y, "cHRM Green Y"), | 
 |   112       png_fixed(png_ptr, blue_x, "cHRM Blue X"), | 
 |   113       png_fixed(png_ptr, blue_y, "cHRM Blue Y")); | 
 |   114 } | 
 |   115  | 
 |   116 void PNGAPI | 
 |   117 png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, | 
 |   118     double red_Y, double red_Z, double green_X, double green_Y, double green_Z, | 
 |   119     double blue_X, double blue_Y, double blue_Z) | 
 |   120 { | 
 |   121    png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, | 
 |   122       png_fixed(png_ptr, red_X, "cHRM Red X"), | 
 |   123       png_fixed(png_ptr, red_Y, "cHRM Red Y"), | 
 |   124       png_fixed(png_ptr, red_Z, "cHRM Red Z"), | 
 |   125       png_fixed(png_ptr, green_X, "cHRM Red X"), | 
 |   126       png_fixed(png_ptr, green_Y, "cHRM Red Y"), | 
 |   127       png_fixed(png_ptr, green_Z, "cHRM Red Z"), | 
 |   128       png_fixed(png_ptr, blue_X, "cHRM Red X"), | 
 |   129       png_fixed(png_ptr, blue_Y, "cHRM Red Y"), | 
 |   130       png_fixed(png_ptr, blue_Z, "cHRM Red Z")); | 
 |   131 } | 
 |   132 #  endif /* PNG_FLOATING_POINT_SUPPORTED */ | 
 |   133  | 
|   111 #endif /* PNG_cHRM_SUPPORTED */ |   134 #endif /* PNG_cHRM_SUPPORTED */ | 
|   112  |   135  | 
|   113 #ifdef PNG_gAMA_SUPPORTED |   136 #ifdef PNG_gAMA_SUPPORTED | 
|   114 #ifdef PNG_FLOATING_POINT_SUPPORTED |   137 void PNGFAPI | 
|   115 void PNGAPI |   138 png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   116 png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) |   139     png_fixed_point file_gamma) | 
|   117 { |   140 { | 
|   118    double png_gamma; |  | 
|   119  |  | 
|   120    png_debug1(1, "in %s storage function", "gAMA"); |   141    png_debug1(1, "in %s storage function", "gAMA"); | 
|   121  |   142  | 
|   122    if (png_ptr == NULL || info_ptr == NULL) |   143    if (png_ptr == NULL || info_ptr == NULL) | 
|   123       return; |   144       return; | 
|   124  |   145  | 
|   125    /* Check for overflow */ |   146    png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma); | 
|   126    if (file_gamma > 21474.83) |   147    png_colorspace_sync_info(png_ptr, info_ptr); | 
|   127    { |  | 
|   128       png_warning(png_ptr, "Limiting gamma to 21474.83"); |  | 
|   129       png_gamma=21474.83; |  | 
|   130    } |  | 
|   131    else |  | 
|   132       png_gamma = file_gamma; |  | 
|   133    info_ptr->gamma = (float)png_gamma; |  | 
|   134 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   135    info_ptr->int_gamma = (int)(png_gamma*100000.+.5); |  | 
|   136 #endif |  | 
|   137    info_ptr->valid |= PNG_INFO_gAMA; |  | 
|   138    if (png_gamma == 0.0) |  | 
|   139       png_warning(png_ptr, "Setting gamma=0"); |  | 
|   140 } |   148 } | 
|   141 #endif |   149  | 
 |   150 #  ifdef PNG_FLOATING_POINT_SUPPORTED | 
|   142 void PNGAPI |   151 void PNGAPI | 
|   143 png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point |   152 png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) | 
|   144    int_gamma) |  | 
|   145 { |   153 { | 
|   146    png_fixed_point png_gamma; |   154    png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, | 
|   147  |   155        "png_set_gAMA")); | 
|   148    png_debug1(1, "in %s storage function", "gAMA"); |  | 
|   149  |  | 
|   150    if (png_ptr == NULL || info_ptr == NULL) |  | 
|   151       return; |  | 
|   152  |  | 
|   153    if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX) |  | 
|   154    { |  | 
|   155       png_warning(png_ptr, "Limiting gamma to 21474.83"); |  | 
|   156       png_gamma=PNG_UINT_31_MAX; |  | 
|   157    } |  | 
|   158    else |  | 
|   159    { |  | 
|   160       if (int_gamma < 0) |  | 
|   161       { |  | 
|   162          png_warning(png_ptr, "Setting negative gamma to zero"); |  | 
|   163          png_gamma = 0; |  | 
|   164       } |  | 
|   165       else |  | 
|   166          png_gamma = int_gamma; |  | 
|   167    } |  | 
|   168 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   169    info_ptr->gamma = (float)(png_gamma/100000.); |  | 
|   170 #endif |  | 
|   171 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   172    info_ptr->int_gamma = png_gamma; |  | 
|   173 #endif |  | 
|   174    info_ptr->valid |= PNG_INFO_gAMA; |  | 
|   175    if (png_gamma == 0) |  | 
|   176       png_warning(png_ptr, "Setting gamma=0"); |  | 
|   177 } |   156 } | 
 |   157 #  endif | 
|   178 #endif |   158 #endif | 
|   179  |   159  | 
|   180 #ifdef PNG_hIST_SUPPORTED |   160 #ifdef PNG_hIST_SUPPORTED | 
|   181 void PNGAPI |   161 void PNGAPI | 
|   182 png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) |   162 png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |   163     png_const_uint_16p hist) | 
|   183 { |   164 { | 
|   184    int i; |   165    int i; | 
|   185  |   166  | 
|   186    png_debug1(1, "in %s storage function", "hIST"); |   167    png_debug1(1, "in %s storage function", "hIST"); | 
|   187  |   168  | 
|   188    if (png_ptr == NULL || info_ptr == NULL) |   169    if (png_ptr == NULL || info_ptr == NULL) | 
|   189       return; |   170       return; | 
|   190  |   171  | 
|   191    if (info_ptr->num_palette == 0 || info_ptr->num_palette |   172    if (info_ptr->num_palette == 0 || info_ptr->num_palette | 
|   192        > PNG_MAX_PALETTE_LENGTH) |   173        > PNG_MAX_PALETTE_LENGTH) | 
|   193    { |   174    { | 
|   194       png_warning(png_ptr, |   175       png_warning(png_ptr, | 
|   195          "Invalid palette size, hIST allocation skipped."); |   176           "Invalid palette size, hIST allocation skipped"); | 
 |   177  | 
|   196       return; |   178       return; | 
|   197    } |   179    } | 
|   198  |   180  | 
|   199 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   200    png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); |   181    png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); | 
|   201 #endif |   182  | 
|   202    /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in |   183    /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in | 
|   203     * version 1.2.1 |   184     * version 1.2.1 | 
|   204     */ |   185     */ | 
|   205    png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, |   186    info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr, | 
|   206       (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16))); |   187        PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16)))); | 
|   207    if (png_ptr->hist == NULL) |   188  | 
 |   189    if (info_ptr->hist == NULL) | 
|   208    { |   190    { | 
|   209       png_warning(png_ptr, "Insufficient memory for hIST chunk data."); |   191       png_warning(png_ptr, "Insufficient memory for hIST chunk data"); | 
|   210       return; |   192       return; | 
|   211    } |   193    } | 
|   212  |   194  | 
 |   195    info_ptr->free_me |= PNG_FREE_HIST; | 
 |   196  | 
|   213    for (i = 0; i < info_ptr->num_palette; i++) |   197    for (i = 0; i < info_ptr->num_palette; i++) | 
|   214       png_ptr->hist[i] = hist[i]; |   198       info_ptr->hist[i] = hist[i]; | 
|   215    info_ptr->hist = png_ptr->hist; |   199  | 
|   216    info_ptr->valid |= PNG_INFO_hIST; |   200    info_ptr->valid |= PNG_INFO_hIST; | 
|   217  |  | 
|   218 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   219    info_ptr->free_me |= PNG_FREE_HIST; |  | 
|   220 #else |  | 
|   221    png_ptr->flags |= PNG_FLAG_FREE_HIST; |  | 
|   222 #endif |  | 
|   223 } |   201 } | 
|   224 #endif |   202 #endif | 
|   225  |   203  | 
|   226 void PNGAPI |   204 void PNGAPI | 
|   227 png_set_IHDR(png_structp png_ptr, png_infop info_ptr, |   205 png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   228    png_uint_32 width, png_uint_32 height, int bit_depth, |   206     png_uint_32 width, png_uint_32 height, int bit_depth, | 
|   229    int color_type, int interlace_type, int compression_type, |   207     int color_type, int interlace_type, int compression_type, | 
|   230    int filter_type) |   208     int filter_type) | 
|   231 { |   209 { | 
|   232    png_debug1(1, "in %s storage function", "IHDR"); |   210    png_debug1(1, "in %s storage function", "IHDR"); | 
|   233  |   211  | 
|   234    if (png_ptr == NULL || info_ptr == NULL) |   212    if (png_ptr == NULL || info_ptr == NULL) | 
|   235       return; |   213       return; | 
|   236  |   214  | 
|   237    info_ptr->width = width; |   215    info_ptr->width = width; | 
|   238    info_ptr->height = height; |   216    info_ptr->height = height; | 
|   239    info_ptr->bit_depth = (png_byte)bit_depth; |   217    info_ptr->bit_depth = (png_byte)bit_depth; | 
|   240    info_ptr->color_type = (png_byte)color_type; |   218    info_ptr->color_type = (png_byte)color_type; | 
|   241    info_ptr->compression_type = (png_byte)compression_type; |   219    info_ptr->compression_type = (png_byte)compression_type; | 
|   242    info_ptr->filter_type = (png_byte)filter_type; |   220    info_ptr->filter_type = (png_byte)filter_type; | 
|   243    info_ptr->interlace_type = (png_byte)interlace_type; |   221    info_ptr->interlace_type = (png_byte)interlace_type; | 
|   244  |   222  | 
|   245    png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, |   223    png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, | 
|   246        info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, |   224        info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, | 
|   247        info_ptr->compression_type, info_ptr->filter_type); |   225        info_ptr->compression_type, info_ptr->filter_type); | 
|   248  |   226  | 
|   249    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |   227    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | 
|   250       info_ptr->channels = 1; |   228       info_ptr->channels = 1; | 
 |   229  | 
|   251    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) |   230    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) | 
|   252       info_ptr->channels = 3; |   231       info_ptr->channels = 3; | 
 |   232  | 
|   253    else |   233    else | 
|   254       info_ptr->channels = 1; |   234       info_ptr->channels = 1; | 
 |   235  | 
|   255    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) |   236    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) | 
|   256       info_ptr->channels++; |   237       info_ptr->channels++; | 
 |   238  | 
|   257    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); |   239    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); | 
|   258  |   240  | 
|   259    /* Check for potential overflow */ |   241    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); | 
|   260    if (width > (PNG_UINT_32_MAX |  | 
|   261                  >> 3)      /* 8-byte RGBA pixels */ |  | 
|   262                  - 64       /* bigrowbuf hack */ |  | 
|   263                  - 1        /* filter byte */ |  | 
|   264                  - 7*8      /* rounding of width to multiple of 8 pixels */ |  | 
|   265                  - 8)       /* extra max_pixel_depth pad */ |  | 
|   266       info_ptr->rowbytes = (png_size_t)0; |  | 
|   267    else |  | 
|   268       info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); |  | 
|   269 } |   242 } | 
|   270  |   243  | 
|   271 #ifdef PNG_oFFs_SUPPORTED |   244 #ifdef PNG_oFFs_SUPPORTED | 
|   272 void PNGAPI |   245 void PNGAPI | 
|   273 png_set_oFFs(png_structp png_ptr, png_infop info_ptr, |   246 png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   274    png_int_32 offset_x, png_int_32 offset_y, int unit_type) |   247     png_int_32 offset_x, png_int_32 offset_y, int unit_type) | 
|   275 { |   248 { | 
|   276    png_debug1(1, "in %s storage function", "oFFs"); |   249    png_debug1(1, "in %s storage function", "oFFs"); | 
|   277  |   250  | 
|   278    if (png_ptr == NULL || info_ptr == NULL) |   251    if (png_ptr == NULL || info_ptr == NULL) | 
|   279       return; |   252       return; | 
|   280  |   253  | 
|   281    info_ptr->x_offset = offset_x; |   254    info_ptr->x_offset = offset_x; | 
|   282    info_ptr->y_offset = offset_y; |   255    info_ptr->y_offset = offset_y; | 
|   283    info_ptr->offset_unit_type = (png_byte)unit_type; |   256    info_ptr->offset_unit_type = (png_byte)unit_type; | 
|   284    info_ptr->valid |= PNG_INFO_oFFs; |   257    info_ptr->valid |= PNG_INFO_oFFs; | 
|   285 } |   258 } | 
|   286 #endif |   259 #endif | 
|   287  |   260  | 
|   288 #ifdef PNG_pCAL_SUPPORTED |   261 #ifdef PNG_pCAL_SUPPORTED | 
|   289 void PNGAPI |   262 void PNGAPI | 
|   290 png_set_pCAL(png_structp png_ptr, png_infop info_ptr, |   263 png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   291    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, |   264     png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, | 
|   292    png_charp units, png_charpp params) |   265     int nparams, png_const_charp units, png_charpp params) | 
|   293 { |   266 { | 
|   294    png_uint_32 length; |   267    png_size_t length; | 
|   295    int i; |   268    int i; | 
|   296  |   269  | 
|   297    png_debug1(1, "in %s storage function", "pCAL"); |   270    png_debug1(1, "in %s storage function", "pCAL"); | 
|   298  |   271  | 
|   299    if (png_ptr == NULL || info_ptr == NULL) |   272    if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL | 
 |   273       || (nparams > 0 && params == NULL)) | 
|   300       return; |   274       return; | 
|   301  |   275  | 
|   302    length = png_strlen(purpose) + 1; |   276    length = strlen(purpose) + 1; | 
|   303    png_debug1(3, "allocating purpose for info (%lu bytes)", |   277    png_debug1(3, "allocating purpose for info (%lu bytes)", | 
|   304      (unsigned long)length); |   278        (unsigned long)length); | 
|   305    info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); |   279  | 
 |   280    /* TODO: validate format of calibration name and unit name */ | 
 |   281  | 
 |   282    /* Check that the type matches the specification. */ | 
 |   283    if (type < 0 || type > 3) | 
 |   284       png_error(png_ptr, "Invalid pCAL equation type"); | 
 |   285  | 
 |   286    if (nparams < 0 || nparams > 255) | 
 |   287       png_error(png_ptr, "Invalid pCAL parameter count"); | 
 |   288  | 
 |   289    /* Validate params[nparams] */ | 
 |   290    for (i=0; i<nparams; ++i) | 
 |   291       if (params[i] == NULL || | 
 |   292          !png_check_fp_string(params[i], strlen(params[i]))) | 
 |   293          png_error(png_ptr, "Invalid format for pCAL parameter"); | 
 |   294  | 
 |   295    info_ptr->pcal_purpose = png_voidcast(png_charp, | 
 |   296       png_malloc_warn(png_ptr, length)); | 
 |   297  | 
|   306    if (info_ptr->pcal_purpose == NULL) |   298    if (info_ptr->pcal_purpose == NULL) | 
|   307    { |   299    { | 
|   308       png_warning(png_ptr, "Insufficient memory for pCAL purpose."); |   300       png_warning(png_ptr, "Insufficient memory for pCAL purpose"); | 
|   309       return; |   301       return; | 
|   310    } |   302    } | 
|   311    png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); |   303  | 
 |   304    memcpy(info_ptr->pcal_purpose, purpose, length); | 
|   312  |   305  | 
|   313    png_debug(3, "storing X0, X1, type, and nparams in info"); |   306    png_debug(3, "storing X0, X1, type, and nparams in info"); | 
|   314    info_ptr->pcal_X0 = X0; |   307    info_ptr->pcal_X0 = X0; | 
|   315    info_ptr->pcal_X1 = X1; |   308    info_ptr->pcal_X1 = X1; | 
|   316    info_ptr->pcal_type = (png_byte)type; |   309    info_ptr->pcal_type = (png_byte)type; | 
|   317    info_ptr->pcal_nparams = (png_byte)nparams; |   310    info_ptr->pcal_nparams = (png_byte)nparams; | 
|   318  |   311  | 
|   319    length = png_strlen(units) + 1; |   312    length = strlen(units) + 1; | 
|   320    png_debug1(3, "allocating units for info (%lu bytes)", |   313    png_debug1(3, "allocating units for info (%lu bytes)", | 
|   321      (unsigned long)length); |   314      (unsigned long)length); | 
|   322    info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); |   315  | 
 |   316    info_ptr->pcal_units = png_voidcast(png_charp, | 
 |   317       png_malloc_warn(png_ptr, length)); | 
 |   318  | 
|   323    if (info_ptr->pcal_units == NULL) |   319    if (info_ptr->pcal_units == NULL) | 
|   324    { |   320    { | 
|   325       png_warning(png_ptr, "Insufficient memory for pCAL units."); |   321       png_warning(png_ptr, "Insufficient memory for pCAL units"); | 
|   326       return; |  | 
|   327    } |  | 
|   328    png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); |  | 
|   329  |  | 
|   330    info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, |  | 
|   331       (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); |  | 
|   332    if (info_ptr->pcal_params == NULL) |  | 
|   333    { |  | 
|   334       png_warning(png_ptr, "Insufficient memory for pCAL params."); |  | 
|   335       return; |   322       return; | 
|   336    } |   323    } | 
|   337  |   324  | 
|   338    png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); |   325    memcpy(info_ptr->pcal_units, units, length); | 
 |   326  | 
 |   327    info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, | 
 |   328        (png_size_t)((nparams + 1) * (sizeof (png_charp))))); | 
 |   329  | 
 |   330    if (info_ptr->pcal_params == NULL) | 
 |   331    { | 
 |   332       png_warning(png_ptr, "Insufficient memory for pCAL params"); | 
 |   333       return; | 
 |   334    } | 
 |   335  | 
 |   336    memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); | 
|   339  |   337  | 
|   340    for (i = 0; i < nparams; i++) |   338    for (i = 0; i < nparams; i++) | 
|   341    { |   339    { | 
|   342       length = png_strlen(params[i]) + 1; |   340       length = strlen(params[i]) + 1; | 
|   343       png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, |   341       png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, | 
|   344         (unsigned long)length); |   342           (unsigned long)length); | 
 |   343  | 
|   345       info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); |   344       info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); | 
 |   345  | 
|   346       if (info_ptr->pcal_params[i] == NULL) |   346       if (info_ptr->pcal_params[i] == NULL) | 
|   347       { |   347       { | 
|   348          png_warning(png_ptr, "Insufficient memory for pCAL parameter."); |   348          png_warning(png_ptr, "Insufficient memory for pCAL parameter"); | 
|   349          return; |   349          return; | 
|   350       } |   350       } | 
|   351       png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); |   351  | 
 |   352       memcpy(info_ptr->pcal_params[i], params[i], length); | 
|   352    } |   353    } | 
|   353  |   354  | 
|   354    info_ptr->valid |= PNG_INFO_pCAL; |   355    info_ptr->valid |= PNG_INFO_pCAL; | 
|   355 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   356    info_ptr->free_me |= PNG_FREE_PCAL; |   356    info_ptr->free_me |= PNG_FREE_PCAL; | 
|   357 #endif |  | 
|   358 } |   357 } | 
|   359 #endif |   358 #endif | 
|   360  |   359  | 
|   361 #if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) |   360 #ifdef PNG_sCAL_SUPPORTED | 
|   362 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   363 void PNGAPI |   361 void PNGAPI | 
|   364 png_set_sCAL(png_structp png_ptr, png_infop info_ptr, |   362 png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   365              int unit, double width, double height) |   363     int unit, png_const_charp swidth, png_const_charp sheight) | 
|   366 { |   364 { | 
|   367    png_debug1(1, "in %s storage function", "sCAL"); |   365    png_size_t lengthw = 0, lengthh = 0; | 
|   368  |  | 
|   369    if (png_ptr == NULL || info_ptr == NULL) |  | 
|   370       return; |  | 
|   371  |  | 
|   372    info_ptr->scal_unit = (png_byte)unit; |  | 
|   373    info_ptr->scal_pixel_width = width; |  | 
|   374    info_ptr->scal_pixel_height = height; |  | 
|   375  |  | 
|   376    info_ptr->valid |= PNG_INFO_sCAL; |  | 
|   377 } |  | 
|   378 #else |  | 
|   379 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   380 void PNGAPI |  | 
|   381 png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, |  | 
|   382              int unit, png_charp swidth, png_charp sheight) |  | 
|   383 { |  | 
|   384    png_uint_32 length; |  | 
|   385  |   366  | 
|   386    png_debug1(1, "in %s storage function", "sCAL"); |   367    png_debug1(1, "in %s storage function", "sCAL"); | 
|   387  |   368  | 
|   388    if (png_ptr == NULL || info_ptr == NULL) |   369    if (png_ptr == NULL || info_ptr == NULL) | 
|   389       return; |   370       return; | 
|   390  |   371  | 
 |   372    /* Double check the unit (should never get here with an invalid | 
 |   373     * unit unless this is an API call.) | 
 |   374     */ | 
 |   375    if (unit != 1 && unit != 2) | 
 |   376       png_error(png_ptr, "Invalid sCAL unit"); | 
 |   377  | 
 |   378    if (swidth == NULL || (lengthw = strlen(swidth)) == 0 || | 
 |   379        swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) | 
 |   380       png_error(png_ptr, "Invalid sCAL width"); | 
 |   381  | 
 |   382    if (sheight == NULL || (lengthh = strlen(sheight)) == 0 || | 
 |   383        sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) | 
 |   384       png_error(png_ptr, "Invalid sCAL height"); | 
 |   385  | 
|   391    info_ptr->scal_unit = (png_byte)unit; |   386    info_ptr->scal_unit = (png_byte)unit; | 
|   392  |   387  | 
|   393    length = png_strlen(swidth) + 1; |   388    ++lengthw; | 
|   394    png_debug1(3, "allocating unit for info (%u bytes)", |   389  | 
|   395       (unsigned int)length); |   390    png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); | 
|   396    info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); |   391  | 
 |   392    info_ptr->scal_s_width = png_voidcast(png_charp, | 
 |   393       png_malloc_warn(png_ptr, lengthw)); | 
 |   394  | 
|   397    if (info_ptr->scal_s_width == NULL) |   395    if (info_ptr->scal_s_width == NULL) | 
|   398    { |   396    { | 
|   399       png_warning(png_ptr, |   397       png_warning(png_ptr, "Memory allocation failed while processing sCAL"); | 
|   400          "Memory allocation failed while processing sCAL."); |  | 
|   401       return; |   398       return; | 
|   402    } |   399    } | 
|   403    png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); |  | 
|   404  |   400  | 
|   405    length = png_strlen(sheight) + 1; |   401    memcpy(info_ptr->scal_s_width, swidth, lengthw); | 
|   406    png_debug1(3, "allocating unit for info (%u bytes)", |   402  | 
|   407       (unsigned int)length); |   403    ++lengthh; | 
|   408    info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); |   404  | 
 |   405    png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); | 
 |   406  | 
 |   407    info_ptr->scal_s_height = png_voidcast(png_charp, | 
 |   408       png_malloc_warn(png_ptr, lengthh)); | 
 |   409  | 
|   409    if (info_ptr->scal_s_height == NULL) |   410    if (info_ptr->scal_s_height == NULL) | 
|   410    { |   411    { | 
|   411       png_free (png_ptr, info_ptr->scal_s_width); |   412       png_free (png_ptr, info_ptr->scal_s_width); | 
|   412       info_ptr->scal_s_width = NULL; |   413       info_ptr->scal_s_width = NULL; | 
|   413       png_warning(png_ptr, |   414  | 
|   414          "Memory allocation failed while processing sCAL."); |   415       png_warning(png_ptr, "Memory allocation failed while processing sCAL"); | 
|   415       return; |   416       return; | 
|   416    } |   417    } | 
|   417    png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); |   418  | 
 |   419    memcpy(info_ptr->scal_s_height, sheight, lengthh); | 
 |   420  | 
|   418    info_ptr->valid |= PNG_INFO_sCAL; |   421    info_ptr->valid |= PNG_INFO_sCAL; | 
|   419 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   420    info_ptr->free_me |= PNG_FREE_SCAL; |   422    info_ptr->free_me |= PNG_FREE_SCAL; | 
|   421 #endif |  | 
|   422 } |   423 } | 
|   423 #endif |   424  | 
|   424 #endif |   425 #  ifdef PNG_FLOATING_POINT_SUPPORTED | 
 |   426 void PNGAPI | 
 |   427 png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, | 
 |   428     double width, double height) | 
 |   429 { | 
 |   430    png_debug1(1, "in %s storage function", "sCAL"); | 
 |   431  | 
 |   432    /* Check the arguments. */ | 
 |   433    if (width <= 0) | 
 |   434       png_warning(png_ptr, "Invalid sCAL width ignored"); | 
 |   435  | 
 |   436    else if (height <= 0) | 
 |   437       png_warning(png_ptr, "Invalid sCAL height ignored"); | 
 |   438  | 
 |   439    else | 
 |   440    { | 
 |   441       /* Convert 'width' and 'height' to ASCII. */ | 
 |   442       char swidth[PNG_sCAL_MAX_DIGITS+1]; | 
 |   443       char sheight[PNG_sCAL_MAX_DIGITS+1]; | 
 |   444  | 
 |   445       png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, | 
 |   446          PNG_sCAL_PRECISION); | 
 |   447       png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, | 
 |   448          PNG_sCAL_PRECISION); | 
 |   449  | 
 |   450       png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); | 
 |   451    } | 
 |   452 } | 
 |   453 #  endif | 
 |   454  | 
 |   455 #  ifdef PNG_FIXED_POINT_SUPPORTED | 
 |   456 void PNGAPI | 
 |   457 png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, | 
 |   458     png_fixed_point width, png_fixed_point height) | 
 |   459 { | 
 |   460    png_debug1(1, "in %s storage function", "sCAL"); | 
 |   461  | 
 |   462    /* Check the arguments. */ | 
 |   463    if (width <= 0) | 
 |   464       png_warning(png_ptr, "Invalid sCAL width ignored"); | 
 |   465  | 
 |   466    else if (height <= 0) | 
 |   467       png_warning(png_ptr, "Invalid sCAL height ignored"); | 
 |   468  | 
 |   469    else | 
 |   470    { | 
 |   471       /* Convert 'width' and 'height' to ASCII. */ | 
 |   472       char swidth[PNG_sCAL_MAX_DIGITS+1]; | 
 |   473       char sheight[PNG_sCAL_MAX_DIGITS+1]; | 
 |   474  | 
 |   475       png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width); | 
 |   476       png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height); | 
 |   477  | 
 |   478       png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); | 
 |   479    } | 
 |   480 } | 
 |   481 #  endif | 
|   425 #endif |   482 #endif | 
|   426  |   483  | 
|   427 #ifdef PNG_pHYs_SUPPORTED |   484 #ifdef PNG_pHYs_SUPPORTED | 
|   428 void PNGAPI |   485 void PNGAPI | 
|   429 png_set_pHYs(png_structp png_ptr, png_infop info_ptr, |   486 png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   430    png_uint_32 res_x, png_uint_32 res_y, int unit_type) |   487     png_uint_32 res_x, png_uint_32 res_y, int unit_type) | 
|   431 { |   488 { | 
|   432    png_debug1(1, "in %s storage function", "pHYs"); |   489    png_debug1(1, "in %s storage function", "pHYs"); | 
|   433  |   490  | 
|   434    if (png_ptr == NULL || info_ptr == NULL) |   491    if (png_ptr == NULL || info_ptr == NULL) | 
|   435       return; |   492       return; | 
|   436  |   493  | 
|   437    info_ptr->x_pixels_per_unit = res_x; |   494    info_ptr->x_pixels_per_unit = res_x; | 
|   438    info_ptr->y_pixels_per_unit = res_y; |   495    info_ptr->y_pixels_per_unit = res_y; | 
|   439    info_ptr->phys_unit_type = (png_byte)unit_type; |   496    info_ptr->phys_unit_type = (png_byte)unit_type; | 
|   440    info_ptr->valid |= PNG_INFO_pHYs; |   497    info_ptr->valid |= PNG_INFO_pHYs; | 
|   441 } |   498 } | 
|   442 #endif |   499 #endif | 
|   443  |   500  | 
|   444 void PNGAPI |   501 void PNGAPI | 
|   445 png_set_PLTE(png_structp png_ptr, png_infop info_ptr, |   502 png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, | 
|   446    png_colorp palette, int num_palette) |   503     png_const_colorp palette, int num_palette) | 
|   447 { |   504 { | 
|   448  |   505  | 
|   449    png_debug1(1, "in %s storage function", "PLTE"); |   506    png_debug1(1, "in %s storage function", "PLTE"); | 
|   450  |   507  | 
|   451    if (png_ptr == NULL || info_ptr == NULL) |   508    if (png_ptr == NULL || info_ptr == NULL) | 
|   452       return; |   509       return; | 
|   453  |   510  | 
|   454    if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) |   511    if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) | 
|   455    { |   512    { | 
|   456       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |   513       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | 
|   457          png_error(png_ptr, "Invalid palette length"); |   514          png_error(png_ptr, "Invalid palette length"); | 
 |   515  | 
|   458       else |   516       else | 
|   459       { |   517       { | 
|   460          png_warning(png_ptr, "Invalid palette length"); |   518          png_warning(png_ptr, "Invalid palette length"); | 
|   461          return; |   519          return; | 
|   462       } |   520       } | 
|   463    } |   521    } | 
|   464  |   522  | 
 |   523    if ((num_palette > 0 && palette == NULL) || | 
 |   524       (num_palette == 0 | 
 |   525 #        ifdef PNG_MNG_FEATURES_SUPPORTED | 
 |   526             && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 | 
 |   527 #        endif | 
 |   528       )) | 
 |   529    { | 
 |   530       png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR); | 
 |   531       return; | 
 |   532    } | 
 |   533  | 
|   465    /* It may not actually be necessary to set png_ptr->palette here; |   534    /* It may not actually be necessary to set png_ptr->palette here; | 
|   466     * we do it for backward compatibility with the way the png_handle_tRNS |   535     * we do it for backward compatibility with the way the png_handle_tRNS | 
|   467     * function used to do the allocation. |   536     * function used to do the allocation. | 
|   468     */ |   537     * | 
|   469 #ifdef PNG_FREE_ME_SUPPORTED |   538     * 1.6.0: the above statement appears to be incorrect; something has to set | 
 |   539     * the palette inside png_struct on read. | 
 |   540     */ | 
|   470    png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); |   541    png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); | 
|   471 #endif |  | 
|   472  |   542  | 
|   473    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead |   543    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead | 
|   474     * of num_palette entries, in case of an invalid PNG file that has |   544     * of num_palette entries, in case of an invalid PNG file that has | 
|   475     * too-large sample values. |   545     * too-large sample values. | 
|   476     */ |   546     */ | 
|   477    png_ptr->palette = (png_colorp)png_calloc(png_ptr, |   547    png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, | 
|   478       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); |   548        PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); | 
|   479    png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); |   549  | 
 |   550    if (num_palette > 0) | 
 |   551       memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); | 
|   480    info_ptr->palette = png_ptr->palette; |   552    info_ptr->palette = png_ptr->palette; | 
|   481    info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; |   553    info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; | 
|   482  |   554  | 
|   483 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   484    info_ptr->free_me |= PNG_FREE_PLTE; |   555    info_ptr->free_me |= PNG_FREE_PLTE; | 
|   485 #else |   556  | 
|   486    png_ptr->flags |= PNG_FLAG_FREE_PLTE; |   557    info_ptr->valid |= PNG_INFO_PLTE; | 
 |   558 } | 
 |   559  | 
 |   560 #ifdef PNG_sBIT_SUPPORTED | 
 |   561 void PNGAPI | 
 |   562 png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |   563     png_const_color_8p sig_bit) | 
 |   564 { | 
 |   565    png_debug1(1, "in %s storage function", "sBIT"); | 
 |   566  | 
 |   567    if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL) | 
 |   568       return; | 
 |   569  | 
 |   570    info_ptr->sig_bit = *sig_bit; | 
 |   571    info_ptr->valid |= PNG_INFO_sBIT; | 
 |   572 } | 
|   487 #endif |   573 #endif | 
|   488  |   574  | 
|   489    info_ptr->valid |= PNG_INFO_PLTE; |   575 #ifdef PNG_sRGB_SUPPORTED | 
|   490 } |   576 void PNGAPI | 
|   491  |   577 png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) | 
|   492 #ifdef PNG_sBIT_SUPPORTED |   578 { | 
|   493 void PNGAPI |   579    png_debug1(1, "in %s storage function", "sRGB"); | 
|   494 png_set_sBIT(png_structp png_ptr, png_infop info_ptr, |  | 
|   495    png_color_8p sig_bit) |  | 
|   496 { |  | 
|   497    png_debug1(1, "in %s storage function", "sBIT"); |  | 
|   498  |   580  | 
|   499    if (png_ptr == NULL || info_ptr == NULL) |   581    if (png_ptr == NULL || info_ptr == NULL) | 
|   500       return; |   582       return; | 
|   501  |   583  | 
|   502    png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); |   584    (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); | 
|   503    info_ptr->valid |= PNG_INFO_sBIT; |   585    png_colorspace_sync_info(png_ptr, info_ptr); | 
|   504 } |   586 } | 
|   505 #endif |   587  | 
|   506  |   588 void PNGAPI | 
|   507 #ifdef PNG_sRGB_SUPPORTED |   589 png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   508 void PNGAPI |   590     int srgb_intent) | 
|   509 png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) |   591 { | 
|   510 { |   592    png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); | 
|   511    png_debug1(1, "in %s storage function", "sRGB"); |  | 
|   512  |   593  | 
|   513    if (png_ptr == NULL || info_ptr == NULL) |   594    if (png_ptr == NULL || info_ptr == NULL) | 
|   514       return; |   595       return; | 
|   515  |   596  | 
|   516    info_ptr->srgb_intent = (png_byte)intent; |   597    if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent)) | 
|   517    info_ptr->valid |= PNG_INFO_sRGB; |   598    { | 
|   518 } |   599       /* This causes the gAMA and cHRM to be written too */ | 
|   519  |   600       info_ptr->colorspace.flags |= | 
|   520 void PNGAPI |   601          PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; | 
|   521 png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, |   602    } | 
|   522    int intent) |   603  | 
|   523 { |   604    png_colorspace_sync_info(png_ptr, info_ptr); | 
|   524 #ifdef PNG_gAMA_SUPPORTED |  | 
|   525 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   526    float file_gamma; |  | 
|   527 #endif |  | 
|   528 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   529    png_fixed_point int_file_gamma; |  | 
|   530 #endif |  | 
|   531 #endif |  | 
|   532 #ifdef PNG_cHRM_SUPPORTED |  | 
|   533 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   534    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; |  | 
|   535 #endif |  | 
|   536    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, |  | 
|   537       int_green_y, int_blue_x, int_blue_y; |  | 
|   538 #endif |  | 
|   539    png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); |  | 
|   540  |  | 
|   541    if (png_ptr == NULL || info_ptr == NULL) |  | 
|   542       return; |  | 
|   543  |  | 
|   544    png_set_sRGB(png_ptr, info_ptr, intent); |  | 
|   545  |  | 
|   546 #ifdef PNG_gAMA_SUPPORTED |  | 
|   547 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   548    file_gamma = (float).45455; |  | 
|   549    png_set_gAMA(png_ptr, info_ptr, file_gamma); |  | 
|   550 #endif |  | 
|   551 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   552    int_file_gamma = 45455L; |  | 
|   553    png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); |  | 
|   554 #endif |  | 
|   555 #endif |  | 
|   556  |  | 
|   557 #ifdef PNG_cHRM_SUPPORTED |  | 
|   558    int_white_x = 31270L; |  | 
|   559    int_white_y = 32900L; |  | 
|   560    int_red_x   = 64000L; |  | 
|   561    int_red_y   = 33000L; |  | 
|   562    int_green_x = 30000L; |  | 
|   563    int_green_y = 60000L; |  | 
|   564    int_blue_x  = 15000L; |  | 
|   565    int_blue_y  =  6000L; |  | 
|   566  |  | 
|   567 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   568    white_x = (float).3127; |  | 
|   569    white_y = (float).3290; |  | 
|   570    red_x   = (float).64; |  | 
|   571    red_y   = (float).33; |  | 
|   572    green_x = (float).30; |  | 
|   573    green_y = (float).60; |  | 
|   574    blue_x  = (float).15; |  | 
|   575    blue_y  = (float).06; |  | 
|   576 #endif |  | 
|   577  |  | 
|   578 #ifdef PNG_FIXED_POINT_SUPPORTED |  | 
|   579    png_set_cHRM_fixed(png_ptr, info_ptr, |  | 
|   580        int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, |  | 
|   581        int_green_y, int_blue_x, int_blue_y); |  | 
|   582 #endif |  | 
|   583 #ifdef PNG_FLOATING_POINT_SUPPORTED |  | 
|   584    png_set_cHRM(png_ptr, info_ptr, |  | 
|   585        white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); |  | 
|   586 #endif |  | 
|   587 #endif /* cHRM */ |  | 
|   588 } |   605 } | 
|   589 #endif /* sRGB */ |   606 #endif /* sRGB */ | 
|   590  |   607  | 
|   591  |   608  | 
|   592 #ifdef PNG_iCCP_SUPPORTED |   609 #ifdef PNG_iCCP_SUPPORTED | 
|   593 void PNGAPI |   610 void PNGAPI | 
|   594 png_set_iCCP(png_structp png_ptr, png_infop info_ptr, |   611 png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   595              png_charp name, int compression_type, |   612     png_const_charp name, int compression_type, | 
|   596              png_charp profile, png_uint_32 proflen) |   613     png_const_bytep profile, png_uint_32 proflen) | 
|   597 { |   614 { | 
|   598    png_charp new_iccp_name; |   615    png_charp new_iccp_name; | 
|   599    png_charp new_iccp_profile; |   616    png_bytep new_iccp_profile; | 
|   600    png_uint_32 length; |   617    png_size_t length; | 
|   601  |   618  | 
|   602    png_debug1(1, "in %s storage function", "iCCP"); |   619    png_debug1(1, "in %s storage function", "iCCP"); | 
|   603  |   620  | 
|   604    if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) |   621    if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) | 
|   605       return; |   622       return; | 
|   606  |   623  | 
|   607    length = png_strlen(name)+1; |   624    if (compression_type != PNG_COMPRESSION_TYPE_BASE) | 
|   608    new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); |   625       png_app_error(png_ptr, "Invalid iCCP compression method"); | 
 |   626  | 
 |   627    /* Set the colorspace first because this validates the profile; do not | 
 |   628     * override previously set app cHRM or gAMA here (because likely as not the | 
 |   629     * application knows better than libpng what the correct values are.)  Pass | 
 |   630     * the info_ptr color_type field to png_colorspace_set_ICC because in the | 
 |   631     * write case it has not yet been stored in png_ptr. | 
 |   632     */ | 
 |   633    { | 
 |   634       int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, | 
 |   635          proflen, profile, info_ptr->color_type); | 
 |   636  | 
 |   637       png_colorspace_sync_info(png_ptr, info_ptr); | 
 |   638  | 
 |   639       /* Don't do any of the copying if the profile was bad, or inconsistent. */ | 
 |   640       if (!result) | 
 |   641          return; | 
 |   642  | 
 |   643       /* But do write the gAMA and cHRM chunks from the profile. */ | 
 |   644       info_ptr->colorspace.flags |= | 
 |   645          PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; | 
 |   646    } | 
 |   647  | 
 |   648    length = strlen(name)+1; | 
 |   649    new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length)); | 
 |   650  | 
|   609    if (new_iccp_name == NULL) |   651    if (new_iccp_name == NULL) | 
|   610    { |   652    { | 
|   611         png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); |   653       png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk"); | 
|   612       return; |   654       return; | 
|   613    } |   655    } | 
|   614    png_memcpy(new_iccp_name, name, length); |   656  | 
|   615    new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); |   657    memcpy(new_iccp_name, name, length); | 
 |   658    new_iccp_profile = png_voidcast(png_bytep, | 
 |   659       png_malloc_warn(png_ptr, proflen)); | 
 |   660  | 
|   616    if (new_iccp_profile == NULL) |   661    if (new_iccp_profile == NULL) | 
|   617    { |   662    { | 
|   618       png_free (png_ptr, new_iccp_name); |   663       png_free(png_ptr, new_iccp_name); | 
|   619       png_warning(png_ptr, |   664       png_benign_error(png_ptr, | 
|   620           "Insufficient memory to process iCCP profile."); |   665           "Insufficient memory to process iCCP profile"); | 
|   621       return; |   666       return; | 
|   622    } |   667    } | 
|   623    png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); |   668  | 
 |   669    memcpy(new_iccp_profile, profile, proflen); | 
|   624  |   670  | 
|   625    png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); |   671    png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); | 
|   626  |   672  | 
|   627    info_ptr->iccp_proflen = proflen; |   673    info_ptr->iccp_proflen = proflen; | 
|   628    info_ptr->iccp_name = new_iccp_name; |   674    info_ptr->iccp_name = new_iccp_name; | 
|   629    info_ptr->iccp_profile = new_iccp_profile; |   675    info_ptr->iccp_profile = new_iccp_profile; | 
|   630    /* Compression is always zero but is here so the API and info structure |  | 
|   631     * does not have to change if we introduce multiple compression types |  | 
|   632     */ |  | 
|   633    info_ptr->iccp_compression = (png_byte)compression_type; |  | 
|   634 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   635    info_ptr->free_me |= PNG_FREE_ICCP; |   676    info_ptr->free_me |= PNG_FREE_ICCP; | 
 |   677    info_ptr->valid |= PNG_INFO_iCCP; | 
 |   678 } | 
|   636 #endif |   679 #endif | 
|   637    info_ptr->valid |= PNG_INFO_iCCP; |  | 
|   638 } |  | 
|   639 #endif |  | 
|   640  |   680  | 
|   641 #ifdef PNG_TEXT_SUPPORTED |   681 #ifdef PNG_TEXT_SUPPORTED | 
|   642 void PNGAPI |   682 void PNGAPI | 
|   643 png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, |   683 png_set_text(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   644              int num_text) |   684     png_const_textp text_ptr, int num_text) | 
|   645 { |   685 { | 
|   646    int ret; |   686    int ret; | 
|   647    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); |   687    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); | 
 |   688  | 
|   648    if (ret) |   689    if (ret) | 
|   649       png_error(png_ptr, "Insufficient memory to store text"); |   690       png_error(png_ptr, "Insufficient memory to store text"); | 
|   650 } |   691 } | 
|   651  |   692  | 
|   652 int /* PRIVATE */ |   693 int /* PRIVATE */ | 
|   653 png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, |   694 png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, | 
|   654                int num_text) |   695     png_const_textp text_ptr, int num_text) | 
|   655 { |   696 { | 
|   656    int i; |   697    int i; | 
|   657  |   698  | 
|   658    png_debug1(1, "in %s storage function", ((png_ptr == NULL || |   699    png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : | 
|   659       png_ptr->chunk_name[0] == '\0') ? |   700       (unsigned long)png_ptr->chunk_name); | 
|   660       "text" : (png_const_charp)png_ptr->chunk_name)); |   701  | 
|   661  |   702    if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) | 
|   662    if (png_ptr == NULL || info_ptr == NULL || num_text == 0) |  | 
|   663       return(0); |   703       return(0); | 
|   664  |   704  | 
|   665    /* Make sure we have enough space in the "text" array in info_struct |   705    /* Make sure we have enough space in the "text" array in info_struct | 
|   666     * to hold all of the incoming text_ptr objects. |   706     * to hold all of the incoming text_ptr objects.  This compare can't overflow | 
|   667     */ |   707     * because max_text >= num_text (anyway, subtract of two positive integers | 
|   668    if (info_ptr->num_text + num_text > info_ptr->max_text) |   708     * can't overflow in any case.) | 
|   669    { |   709     */ | 
|   670       if (info_ptr->text != NULL) |   710    if (num_text > info_ptr->max_text - info_ptr->num_text) | 
|   671       { |   711    { | 
|   672          png_textp old_text; |   712       int old_num_text = info_ptr->num_text; | 
|   673          int old_max; |   713       int max_text; | 
|   674  |   714       png_textp new_text = NULL; | 
|   675          old_max = info_ptr->max_text; |   715  | 
|   676          info_ptr->max_text = info_ptr->num_text + num_text + 8; |   716       /* Calculate an appropriate max_text, checking for overflow. */ | 
|   677          old_text = info_ptr->text; |   717       max_text = old_num_text; | 
|   678          info_ptr->text = (png_textp)png_malloc_warn(png_ptr, |   718       if (num_text <= INT_MAX - max_text) | 
|   679             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); |   719       { | 
|   680          if (info_ptr->text == NULL) |   720          max_text += num_text; | 
|   681          { |   721  | 
|   682             png_free(png_ptr, old_text); |   722          /* Round up to a multiple of 8 */ | 
|   683             return(1); |   723          if (max_text < INT_MAX-8) | 
|   684          } |   724             max_text = (max_text + 8) & ~0x7; | 
|   685          png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * |   725  | 
|   686             png_sizeof(png_text))); |   726          else | 
|   687          png_free(png_ptr, old_text); |   727             max_text = INT_MAX; | 
|   688       } |   728  | 
|   689       else |   729          /* Now allocate a new array and copy the old members in, this does all | 
|   690       { |   730           * the overflow checks. | 
|   691          info_ptr->max_text = num_text + 8; |   731           */ | 
|   692          info_ptr->num_text = 0; |   732          new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, | 
|   693          info_ptr->text = (png_textp)png_malloc_warn(png_ptr, |   733             info_ptr->text, old_num_text, max_text-old_num_text, | 
|   694             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); |   734             sizeof *new_text)); | 
|   695          if (info_ptr->text == NULL) |   735       } | 
|   696             return(1); |   736  | 
|   697 #ifdef PNG_FREE_ME_SUPPORTED |   737       if (new_text == NULL) | 
|   698          info_ptr->free_me |= PNG_FREE_TEXT; |   738       { | 
|   699 #endif |   739          png_chunk_report(png_ptr, "too many text chunks", | 
|   700       } |   740             PNG_CHUNK_WRITE_ERROR); | 
|   701       png_debug1(3, "allocated %d entries for info_ptr->text", |   741          return 1; | 
|   702          info_ptr->max_text); |   742       } | 
|   703    } |   743  | 
 |   744       png_free(png_ptr, info_ptr->text); | 
 |   745  | 
 |   746       info_ptr->text = new_text; | 
 |   747       info_ptr->free_me |= PNG_FREE_TEXT; | 
 |   748       info_ptr->max_text = max_text; | 
 |   749       /* num_text is adjusted below as the entries are copied in */ | 
 |   750  | 
 |   751       png_debug1(3, "allocated %d entries for info_ptr->text", max_text); | 
 |   752    } | 
 |   753  | 
|   704    for (i = 0; i < num_text; i++) |   754    for (i = 0; i < num_text; i++) | 
|   705    { |   755    { | 
|   706       png_size_t text_length, key_len; |   756       size_t text_length, key_len; | 
|   707       png_size_t lang_len, lang_key_len; |   757       size_t lang_len, lang_key_len; | 
|   708       png_textp textp = &(info_ptr->text[info_ptr->num_text]); |   758       png_textp textp = &(info_ptr->text[info_ptr->num_text]); | 
|   709  |   759  | 
|   710       if (text_ptr[i].key == NULL) |   760       if (text_ptr[i].key == NULL) | 
|   711           continue; |   761           continue; | 
|   712  |   762  | 
|   713       key_len = png_strlen(text_ptr[i].key); |   763       if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || | 
 |   764           text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) | 
 |   765       { | 
 |   766          png_chunk_report(png_ptr, "text compression mode is out of range", | 
 |   767             PNG_CHUNK_WRITE_ERROR); | 
 |   768          continue; | 
 |   769       } | 
 |   770  | 
 |   771       key_len = strlen(text_ptr[i].key); | 
|   714  |   772  | 
|   715       if (text_ptr[i].compression <= 0) |   773       if (text_ptr[i].compression <= 0) | 
|   716       { |   774       { | 
|   717          lang_len = 0; |   775          lang_len = 0; | 
|   718          lang_key_len = 0; |   776          lang_key_len = 0; | 
|   719       } |   777       } | 
|   720  |   778  | 
|   721       else |   779       else | 
|   722 #ifdef PNG_iTXt_SUPPORTED |   780 #  ifdef PNG_iTXt_SUPPORTED | 
|   723       { |   781       { | 
|   724          /* Set iTXt data */ |   782          /* Set iTXt data */ | 
|   725  |   783  | 
|   726          if (text_ptr[i].lang != NULL) |   784          if (text_ptr[i].lang != NULL) | 
|   727             lang_len = png_strlen(text_ptr[i].lang); |   785             lang_len = strlen(text_ptr[i].lang); | 
 |   786  | 
|   728          else |   787          else | 
|   729             lang_len = 0; |   788             lang_len = 0; | 
 |   789  | 
|   730          if (text_ptr[i].lang_key != NULL) |   790          if (text_ptr[i].lang_key != NULL) | 
|   731             lang_key_len = png_strlen(text_ptr[i].lang_key); |   791             lang_key_len = strlen(text_ptr[i].lang_key); | 
 |   792  | 
|   732          else |   793          else | 
|   733             lang_key_len = 0; |   794             lang_key_len = 0; | 
|   734       } |   795       } | 
|   735 #else /* PNG_iTXt_SUPPORTED */ |   796 #  else /* PNG_iTXt_SUPPORTED */ | 
|   736       { |   797       { | 
|   737          png_warning(png_ptr, "iTXt chunk not supported."); |   798          png_chunk_report(png_ptr, "iTXt chunk not supported", | 
 |   799             PNG_CHUNK_WRITE_ERROR); | 
|   738          continue; |   800          continue; | 
|   739       } |   801       } | 
|   740 #endif |   802 #  endif | 
|   741  |   803  | 
|   742       if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') |   804       if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') | 
|   743       { |   805       { | 
|   744          text_length = 0; |   806          text_length = 0; | 
|   745 #ifdef PNG_iTXt_SUPPORTED |   807 #  ifdef PNG_iTXt_SUPPORTED | 
|   746          if (text_ptr[i].compression > 0) |   808          if (text_ptr[i].compression > 0) | 
|   747             textp->compression = PNG_ITXT_COMPRESSION_NONE; |   809             textp->compression = PNG_ITXT_COMPRESSION_NONE; | 
 |   810  | 
|   748          else |   811          else | 
|   749 #endif |   812 #  endif | 
|   750             textp->compression = PNG_TEXT_COMPRESSION_NONE; |   813             textp->compression = PNG_TEXT_COMPRESSION_NONE; | 
|   751       } |   814       } | 
|   752  |   815  | 
|   753       else |   816       else | 
|   754       { |   817       { | 
|   755          text_length = png_strlen(text_ptr[i].text); |   818          text_length = strlen(text_ptr[i].text); | 
|   756          textp->compression = text_ptr[i].compression; |   819          textp->compression = text_ptr[i].compression; | 
|   757       } |   820       } | 
|   758  |   821  | 
|   759       textp->key = (png_charp)png_malloc_warn(png_ptr, |   822       textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr, | 
|   760          (png_uint_32) |   823           key_len + text_length + lang_len + lang_key_len + 4)); | 
|   761          (key_len + text_length + lang_len + lang_key_len + 4)); |   824  | 
|   762       if (textp->key == NULL) |   825       if (textp->key == NULL) | 
|   763          return(1); |   826       { | 
|   764       png_debug2(2, "Allocated %lu bytes at %x in png_set_text", |   827          png_chunk_report(png_ptr, "text chunk: out of memory", | 
|   765                  (png_uint_32) |   828                PNG_CHUNK_WRITE_ERROR); | 
|   766                  (key_len + lang_len + lang_key_len + text_length + 4), |   829          return 1; | 
|   767                  (int)textp->key); |   830       } | 
|   768  |   831  | 
|   769       png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); |   832       png_debug2(2, "Allocated %lu bytes at %p in png_set_text", | 
 |   833           (unsigned long)(png_uint_32) | 
 |   834           (key_len + lang_len + lang_key_len + text_length + 4), | 
 |   835           textp->key); | 
 |   836  | 
 |   837       memcpy(textp->key, text_ptr[i].key, key_len); | 
|   770       *(textp->key + key_len) = '\0'; |   838       *(textp->key + key_len) = '\0'; | 
|   771 #ifdef PNG_iTXt_SUPPORTED |   839  | 
|   772       if (text_ptr[i].compression > 0) |   840       if (text_ptr[i].compression > 0) | 
|   773       { |   841       { | 
|   774          textp->lang = textp->key + key_len + 1; |   842          textp->lang = textp->key + key_len + 1; | 
|   775          png_memcpy(textp->lang, text_ptr[i].lang, lang_len); |   843          memcpy(textp->lang, text_ptr[i].lang, lang_len); | 
|   776          *(textp->lang + lang_len) = '\0'; |   844          *(textp->lang + lang_len) = '\0'; | 
|   777          textp->lang_key = textp->lang + lang_len + 1; |   845          textp->lang_key = textp->lang + lang_len + 1; | 
|   778          png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); |   846          memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); | 
|   779          *(textp->lang_key + lang_key_len) = '\0'; |   847          *(textp->lang_key + lang_key_len) = '\0'; | 
|   780          textp->text = textp->lang_key + lang_key_len + 1; |   848          textp->text = textp->lang_key + lang_key_len + 1; | 
|   781       } |   849       } | 
 |   850  | 
|   782       else |   851       else | 
|   783 #endif |   852       { | 
|   784       { |  | 
|   785 #ifdef PNG_iTXt_SUPPORTED |  | 
|   786          textp->lang=NULL; |   853          textp->lang=NULL; | 
|   787          textp->lang_key=NULL; |   854          textp->lang_key=NULL; | 
|   788 #endif |  | 
|   789          textp->text = textp->key + key_len + 1; |   855          textp->text = textp->key + key_len + 1; | 
|   790       } |   856       } | 
 |   857  | 
|   791       if (text_length) |   858       if (text_length) | 
|   792          png_memcpy(textp->text, text_ptr[i].text, |   859          memcpy(textp->text, text_ptr[i].text, text_length); | 
|   793             (png_size_t)(text_length)); |   860  | 
|   794       *(textp->text + text_length) = '\0'; |   861       *(textp->text + text_length) = '\0'; | 
|   795  |   862  | 
|   796 #ifdef PNG_iTXt_SUPPORTED |   863 #  ifdef PNG_iTXt_SUPPORTED | 
|   797       if (textp->compression > 0) |   864       if (textp->compression > 0) | 
|   798       { |   865       { | 
|   799          textp->text_length = 0; |   866          textp->text_length = 0; | 
|   800          textp->itxt_length = text_length; |   867          textp->itxt_length = text_length; | 
|   801       } |   868       } | 
 |   869  | 
|   802       else |   870       else | 
|   803 #endif |   871 #  endif | 
|   804  |  | 
|   805       { |   872       { | 
|   806          textp->text_length = text_length; |   873          textp->text_length = text_length; | 
|   807 #ifdef PNG_iTXt_SUPPORTED |  | 
|   808          textp->itxt_length = 0; |   874          textp->itxt_length = 0; | 
|   809 #endif |   875       } | 
|   810       } |   876  | 
|   811       info_ptr->num_text++; |   877       info_ptr->num_text++; | 
|   812       png_debug1(3, "transferred text chunk %d", info_ptr->num_text); |   878       png_debug1(3, "transferred text chunk %d", info_ptr->num_text); | 
|   813    } |   879    } | 
 |   880  | 
|   814    return(0); |   881    return(0); | 
|   815 } |   882 } | 
|   816 #endif |   883 #endif | 
|   817  |   884  | 
|   818 #ifdef PNG_tIME_SUPPORTED |   885 #ifdef PNG_tIME_SUPPORTED | 
|   819 void PNGAPI |   886 void PNGAPI | 
|   820 png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) |   887 png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |   888     png_const_timep mod_time) | 
|   821 { |   889 { | 
|   822    png_debug1(1, "in %s storage function", "tIME"); |   890    png_debug1(1, "in %s storage function", "tIME"); | 
|   823  |   891  | 
|   824    if (png_ptr == NULL || info_ptr == NULL || |   892    if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL || | 
|   825        (png_ptr->mode & PNG_WROTE_tIME)) |   893        (png_ptr->mode & PNG_WROTE_tIME)) | 
|   826       return; |   894       return; | 
|   827  |   895  | 
|   828    png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); |   896    if (mod_time->month == 0   || mod_time->month > 12  || | 
 |   897        mod_time->day   == 0   || mod_time->day   > 31  || | 
 |   898        mod_time->hour  > 23   || mod_time->minute > 59 || | 
 |   899        mod_time->second > 60) | 
 |   900    { | 
 |   901       png_warning(png_ptr, "Ignoring invalid time value"); | 
 |   902       return; | 
 |   903    } | 
 |   904  | 
 |   905    info_ptr->mod_time = *mod_time; | 
|   829    info_ptr->valid |= PNG_INFO_tIME; |   906    info_ptr->valid |= PNG_INFO_tIME; | 
|   830 } |   907 } | 
|   831 #endif |   908 #endif | 
|   832  |   909  | 
|   833 #ifdef PNG_tRNS_SUPPORTED |   910 #ifdef PNG_tRNS_SUPPORTED | 
|   834 void PNGAPI |   911 void PNGAPI | 
|   835 png_set_tRNS(png_structp png_ptr, png_infop info_ptr, |   912 png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, | 
|   836    png_bytep trans, int num_trans, png_color_16p trans_values) |   913     png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) | 
|   837 { |   914 { | 
|   838    png_debug1(1, "in %s storage function", "tRNS"); |   915    png_debug1(1, "in %s storage function", "tRNS"); | 
|   839  |   916  | 
|   840    if (png_ptr == NULL || info_ptr == NULL) |   917    if (png_ptr == NULL || info_ptr == NULL) | 
|   841       return; |   918       return; | 
|   842  |   919  | 
|   843    if (trans != NULL) |   920    if (trans_alpha != NULL) | 
|   844    { |   921    { | 
|   845        /* It may not actually be necessary to set png_ptr->trans here; |   922        /* It may not actually be necessary to set png_ptr->trans_alpha here; | 
|   846         * we do it for backward compatibility with the way the png_handle_tRNS |   923         * we do it for backward compatibility with the way the png_handle_tRNS | 
|   847         * function used to do the allocation. |   924         * function used to do the allocation. | 
 |   925         * | 
 |   926         * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively | 
 |   927         * relies on png_set_tRNS storing the information in png_struct | 
 |   928         * (otherwise it won't be there for the code in pngrtran.c). | 
|   848         */ |   929         */ | 
|   849  |   930  | 
|   850 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   851        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); |   931        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); | 
|   852 #endif |  | 
|   853  |   932  | 
|   854        /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ |   933        /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ | 
|   855        png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, |   934        png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep, | 
|   856            (png_uint_32)PNG_MAX_PALETTE_LENGTH); |   935          png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); | 
 |   936  | 
|   857        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) |   937        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) | 
|   858           png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); |   938           memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); | 
|   859    } |   939    } | 
|   860  |   940  | 
|   861    if (trans_values != NULL) |   941    if (trans_color != NULL) | 
|   862    { |   942    { | 
|   863       int sample_max = (1 << info_ptr->bit_depth); |   943       int sample_max = (1 << info_ptr->bit_depth); | 
 |   944  | 
|   864       if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && |   945       if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && | 
|   865           (int)trans_values->gray > sample_max) || |   946           trans_color->gray > sample_max) || | 
|   866           (info_ptr->color_type == PNG_COLOR_TYPE_RGB && |   947           (info_ptr->color_type == PNG_COLOR_TYPE_RGB && | 
|   867           ((int)trans_values->red > sample_max || |   948           (trans_color->red > sample_max || | 
|   868           (int)trans_values->green > sample_max || |   949           trans_color->green > sample_max || | 
|   869           (int)trans_values->blue > sample_max))) |   950           trans_color->blue > sample_max))) | 
|   870          png_warning(png_ptr, |   951          png_warning(png_ptr, | 
|   871             "tRNS chunk has out-of-range samples for bit_depth"); |   952             "tRNS chunk has out-of-range samples for bit_depth"); | 
|   872       png_memcpy(&(info_ptr->trans_values), trans_values, |   953  | 
|   873          png_sizeof(png_color_16)); |   954       info_ptr->trans_color = *trans_color; | 
 |   955  | 
|   874       if (num_trans == 0) |   956       if (num_trans == 0) | 
|   875          num_trans = 1; |   957          num_trans = 1; | 
|   876    } |   958    } | 
|   877  |   959  | 
|   878    info_ptr->num_trans = (png_uint_16)num_trans; |   960    info_ptr->num_trans = (png_uint_16)num_trans; | 
 |   961  | 
|   879    if (num_trans != 0) |   962    if (num_trans != 0) | 
|   880    { |   963    { | 
|   881       info_ptr->valid |= PNG_INFO_tRNS; |   964       info_ptr->valid |= PNG_INFO_tRNS; | 
|   882 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|   883       info_ptr->free_me |= PNG_FREE_TRNS; |   965       info_ptr->free_me |= PNG_FREE_TRNS; | 
|   884 #else |  | 
|   885       png_ptr->flags |= PNG_FLAG_FREE_TRNS; |  | 
|   886 #endif |  | 
|   887    } |   966    } | 
|   888 } |   967 } | 
|   889 #endif |   968 #endif | 
|   890  |   969  | 
|   891 #ifdef PNG_sPLT_SUPPORTED |   970 #ifdef PNG_sPLT_SUPPORTED | 
|   892 void PNGAPI |   971 void PNGAPI | 
|   893 png_set_sPLT(png_structp png_ptr, |   972 png_set_sPLT(png_const_structrp png_ptr, | 
|   894              png_infop info_ptr, png_sPLT_tp entries, int nentries) |   973     png_inforp info_ptr, png_const_sPLT_tp entries, int nentries) | 
|   895 /* |   974 /* | 
|   896  *  entries        - array of png_sPLT_t structures |   975  *  entries        - array of png_sPLT_t structures | 
|   897  *                   to be added to the list of palettes |   976  *                   to be added to the list of palettes | 
|   898  *                   in the info structure. |   977  *                   in the info structure. | 
 |   978  * | 
|   899  *  nentries       - number of palette structures to be |   979  *  nentries       - number of palette structures to be | 
|   900  *                   added. |   980  *                   added. | 
|   901  */ |   981  */ | 
|   902 { |   982 { | 
|   903    png_sPLT_tp np; |   983    png_sPLT_tp np; | 
|   904    int i; |   984  | 
|   905  |   985    if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) | 
|   906    if (png_ptr == NULL || info_ptr == NULL) |   986       return; | 
|   907       return; |   987  | 
|   908  |   988    /* Use the internal realloc function, which checks for all the possible | 
|   909    np = (png_sPLT_tp)png_malloc_warn(png_ptr, |   989     * overflows.  Notice that the parameters are (int) and (size_t) | 
|   910        (info_ptr->splt_palettes_num + nentries) * |   990     */ | 
|   911         (png_uint_32)png_sizeof(png_sPLT_t)); |   991    np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, | 
 |   992       info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, | 
 |   993       sizeof *np)); | 
 |   994  | 
|   912    if (np == NULL) |   995    if (np == NULL) | 
|   913    { |   996    { | 
|   914       png_warning(png_ptr, "No memory for sPLT palettes."); |   997       /* Out of memory or too many chunks */ | 
|   915       return; |   998       png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); | 
|   916    } |   999       return; | 
|   917  |  1000    } | 
|   918    png_memcpy(np, info_ptr->splt_palettes, |  1001  | 
|   919        info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); |  | 
|   920    png_free(png_ptr, info_ptr->splt_palettes); |  1002    png_free(png_ptr, info_ptr->splt_palettes); | 
|   921    info_ptr->splt_palettes=NULL; |  1003    info_ptr->splt_palettes = np; | 
|   922  |  1004    info_ptr->free_me |= PNG_FREE_SPLT; | 
|   923    for (i = 0; i < nentries; i++) |  1005  | 
|   924    { |  1006    np += info_ptr->splt_palettes_num; | 
|   925       png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; |  1007  | 
|   926       png_sPLT_tp from = entries + i; |  1008    do | 
|   927       png_uint_32 length; |  1009    { | 
|   928  |  1010       png_size_t length; | 
|   929       length = png_strlen(from->name) + 1; |  1011  | 
|   930       to->name = (png_charp)png_malloc_warn(png_ptr, length); |  1012       /* Skip invalid input entries */ | 
|   931       if (to->name == NULL) |  1013       if (entries->name == NULL || entries->entries == NULL) | 
|   932       { |  1014       { | 
|   933          png_warning(png_ptr, |  1015          /* png_handle_sPLT doesn't do this, so this is an app error */ | 
|   934            "Out of memory while processing sPLT chunk"); |  1016          png_app_error(png_ptr, "png_set_sPLT: invalid sPLT"); | 
 |  1017          /* Just skip the invalid entry */ | 
|   935          continue; |  1018          continue; | 
|   936       } |  1019       } | 
|   937       png_memcpy(to->name, from->name, length); |  1020  | 
|   938       to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, |  1021       np->depth = entries->depth; | 
|   939           (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry))); |  1022  | 
|   940       if (to->entries == NULL) |  1023       /* In the even of out-of-memory just return - there's no point keeping on | 
|   941       { |  1024        * trying to add sPLT chunks. | 
|   942          png_warning(png_ptr, |  1025        */ | 
|   943            "Out of memory while processing sPLT chunk"); |  1026       length = strlen(entries->name) + 1; | 
|   944          png_free(png_ptr, to->name); |  1027       np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length)); | 
|   945          to->name = NULL; |  1028  | 
|   946          continue; |  1029       if (np->name == NULL) | 
|   947       } |  1030          break; | 
|   948       png_memcpy(to->entries, from->entries, |  1031  | 
|   949           from->nentries * png_sizeof(png_sPLT_entry)); |  1032       memcpy(np->name, entries->name, length); | 
|   950       to->nentries = from->nentries; |  1033  | 
|   951       to->depth = from->depth; |  1034       /* IMPORTANT: we have memory now that won't get freed if something else | 
|   952    } |  1035        * goes wrong, this code must free it.  png_malloc_array produces no | 
|   953  |  1036        * warnings, use a png_chunk_report (below) if there is an error. | 
|   954    info_ptr->splt_palettes = np; |  1037        */ | 
|   955    info_ptr->splt_palettes_num += nentries; |  1038       np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr, | 
|   956    info_ptr->valid |= PNG_INFO_sPLT; |  1039           entries->nentries, sizeof (png_sPLT_entry))); | 
|   957 #ifdef PNG_FREE_ME_SUPPORTED |  1040  | 
|   958    info_ptr->free_me |= PNG_FREE_SPLT; |  1041       if (np->entries == NULL) | 
 |  1042       { | 
 |  1043          png_free(png_ptr, np->name); | 
 |  1044          break; | 
 |  1045       } | 
 |  1046  | 
 |  1047       np->nentries = entries->nentries; | 
 |  1048       /* This multiply can't overflow because png_malloc_array has already | 
 |  1049        * checked it when doing the allocation. | 
 |  1050        */ | 
 |  1051       memcpy(np->entries, entries->entries, | 
 |  1052          entries->nentries * sizeof (png_sPLT_entry)); | 
 |  1053  | 
 |  1054       /* Note that 'continue' skips the advance of the out pointer and out | 
 |  1055        * count, so an invalid entry is not added. | 
 |  1056        */ | 
 |  1057       info_ptr->valid |= PNG_INFO_sPLT; | 
 |  1058       ++(info_ptr->splt_palettes_num); | 
 |  1059       ++np; | 
 |  1060    } | 
 |  1061    while (++entries, --nentries); | 
 |  1062  | 
 |  1063    if (nentries > 0) | 
 |  1064       png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); | 
 |  1065 } | 
 |  1066 #endif /* PNG_sPLT_SUPPORTED */ | 
 |  1067  | 
 |  1068 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED | 
 |  1069 static png_byte | 
 |  1070 check_location(png_const_structrp png_ptr, int location) | 
 |  1071 { | 
 |  1072    location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT); | 
 |  1073  | 
 |  1074    /* New in 1.6.0; copy the location and check it.  This is an API | 
 |  1075     * change, previously the app had to use the | 
 |  1076     * png_set_unknown_chunk_location API below for each chunk. | 
 |  1077     */ | 
 |  1078    if (location == 0 && !(png_ptr->mode & PNG_IS_READ_STRUCT)) | 
 |  1079    { | 
 |  1080       /* Write struct, so unknown chunks come from the app */ | 
 |  1081       png_app_warning(png_ptr, | 
 |  1082          "png_set_unknown_chunks now expects a valid location"); | 
 |  1083       /* Use the old behavior */ | 
 |  1084       location = (png_byte)(png_ptr->mode & | 
 |  1085          (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); | 
 |  1086    } | 
 |  1087  | 
 |  1088    /* This need not be an internal error - if the app calls | 
 |  1089     * png_set_unknown_chunks on a read pointer it must get the location right. | 
 |  1090     */ | 
 |  1091    if (location == 0) | 
 |  1092       png_error(png_ptr, "invalid location in png_set_unknown_chunks"); | 
 |  1093  | 
 |  1094    /* Now reduce the location to the top-most set bit by removing each least | 
 |  1095     * significant bit in turn. | 
 |  1096     */ | 
 |  1097    while (location != (location & -location)) | 
 |  1098       location &= ~(location & -location); | 
 |  1099  | 
 |  1100    /* The cast is safe because 'location' is a bit mask and only the low four | 
 |  1101     * bits are significant. | 
 |  1102     */ | 
 |  1103    return (png_byte)location; | 
 |  1104 } | 
 |  1105  | 
 |  1106 void PNGAPI | 
 |  1107 png_set_unknown_chunks(png_const_structrp png_ptr, | 
 |  1108    png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) | 
 |  1109 { | 
 |  1110    png_unknown_chunkp np; | 
 |  1111  | 
 |  1112    if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 || | 
 |  1113       unknowns == NULL) | 
 |  1114       return; | 
 |  1115  | 
 |  1116    /* Check for the failure cases where support has been disabled at compile | 
 |  1117     * time.  This code is hardly ever compiled - it's here because | 
 |  1118     * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this | 
 |  1119     * code) but may be meaningless if the read or write handling of unknown | 
 |  1120     * chunks is not compiled in. | 
 |  1121     */ | 
 |  1122 #  if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \ | 
 |  1123       defined(PNG_READ_SUPPORTED) | 
 |  1124       if (png_ptr->mode & PNG_IS_READ_STRUCT) | 
 |  1125       { | 
 |  1126          png_app_error(png_ptr, "no unknown chunk support on read"); | 
 |  1127          return; | 
 |  1128       } | 
 |  1129 #  endif | 
 |  1130 #  if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \ | 
 |  1131       defined(PNG_WRITE_SUPPORTED) | 
 |  1132       if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) | 
 |  1133       { | 
 |  1134          png_app_error(png_ptr, "no unknown chunk support on write"); | 
 |  1135          return; | 
 |  1136       } | 
 |  1137 #  endif | 
 |  1138  | 
 |  1139    /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that | 
 |  1140     * unknown critical chunks could be lost with just a warning resulting in | 
 |  1141     * undefined behavior.  Now png_chunk_report is used to provide behavior | 
 |  1142     * appropriate to read or write. | 
 |  1143     */ | 
 |  1144    np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, | 
 |  1145          info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, | 
 |  1146          sizeof *np)); | 
 |  1147  | 
 |  1148    if (np == NULL) | 
 |  1149    { | 
 |  1150       png_chunk_report(png_ptr, "too many unknown chunks", | 
 |  1151          PNG_CHUNK_WRITE_ERROR); | 
 |  1152       return; | 
 |  1153    } | 
 |  1154  | 
 |  1155    png_free(png_ptr, info_ptr->unknown_chunks); | 
 |  1156    info_ptr->unknown_chunks = np; /* safe because it is initialized */ | 
 |  1157    info_ptr->free_me |= PNG_FREE_UNKN; | 
 |  1158  | 
 |  1159    np += info_ptr->unknown_chunks_num; | 
 |  1160  | 
 |  1161    /* Increment unknown_chunks_num each time round the loop to protect the | 
 |  1162     * just-allocated chunk data. | 
 |  1163     */ | 
 |  1164    for (; num_unknowns > 0; --num_unknowns, ++unknowns) | 
 |  1165    { | 
 |  1166       memcpy(np->name, unknowns->name, (sizeof np->name)); | 
 |  1167       np->name[(sizeof np->name)-1] = '\0'; | 
 |  1168       np->location = check_location(png_ptr, unknowns->location); | 
 |  1169  | 
 |  1170       if (unknowns->size == 0) | 
 |  1171       { | 
 |  1172          np->data = NULL; | 
 |  1173          np->size = 0; | 
 |  1174       } | 
 |  1175  | 
 |  1176       else | 
 |  1177       { | 
 |  1178          np->data = png_voidcast(png_bytep, | 
 |  1179             png_malloc_base(png_ptr, unknowns->size)); | 
 |  1180  | 
 |  1181          if (np->data == NULL) | 
 |  1182          { | 
 |  1183             png_chunk_report(png_ptr, "unknown chunk: out of memory", | 
 |  1184                PNG_CHUNK_WRITE_ERROR); | 
 |  1185             /* But just skip storing the unknown chunk */ | 
 |  1186             continue; | 
 |  1187          } | 
 |  1188  | 
 |  1189          memcpy(np->data, unknowns->data, unknowns->size); | 
 |  1190          np->size = unknowns->size; | 
 |  1191       } | 
 |  1192  | 
 |  1193       /* These increments are skipped on out-of-memory for the data - the | 
 |  1194        * unknown chunk entry gets overwritten if the png_chunk_report returns. | 
 |  1195        * This is correct in the read case (the chunk is just dropped.) | 
 |  1196        */ | 
 |  1197       ++np; | 
 |  1198       ++(info_ptr->unknown_chunks_num); | 
 |  1199    } | 
 |  1200 } | 
 |  1201  | 
 |  1202 void PNGAPI | 
 |  1203 png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |  1204     int chunk, int location) | 
 |  1205 { | 
 |  1206    /* This API is pretty pointless in 1.6.0 because the location can be set | 
 |  1207     * before the call to png_set_unknown_chunks. | 
 |  1208     * | 
 |  1209     * TODO: add a png_app_warning in 1.7 | 
 |  1210     */ | 
 |  1211    if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && | 
 |  1212       chunk < info_ptr->unknown_chunks_num) | 
 |  1213    { | 
 |  1214       if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0) | 
 |  1215       { | 
 |  1216          png_app_error(png_ptr, "invalid unknown chunk location"); | 
 |  1217          /* Fake out the pre 1.6.0 behavior: */ | 
 |  1218          if ((location & PNG_HAVE_IDAT)) /* undocumented! */ | 
 |  1219             location = PNG_AFTER_IDAT; | 
 |  1220  | 
 |  1221          else | 
 |  1222             location = PNG_HAVE_IHDR; /* also undocumented */ | 
 |  1223       } | 
 |  1224  | 
 |  1225       info_ptr->unknown_chunks[chunk].location = | 
 |  1226          check_location(png_ptr, location); | 
 |  1227    } | 
 |  1228 } | 
|   959 #endif |  1229 #endif | 
|   960 } |  1230  | 
|   961 #endif /* PNG_sPLT_SUPPORTED */ |  | 
|   962  |  | 
|   963 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED |  | 
|   964 void PNGAPI |  | 
|   965 png_set_unknown_chunks(png_structp png_ptr, |  | 
|   966    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) |  | 
|   967 { |  | 
|   968    png_unknown_chunkp np; |  | 
|   969    int i; |  | 
|   970  |  | 
|   971    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) |  | 
|   972       return; |  | 
|   973  |  | 
|   974    np = (png_unknown_chunkp)png_malloc_warn(png_ptr, |  | 
|   975        (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) * |  | 
|   976        png_sizeof(png_unknown_chunk))); |  | 
|   977    if (np == NULL) |  | 
|   978    { |  | 
|   979       png_warning(png_ptr, |  | 
|   980           "Out of memory while processing unknown chunk."); |  | 
|   981       return; |  | 
|   982    } |  | 
|   983  |  | 
|   984    png_memcpy(np, info_ptr->unknown_chunks, |  | 
|   985        info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); |  | 
|   986    png_free(png_ptr, info_ptr->unknown_chunks); |  | 
|   987    info_ptr->unknown_chunks = NULL; |  | 
|   988  |  | 
|   989    for (i = 0; i < num_unknowns; i++) |  | 
|   990    { |  | 
|   991       png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; |  | 
|   992       png_unknown_chunkp from = unknowns + i; |  | 
|   993  |  | 
|   994       png_memcpy((png_charp)to->name, (png_charp)from->name, |  | 
|   995           png_sizeof(from->name)); |  | 
|   996       to->name[png_sizeof(to->name)-1] = '\0'; |  | 
|   997       to->size = from->size; |  | 
|   998       /* Note our location in the read or write sequence */ |  | 
|   999       to->location = (png_byte)(png_ptr->mode & 0xff); |  | 
|  1000  |  | 
|  1001       if (from->size == 0) |  | 
|  1002          to->data=NULL; |  | 
|  1003       else |  | 
|  1004       { |  | 
|  1005          to->data = (png_bytep)png_malloc_warn(png_ptr, |  | 
|  1006            (png_uint_32)from->size); |  | 
|  1007          if (to->data == NULL) |  | 
|  1008          { |  | 
|  1009             png_warning(png_ptr, |  | 
|  1010              "Out of memory while processing unknown chunk."); |  | 
|  1011             to->size = 0; |  | 
|  1012          } |  | 
|  1013          else |  | 
|  1014             png_memcpy(to->data, from->data, from->size); |  | 
|  1015       } |  | 
|  1016    } |  | 
|  1017  |  | 
|  1018    info_ptr->unknown_chunks = np; |  | 
|  1019    info_ptr->unknown_chunks_num += num_unknowns; |  | 
|  1020 #ifdef PNG_FREE_ME_SUPPORTED |  | 
|  1021    info_ptr->free_me |= PNG_FREE_UNKN; |  | 
|  1022 #endif |  | 
|  1023 } |  | 
|  1024 void PNGAPI |  | 
|  1025 png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, |  | 
|  1026    int chunk, int location) |  | 
|  1027 { |  | 
|  1028    if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < |  | 
|  1029        (int)info_ptr->unknown_chunks_num) |  | 
|  1030       info_ptr->unknown_chunks[chunk].location = (png_byte)location; |  | 
|  1031 } |  | 
|  1032 #endif |  | 
|  1033  |  | 
|  1034 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) |  | 
|  1035 #if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ |  | 
|  1036     defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) |  | 
|  1037 void PNGAPI |  | 
|  1038 png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) |  | 
|  1039 { |  | 
|  1040    /* This function is deprecated in favor of png_permit_mng_features() |  | 
|  1041       and will be removed from libpng-1.3.0 */ |  | 
|  1042  |  | 
|  1043    png_debug(1, "in png_permit_empty_plte, DEPRECATED."); |  | 
|  1044  |  | 
|  1045    if (png_ptr == NULL) |  | 
|  1046       return; |  | 
|  1047    png_ptr->mng_features_permitted = (png_byte) |  | 
|  1048      ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) | |  | 
|  1049      ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); |  | 
|  1050 } |  | 
|  1051 #endif |  | 
|  1052 #endif |  | 
|  1053  |  1231  | 
|  1054 #ifdef PNG_MNG_FEATURES_SUPPORTED |  1232 #ifdef PNG_MNG_FEATURES_SUPPORTED | 
|  1055 png_uint_32 PNGAPI |  1233 png_uint_32 PNGAPI | 
|  1056 png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) |  1234 png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) | 
|  1057 { |  1235 { | 
|  1058    png_debug(1, "in png_permit_mng_features"); |  1236    png_debug(1, "in png_permit_mng_features"); | 
|  1059  |  1237  | 
|  1060    if (png_ptr == NULL) |  1238    if (png_ptr == NULL) | 
|  1061       return (png_uint_32)0; |  1239       return 0; | 
|  1062    png_ptr->mng_features_permitted = |  1240  | 
|  1063      (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); |  1241    png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES; | 
|  1064    return (png_uint_32)png_ptr->mng_features_permitted; |  1242  | 
 |  1243    return png_ptr->mng_features_permitted; | 
|  1065 } |  1244 } | 
|  1066 #endif |  1245 #endif | 
|  1067  |  1246  | 
|  1068 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED |  1247 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | 
 |  1248 static unsigned int | 
 |  1249 add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) | 
 |  1250 { | 
 |  1251    unsigned int i; | 
 |  1252  | 
 |  1253    /* Utility function: update the 'keep' state of a chunk if it is already in | 
 |  1254     * the list, otherwise add it to the list. | 
 |  1255     */ | 
 |  1256    for (i=0; i<count; ++i, list += 5) if (memcmp(list, add, 4) == 0) | 
 |  1257    { | 
 |  1258       list[4] = (png_byte)keep; | 
 |  1259       return count; | 
 |  1260    } | 
 |  1261  | 
 |  1262    if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT) | 
 |  1263    { | 
 |  1264       ++count; | 
 |  1265       memcpy(list, add, 4); | 
 |  1266       list[4] = (png_byte)keep; | 
 |  1267    } | 
 |  1268  | 
 |  1269    return count; | 
 |  1270 } | 
 |  1271  | 
|  1069 void PNGAPI |  1272 void PNGAPI | 
|  1070 png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep |  1273 png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, | 
|  1071    chunk_list, int num_chunks) |  1274     png_const_bytep chunk_list, int num_chunks_in) | 
|  1072 { |  1275 { | 
|  1073    png_bytep new_list, p; |  1276    png_bytep new_list; | 
|  1074    int i, old_num_chunks; |  1277    unsigned int num_chunks, old_num_chunks; | 
 |  1278  | 
|  1075    if (png_ptr == NULL) |  1279    if (png_ptr == NULL) | 
|  1076       return; |  1280       return; | 
|  1077    if (num_chunks == 0) |  1281  | 
|  1078    { |  1282    if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST) | 
|  1079       if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) |  1283    { | 
|  1080          png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; |  1284       png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); | 
|  1081       else |  1285       return; | 
|  1082          png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; |  1286    } | 
|  1083  |  1287  | 
|  1084       if (keep == PNG_HANDLE_CHUNK_ALWAYS) |  1288    if (num_chunks_in <= 0) | 
|  1085          png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; |  1289    { | 
|  1086       else |  1290       png_ptr->unknown_default = keep; | 
|  1087          png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; |  1291  | 
|  1088       return; |  1292       /* '0' means just set the flags, so stop here */ | 
|  1089    } |  1293       if (num_chunks_in == 0) | 
|  1090    if (chunk_list == NULL) |  1294         return; | 
|  1091       return; |  1295    } | 
 |  1296  | 
 |  1297    if (num_chunks_in < 0) | 
 |  1298    { | 
 |  1299       /* Ignore all unknown chunks and all chunks recognized by | 
 |  1300        * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND | 
 |  1301        */ | 
 |  1302       static PNG_CONST png_byte chunks_to_ignore[] = { | 
 |  1303          98,  75,  71,  68, '\0',  /* bKGD */ | 
 |  1304          99,  72,  82,  77, '\0',  /* cHRM */ | 
 |  1305         103,  65,  77,  65, '\0',  /* gAMA */ | 
 |  1306         104,  73,  83,  84, '\0',  /* hIST */ | 
 |  1307         105,  67,  67,  80, '\0',  /* iCCP */ | 
 |  1308         105,  84,  88, 116, '\0',  /* iTXt */ | 
 |  1309         111,  70,  70, 115, '\0',  /* oFFs */ | 
 |  1310         112,  67,  65,  76, '\0',  /* pCAL */ | 
 |  1311         112,  72,  89, 115, '\0',  /* pHYs */ | 
 |  1312         115,  66,  73,  84, '\0',  /* sBIT */ | 
 |  1313         115,  67,  65,  76, '\0',  /* sCAL */ | 
 |  1314         115,  80,  76,  84, '\0',  /* sPLT */ | 
 |  1315         115,  84,  69,  82, '\0',  /* sTER */ | 
 |  1316         115,  82,  71,  66, '\0',  /* sRGB */ | 
 |  1317         116,  69,  88, 116, '\0',  /* tEXt */ | 
 |  1318         116,  73,  77,  69, '\0',  /* tIME */ | 
 |  1319         122,  84,  88, 116, '\0'   /* zTXt */ | 
 |  1320       }; | 
 |  1321  | 
 |  1322       chunk_list = chunks_to_ignore; | 
 |  1323       num_chunks = (sizeof chunks_to_ignore)/5; | 
 |  1324    } | 
 |  1325  | 
 |  1326    else /* num_chunks_in > 0 */ | 
 |  1327    { | 
 |  1328       if (chunk_list == NULL) | 
 |  1329       { | 
 |  1330          /* Prior to 1.6.0 this was silently ignored, now it is an app_error | 
 |  1331           * which can be switched off. | 
 |  1332           */ | 
 |  1333          png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); | 
 |  1334          return; | 
 |  1335       } | 
 |  1336  | 
 |  1337       num_chunks = num_chunks_in; | 
 |  1338    } | 
 |  1339  | 
|  1092    old_num_chunks = png_ptr->num_chunk_list; |  1340    old_num_chunks = png_ptr->num_chunk_list; | 
|  1093    new_list=(png_bytep)png_malloc(png_ptr, |  1341    if (png_ptr->chunk_list == NULL) | 
|  1094       (png_uint_32) |  1342       old_num_chunks = 0; | 
|  1095        (5*(num_chunks + old_num_chunks))); |  1343  | 
|  1096    if (png_ptr->chunk_list != NULL) |  1344    /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow. | 
|  1097    { |  1345     */ | 
|  1098       png_memcpy(new_list, png_ptr->chunk_list, |  1346    if (num_chunks + old_num_chunks > UINT_MAX/5) | 
|  1099           (png_size_t)(5*old_num_chunks)); |  1347    { | 
|  1100       png_free(png_ptr, png_ptr->chunk_list); |  1348       png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); | 
|  1101       png_ptr->chunk_list=NULL; |  1349       return; | 
|  1102    } |  1350    } | 
|  1103    png_memcpy(new_list + 5*old_num_chunks, chunk_list, |  1351  | 
|  1104        (png_size_t)(5*num_chunks)); |  1352    /* If these chunks are being reset to the default then no more memory is | 
|  1105    for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5) |  1353     * required because add_one_chunk above doesn't extend the list if the 'keep' | 
|  1106       *p=(png_byte)keep; |  1354     * parameter is the default. | 
|  1107    png_ptr->num_chunk_list = old_num_chunks + num_chunks; |  1355     */ | 
|  1108    png_ptr->chunk_list = new_list; |  1356    if (keep) | 
|  1109 #ifdef PNG_FREE_ME_SUPPORTED |  1357    { | 
|  1110    png_ptr->free_me |= PNG_FREE_LIST; |  1358       new_list = png_voidcast(png_bytep, png_malloc(png_ptr, | 
|  1111 #endif |  1359           5 * (num_chunks + old_num_chunks))); | 
 |  1360  | 
 |  1361       if (old_num_chunks > 0) | 
 |  1362          memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); | 
 |  1363    } | 
 |  1364  | 
 |  1365    else if (old_num_chunks > 0) | 
 |  1366       new_list = png_ptr->chunk_list; | 
 |  1367  | 
 |  1368    else | 
 |  1369       new_list = NULL; | 
 |  1370  | 
 |  1371    /* Add the new chunks together with each one's handling code.  If the chunk | 
 |  1372     * already exists the code is updated, otherwise the chunk is added to the | 
 |  1373     * end.  (In libpng 1.6.0 order no longer matters because this code enforces | 
 |  1374     * the earlier convention that the last setting is the one that is used.) | 
 |  1375     */ | 
 |  1376    if (new_list != NULL) | 
 |  1377    { | 
 |  1378       png_const_bytep inlist; | 
 |  1379       png_bytep outlist; | 
 |  1380       unsigned int i; | 
 |  1381  | 
 |  1382       for (i=0; i<num_chunks; ++i) | 
 |  1383          old_num_chunks = add_one_chunk(new_list, old_num_chunks, | 
 |  1384             chunk_list+5*i, keep); | 
 |  1385  | 
 |  1386       /* Now remove any spurious 'default' entries. */ | 
 |  1387       num_chunks = 0; | 
 |  1388       for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5) | 
 |  1389          if (inlist[4]) | 
 |  1390          { | 
 |  1391             if (outlist != inlist) | 
 |  1392                memcpy(outlist, inlist, 5); | 
 |  1393             outlist += 5; | 
 |  1394             ++num_chunks; | 
 |  1395          } | 
 |  1396  | 
 |  1397       /* This means the application has removed all the specialized handling. */ | 
 |  1398       if (num_chunks == 0) | 
 |  1399       { | 
 |  1400          if (png_ptr->chunk_list != new_list) | 
 |  1401             png_free(png_ptr, new_list); | 
 |  1402  | 
 |  1403          new_list = NULL; | 
 |  1404       } | 
 |  1405    } | 
 |  1406  | 
 |  1407    else | 
 |  1408       num_chunks = 0; | 
 |  1409  | 
 |  1410    png_ptr->num_chunk_list = num_chunks; | 
 |  1411  | 
 |  1412    if (png_ptr->chunk_list != new_list) | 
 |  1413    { | 
 |  1414       if (png_ptr->chunk_list != NULL) | 
 |  1415          png_free(png_ptr, png_ptr->chunk_list); | 
 |  1416  | 
 |  1417       png_ptr->chunk_list = new_list; | 
 |  1418    } | 
|  1112 } |  1419 } | 
|  1113 #endif |  1420 #endif | 
|  1114  |  1421  | 
|  1115 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED |  1422 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED | 
|  1116 void PNGAPI |  1423 void PNGAPI | 
|  1117 png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, |  1424 png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr, | 
|  1118    png_user_chunk_ptr read_user_chunk_fn) |  1425     png_user_chunk_ptr read_user_chunk_fn) | 
|  1119 { |  1426 { | 
|  1120    png_debug(1, "in png_set_read_user_chunk_fn"); |  1427    png_debug(1, "in png_set_read_user_chunk_fn"); | 
|  1121  |  1428  | 
|  1122    if (png_ptr == NULL) |  1429    if (png_ptr == NULL) | 
|  1123       return; |  1430       return; | 
|  1124  |  1431  | 
|  1125    png_ptr->read_user_chunk_fn = read_user_chunk_fn; |  1432    png_ptr->read_user_chunk_fn = read_user_chunk_fn; | 
|  1126    png_ptr->user_chunk_ptr = user_chunk_ptr; |  1433    png_ptr->user_chunk_ptr = user_chunk_ptr; | 
|  1127 } |  1434 } | 
|  1128 #endif |  1435 #endif | 
|  1129  |  1436  | 
|  1130 #ifdef PNG_INFO_IMAGE_SUPPORTED |  1437 #ifdef PNG_INFO_IMAGE_SUPPORTED | 
|  1131 void PNGAPI |  1438 void PNGAPI | 
|  1132 png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) |  1439 png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, | 
 |  1440     png_bytepp row_pointers) | 
|  1133 { |  1441 { | 
|  1134    png_debug1(1, "in %s storage function", "rows"); |  1442    png_debug1(1, "in %s storage function", "rows"); | 
|  1135  |  1443  | 
|  1136    if (png_ptr == NULL || info_ptr == NULL) |  1444    if (png_ptr == NULL || info_ptr == NULL) | 
|  1137       return; |  1445       return; | 
|  1138  |  1446  | 
|  1139    if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) |  1447    if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) | 
|  1140       png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); |  1448       png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); | 
 |  1449  | 
|  1141    info_ptr->row_pointers = row_pointers; |  1450    info_ptr->row_pointers = row_pointers; | 
 |  1451  | 
|  1142    if (row_pointers) |  1452    if (row_pointers) | 
|  1143       info_ptr->valid |= PNG_INFO_IDAT; |  1453       info_ptr->valid |= PNG_INFO_IDAT; | 
|  1144 } |  1454 } | 
|  1145 #endif |  1455 #endif | 
|  1146  |  1456  | 
|  1147 void PNGAPI |  1457 void PNGAPI | 
|  1148 png_set_compression_buffer_size(png_structp png_ptr, |  1458 png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) | 
|  1149     png_uint_32 size) |  | 
|  1150 { |  1459 { | 
|  1151     if (png_ptr == NULL) |  1460     if (png_ptr == NULL) | 
|  1152        return; |  1461        return; | 
|  1153     png_free(png_ptr, png_ptr->zbuf); |  1462  | 
|  1154     png_ptr->zbuf_size = (png_size_t)size; |  1463     if (size == 0 || size > PNG_UINT_31_MAX) | 
|  1155     png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); |  1464        png_error(png_ptr, "invalid compression buffer size"); | 
|  1156     png_ptr->zstream.next_out = png_ptr->zbuf; |  1465  | 
|  1157     png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |  1466 #  ifdef PNG_SEQUENTIAL_READ_SUPPORTED | 
 |  1467       if (png_ptr->mode & PNG_IS_READ_STRUCT) | 
 |  1468       { | 
 |  1469          png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ | 
 |  1470          return; | 
 |  1471       } | 
 |  1472 #  endif | 
 |  1473  | 
 |  1474 #  ifdef PNG_WRITE_SUPPORTED | 
 |  1475       if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) | 
 |  1476       { | 
 |  1477          if (png_ptr->zowner != 0) | 
 |  1478          { | 
 |  1479             png_warning(png_ptr, | 
 |  1480               "Compression buffer size cannot be changed because it is in use"); | 
 |  1481             return; | 
 |  1482          } | 
 |  1483  | 
 |  1484          if (size > ZLIB_IO_MAX) | 
 |  1485          { | 
 |  1486             png_warning(png_ptr, | 
 |  1487                "Compression buffer size limited to system maximum"); | 
 |  1488             size = ZLIB_IO_MAX; /* must fit */ | 
 |  1489          } | 
 |  1490  | 
 |  1491          else if (size < 6) | 
 |  1492          { | 
 |  1493             /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH | 
 |  1494              * if this is permitted. | 
 |  1495              */ | 
 |  1496             png_warning(png_ptr, | 
 |  1497                "Compression buffer size cannot be reduced below 6"); | 
 |  1498             return; | 
 |  1499          } | 
 |  1500  | 
 |  1501          if (png_ptr->zbuffer_size != size) | 
 |  1502          { | 
 |  1503             png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); | 
 |  1504             png_ptr->zbuffer_size = (uInt)size; | 
 |  1505          } | 
 |  1506       } | 
 |  1507 #  endif | 
|  1158 } |  1508 } | 
|  1159  |  1509  | 
|  1160 void PNGAPI |  1510 void PNGAPI | 
|  1161 png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) |  1511 png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) | 
|  1162 { |  1512 { | 
|  1163    if (png_ptr && info_ptr) |  1513    if (png_ptr && info_ptr) | 
|  1164       info_ptr->valid &= ~mask; |  1514       info_ptr->valid &= ~mask; | 
|  1165 } |  1515 } | 
|  1166  |  1516  | 
|  1167  |  1517  | 
|  1168 #ifndef PNG_1_0_X |  | 
|  1169 #ifdef PNG_ASSEMBLER_CODE_SUPPORTED |  | 
|  1170 /* Function was added to libpng 1.2.0 and should always exist by default */ |  | 
|  1171 void PNGAPI |  | 
|  1172 png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) |  | 
|  1173 { |  | 
|  1174 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ |  | 
|  1175     if (png_ptr != NULL) |  | 
|  1176     png_ptr->asm_flags = 0; |  | 
|  1177     asm_flags = asm_flags; /* Quiet the compiler */ |  | 
|  1178 } |  | 
|  1179  |  | 
|  1180 /* This function was added to libpng 1.2.0 */ |  | 
|  1181 void PNGAPI |  | 
|  1182 png_set_mmx_thresholds (png_structp png_ptr, |  | 
|  1183                         png_byte mmx_bitdepth_threshold, |  | 
|  1184                         png_uint_32 mmx_rowbytes_threshold) |  | 
|  1185 { |  | 
|  1186 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ |  | 
|  1187     if (png_ptr == NULL) |  | 
|  1188        return; |  | 
|  1189     /* Quiet the compiler */ |  | 
|  1190     mmx_bitdepth_threshold = mmx_bitdepth_threshold; |  | 
|  1191     mmx_rowbytes_threshold = mmx_rowbytes_threshold; |  | 
|  1192 } |  | 
|  1193 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ |  | 
|  1194  |  | 
|  1195 #ifdef PNG_SET_USER_LIMITS_SUPPORTED |  1518 #ifdef PNG_SET_USER_LIMITS_SUPPORTED | 
|  1196 /* This function was added to libpng 1.2.6 */ |  1519 /* This function was added to libpng 1.2.6 */ | 
|  1197 void PNGAPI |  1520 void PNGAPI | 
|  1198 png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, |  1521 png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, | 
|  1199     png_uint_32 user_height_max) |  1522     png_uint_32 user_height_max) | 
|  1200 { |  1523 { | 
|  1201    /* Images with dimensions larger than these limits will be |  1524    /* Images with dimensions larger than these limits will be | 
|  1202     * rejected by png_set_IHDR().  To accept any PNG datastream |  1525     * rejected by png_set_IHDR().  To accept any PNG datastream | 
|  1203     * regardless of dimensions, set both limits to 0x7ffffffL. |  1526     * regardless of dimensions, set both limits to 0x7ffffffL. | 
|  1204     */ |  1527     */ | 
|  1205    if (png_ptr == NULL) |  1528    if (png_ptr == NULL) | 
|  1206       return; |  1529       return; | 
 |  1530  | 
|  1207    png_ptr->user_width_max = user_width_max; |  1531    png_ptr->user_width_max = user_width_max; | 
|  1208    png_ptr->user_height_max = user_height_max; |  1532    png_ptr->user_height_max = user_height_max; | 
|  1209 } |  1533 } | 
 |  1534  | 
 |  1535 /* This function was added to libpng 1.4.0 */ | 
 |  1536 void PNGAPI | 
 |  1537 png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) | 
 |  1538 { | 
 |  1539     if (png_ptr) | 
 |  1540        png_ptr->user_chunk_cache_max = user_chunk_cache_max; | 
 |  1541 } | 
 |  1542  | 
 |  1543 /* This function was added to libpng 1.4.1 */ | 
 |  1544 void PNGAPI | 
 |  1545 png_set_chunk_malloc_max (png_structrp png_ptr, | 
 |  1546     png_alloc_size_t user_chunk_malloc_max) | 
 |  1547 { | 
 |  1548    if (png_ptr) | 
 |  1549       png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; | 
 |  1550 } | 
|  1210 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ |  1551 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ | 
|  1211  |  1552  | 
|  1212  |  1553  | 
|  1213 #ifdef PNG_BENIGN_ERRORS_SUPPORTED |  1554 #ifdef PNG_BENIGN_ERRORS_SUPPORTED | 
|  1214 void PNGAPI |  1555 void PNGAPI | 
|  1215 png_set_benign_errors(png_structp png_ptr, int allowed) |  1556 png_set_benign_errors(png_structrp png_ptr, int allowed) | 
|  1216 { |  1557 { | 
|  1217    png_debug(1, "in png_set_benign_errors"); |  1558    png_debug(1, "in png_set_benign_errors"); | 
|  1218  |  1559  | 
 |  1560    /* If allowed is 1, png_benign_error() is treated as a warning. | 
 |  1561     * | 
 |  1562     * If allowed is 0, png_benign_error() is treated as an error (which | 
 |  1563     * is the default behavior if png_set_benign_errors() is not called). | 
 |  1564     */ | 
 |  1565  | 
|  1219    if (allowed) |  1566    if (allowed) | 
|  1220       png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; |  1567       png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN | | 
 |  1568          PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN; | 
 |  1569  | 
|  1221    else |  1570    else | 
|  1222       png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; |  1571       png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN | | 
 |  1572          PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN); | 
|  1223 } |  1573 } | 
|  1224 #endif /* PNG_BENIGN_ERRORS_SUPPORTED */ |  1574 #endif /* PNG_BENIGN_ERRORS_SUPPORTED */ | 
|  1225 #endif /* ?PNG_1_0_X */ |  1575  | 
 |  1576 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED | 
 |  1577    /* Whether to report invalid palette index; added at libng-1.5.10. | 
 |  1578     * It is possible for an indexed (color-type==3) PNG file to contain | 
 |  1579     * pixels with invalid (out-of-range) indexes if the PLTE chunk has | 
 |  1580     * fewer entries than the image's bit-depth would allow. We recover | 
 |  1581     * from this gracefully by filling any incomplete palette with zeroes | 
 |  1582     * (opaque black).  By default, when this occurs libpng will issue | 
 |  1583     * a benign error.  This API can be used to override that behavior. | 
 |  1584     */ | 
 |  1585 void PNGAPI | 
 |  1586 png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) | 
 |  1587 { | 
 |  1588    png_debug(1, "in png_set_check_for_invalid_index"); | 
 |  1589  | 
 |  1590    if (allowed > 0) | 
 |  1591       png_ptr->num_palette_max = 0; | 
 |  1592  | 
 |  1593    else | 
 |  1594       png_ptr->num_palette_max = -1; | 
 |  1595 } | 
 |  1596 #endif | 
|  1226 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ |  1597 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ | 
| OLD | NEW |