blob: 998473557f037f3b7839db85e6936bf1e6ae6be8 [file] [log] [blame]
Andreas Dilger47a0c421997-05-16 02:46:07 -05001
2/* pngset.c - storage of image information into info struct
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson9f7134c2017-06-29 17:49:59 -05004 * Last changed in libpng 1.6.30 [June 28, 2017]
Glenn Randers-Pehrsone744ee12017-03-30 12:24:55 -05005 * Copyright (c) 1998-2017 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -050012 *
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060013 * 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
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.
17 */
Andreas Dilger47a0c421997-05-16 02:46:07 -050018
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050019#include "pngpriv.h"
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060020
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060021#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
22
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -050023#ifdef PNG_bKGD_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050024void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -060025png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -050026 png_const_color_16p background)
Andreas Dilger47a0c421997-05-16 02:46:07 -050027{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050028 png_debug1(1, "in %s storage function", "bKGD");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050029
John Bowlerfcd301d2011-12-28 21:34:27 -060030 if (png_ptr == NULL || info_ptr == NULL || background == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -050031 return;
32
John Bowlerfcd301d2011-12-28 21:34:27 -060033 info_ptr->background = *background;
Andreas Dilger47a0c421997-05-16 02:46:07 -050034 info_ptr->valid |= PNG_INFO_bKGD;
35}
36#endif
37
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -050038#ifdef PNG_cHRM_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -050039void PNGFAPI
John Bowler4f67e402011-12-28 08:43:37 -060040png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -060041 png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
42 png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
43 png_fixed_point blue_x, png_fixed_point blue_y)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060044{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060045 png_xy xy;
46
Glenn Randers-Pehrsond6d80752008-12-02 09:49:43 -060047 png_debug1(1, "in %s storage function", "cHRM fixed");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050048
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060049 if (png_ptr == NULL || info_ptr == NULL)
50 return;
Andreas Dilger47a0c421997-05-16 02:46:07 -050051
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060052 xy.redx = red_x;
53 xy.redy = red_y;
54 xy.greenx = green_x;
55 xy.greeny = green_y;
56 xy.bluex = blue_x;
57 xy.bluey = blue_y;
58 xy.whitex = white_x;
59 xy.whitey = white_y;
60
61 if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -050062 2/* override with app values*/) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060063 info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
64
65 png_colorspace_sync_info(png_ptr, info_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060066}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -050067
John Bowler736f40f2011-08-25 16:19:44 -050068void PNGFAPI
John Bowler4f67e402011-12-28 08:43:37 -060069png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
John Bowler736f40f2011-08-25 16:19:44 -050070 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;
John Bowler736f40f2011-08-25 16:19:44 -050077
78 png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
79
80 if (png_ptr == NULL || info_ptr == NULL)
81 return;
82
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060083 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;
John Bowler736f40f2011-08-25 16:19:44 -050092
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -050093 if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
94 &XYZ, 2) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060095 info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
John Bowler736f40f2011-08-25 16:19:44 -050096
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060097 png_colorspace_sync_info(png_ptr, info_ptr);
John Bowler736f40f2011-08-25 16:19:44 -050098}
99
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500100# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500101void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600102png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500103 double white_x, double white_y, double red_x, double red_y,
104 double green_x, double green_y, double blue_x, double blue_y)
105{
106 png_set_cHRM_fixed(png_ptr, info_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500107 png_fixed(png_ptr, white_x, "cHRM White X"),
108 png_fixed(png_ptr, white_y, "cHRM White Y"),
109 png_fixed(png_ptr, red_x, "cHRM Red X"),
110 png_fixed(png_ptr, red_y, "cHRM Red Y"),
111 png_fixed(png_ptr, green_x, "cHRM Green X"),
112 png_fixed(png_ptr, green_y, "cHRM Green Y"),
113 png_fixed(png_ptr, blue_x, "cHRM Blue X"),
114 png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500115}
John Bowler736f40f2011-08-25 16:19:44 -0500116
117void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600118png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
John Bowler736f40f2011-08-25 16:19:44 -0500119 double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
120 double blue_X, double blue_Y, double blue_Z)
121{
122 png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500123 png_fixed(png_ptr, red_X, "cHRM Red X"),
124 png_fixed(png_ptr, red_Y, "cHRM Red Y"),
125 png_fixed(png_ptr, red_Z, "cHRM Red Z"),
126 png_fixed(png_ptr, green_X, "cHRM Green X"),
127 png_fixed(png_ptr, green_Y, "cHRM Green Y"),
128 png_fixed(png_ptr, green_Z, "cHRM Green Z"),
129 png_fixed(png_ptr, blue_X, "cHRM Blue X"),
130 png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
131 png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
John Bowler736f40f2011-08-25 16:19:44 -0500132}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600133# endif /* FLOATING_POINT */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500134
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600135#endif /* cHRM */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600136
Glenn Randers-Pehrson68cb0aa2017-07-13 11:19:53 -0500137#ifdef PNG_eXIf_SUPPORTED
138void PNGAPI
139png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
140 const png_bytep eXIf_buf)
141{
142 int i;
143
144 png_debug1(1, "in %s storage function", "eXIf");
145
146 if (png_ptr == NULL || info_ptr == NULL)
147 return;
148
149 png_free_data(png_ptr, info_ptr, PNG_FREE_EXIF, 0);
150
151 info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr,
152 info_ptr->num_exif));
153
154 if (info_ptr->exif == NULL)
155 {
156 png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
157
158 return;
159 }
160
161 info_ptr->free_me |= PNG_FREE_EXIF;
162
163 for (i = 0; i < info_ptr->num_exif; i++)
164 info_ptr->exif[i] = eXIf_buf[i];
165
166 info_ptr->valid |= PNG_INFO_eXIf;
167}
168#endif /* eXIf */
169
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500170#ifdef PNG_gAMA_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500171void PNGFAPI
John Bowler4f67e402011-12-28 08:43:37 -0600172png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
173 png_fixed_point file_gamma)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500174{
175 png_debug1(1, "in %s storage function", "gAMA");
176
177 if (png_ptr == NULL || info_ptr == NULL)
178 return;
179
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600180 png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
181 png_colorspace_sync_info(png_ptr, info_ptr);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500182}
183
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500184# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500185void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600186png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500187{
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500188 png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500189 "png_set_gAMA"));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500190}
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500191# endif
Glenn Randers-Pehrsona272d8f2010-06-25 21:45:31 -0500192#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500193
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500194#ifdef PNG_hIST_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500195void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600196png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
197 png_const_uint_16p hist)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500198{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500199 int i;
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600200
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500201 png_debug1(1, "in %s storage function", "hIST");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500202
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600203 if (png_ptr == NULL || info_ptr == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500204 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500205
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500206 if (info_ptr->num_palette == 0 || info_ptr->num_palette
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600207 > PNG_MAX_PALETTE_LENGTH)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500208 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500209 png_warning(png_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -0600210 "Invalid palette size, hIST allocation skipped");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500211
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500212 return;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500213 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500214
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600215 png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500216
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500217 /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
218 * version 1.2.1
219 */
John Bowler4f67e402011-12-28 08:43:37 -0600220 info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600221 PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500222
John Bowler4f67e402011-12-28 08:43:37 -0600223 if (info_ptr->hist == NULL)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500224 {
225 png_warning(png_ptr, "Insufficient memory for hIST chunk data");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600226
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500227 return;
228 }
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600229
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600230 info_ptr->free_me |= PNG_FREE_HIST;
John Bowler4f67e402011-12-28 08:43:37 -0600231
232 for (i = 0; i < info_ptr->num_palette; i++)
233 info_ptr->hist[i] = hist[i];
234
235 info_ptr->valid |= PNG_INFO_hIST;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500236}
237#endif
238
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500239void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600240png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500241 png_uint_32 width, png_uint_32 height, int bit_depth,
242 int color_type, int interlace_type, int compression_type,
243 int filter_type)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500244{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500245 png_debug1(1, "in %s storage function", "IHDR");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500246
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600247 if (png_ptr == NULL || info_ptr == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500248 return;
249
250 info_ptr->width = width;
251 info_ptr->height = height;
252 info_ptr->bit_depth = (png_byte)bit_depth;
Glenn Randers-Pehrsonb35a7452009-09-30 23:12:13 -0500253 info_ptr->color_type = (png_byte)color_type;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500254 info_ptr->compression_type = (png_byte)compression_type;
255 info_ptr->filter_type = (png_byte)filter_type;
256 info_ptr->interlace_type = (png_byte)interlace_type;
Glenn Randers-Pehrsonb35a7452009-09-30 23:12:13 -0500257
258 png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
259 info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
260 info_ptr->compression_type, info_ptr->filter_type);
261
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500262 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
263 info_ptr->channels = 1;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500264
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500265 else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500266 info_ptr->channels = 3;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500267
Andreas Dilger47a0c421997-05-16 02:46:07 -0500268 else
269 info_ptr->channels = 1;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500270
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500271 if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500272 info_ptr->channels++;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500273
Andreas Dilger47a0c421997-05-16 02:46:07 -0500274 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600275
Glenn Randers-Pehrson421f95d2013-06-04 15:05:12 -0500276 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500277}
278
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500279#ifdef PNG_oFFs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500280void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600281png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -0600282 png_int_32 offset_x, png_int_32 offset_y, int unit_type)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500283{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500284 png_debug1(1, "in %s storage function", "oFFs");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500285
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600286 if (png_ptr == NULL || info_ptr == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500287 return;
288
289 info_ptr->x_offset = offset_x;
290 info_ptr->y_offset = offset_y;
291 info_ptr->offset_unit_type = (png_byte)unit_type;
292 info_ptr->valid |= PNG_INFO_oFFs;
293}
294#endif
295
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500296#ifdef PNG_pCAL_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500297void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600298png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500299 png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
300 int nparams, png_const_charp units, png_charpp params)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500301{
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500302 png_size_t length;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600303 int i;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500304
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500305 png_debug1(1, "in %s storage function", "pCAL");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500306
John Bowlerfcd301d2011-12-28 21:34:27 -0600307 if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600308 || (nparams > 0 && params == NULL))
Andreas Dilger47a0c421997-05-16 02:46:07 -0500309 return;
310
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600311 length = strlen(purpose) + 1;
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500312 png_debug1(3, "allocating purpose for info (%lu bytes)",
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -0600313 (unsigned long)length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500314
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500315 /* TODO: validate format of calibration name and unit name */
316
317 /* Check that the type matches the specification. */
318 if (type < 0 || type > 3)
John Bowler7dc03292016-09-02 19:26:42 -0700319 {
320 png_chunk_report(png_ptr, "Invalid pCAL equation type",
321 PNG_CHUNK_WRITE_ERROR);
322 return;
323 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500324
John Bowlerfcd301d2011-12-28 21:34:27 -0600325 if (nparams < 0 || nparams > 255)
John Bowler7dc03292016-09-02 19:26:42 -0700326 {
327 png_chunk_report(png_ptr, "Invalid pCAL parameter count",
328 PNG_CHUNK_WRITE_ERROR);
329 return;
330 }
John Bowlerfcd301d2011-12-28 21:34:27 -0600331
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500332 /* Validate params[nparams] */
333 for (i=0; i<nparams; ++i)
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500334 {
John Bowlerfcd301d2011-12-28 21:34:27 -0600335 if (params[i] == NULL ||
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500336 !png_check_fp_string(params[i], strlen(params[i])))
John Bowler7dc03292016-09-02 19:26:42 -0700337 {
338 png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
339 PNG_CHUNK_WRITE_ERROR);
340 return;
341 }
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500342 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500343
John Bowlerfcd301d2011-12-28 21:34:27 -0600344 info_ptr->pcal_purpose = png_voidcast(png_charp,
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500345 png_malloc_warn(png_ptr, length));
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500346
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500347 if (info_ptr->pcal_purpose == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500348 {
John Bowler7dc03292016-09-02 19:26:42 -0700349 png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
350 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500351 return;
352 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500353
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600354 memcpy(info_ptr->pcal_purpose, purpose, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500355
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500356 png_debug(3, "storing X0, X1, type, and nparams in info");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500357 info_ptr->pcal_X0 = X0;
358 info_ptr->pcal_X1 = X1;
359 info_ptr->pcal_type = (png_byte)type;
360 info_ptr->pcal_nparams = (png_byte)nparams;
361
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600362 length = strlen(units) + 1;
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500363 png_debug1(3, "allocating units for info (%lu bytes)",
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -0500364 (unsigned long)length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500365
John Bowlerfcd301d2011-12-28 21:34:27 -0600366 info_ptr->pcal_units = png_voidcast(png_charp,
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -0500367 png_malloc_warn(png_ptr, length));
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500368
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500369 if (info_ptr->pcal_units == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500370 {
Glenn Randers-Pehrson83fb8552009-06-16 17:52:23 -0500371 png_warning(png_ptr, "Insufficient memory for pCAL units");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600372
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500373 return;
374 }
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500375
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600376 memcpy(info_ptr->pcal_units, units, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500377
John Bowlerfcd301d2011-12-28 21:34:27 -0600378 info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -0500379 (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500380
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500381 if (info_ptr->pcal_params == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500382 {
Glenn Randers-Pehrson83fb8552009-06-16 17:52:23 -0500383 png_warning(png_ptr, "Insufficient memory for pCAL params");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600384
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500385 return;
386 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500387
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -0500388 memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
389 (sizeof (png_charp)));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500390
391 for (i = 0; i < nparams; i++)
392 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600393 length = strlen(params[i]) + 1;
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500394 png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500395 (unsigned long)length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500396
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500397 info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500398
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500399 if (info_ptr->pcal_params[i] == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500400 {
Glenn Randers-Pehrson83fb8552009-06-16 17:52:23 -0500401 png_warning(png_ptr, "Insufficient memory for pCAL parameter");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600402
Glenn Randers-Pehrson83fb8552009-06-16 17:52:23 -0500403 return;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500404 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500405
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600406 memcpy(info_ptr->pcal_params[i], params[i], length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500407 }
408
409 info_ptr->valid |= PNG_INFO_pCAL;
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500410 info_ptr->free_me |= PNG_FREE_PCAL;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500411}
412#endif
413
Glenn Randers-Pehrsona272d8f2010-06-25 21:45:31 -0500414#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500415void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600416png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500417 int unit, png_const_charp swidth, png_const_charp sheight)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600418{
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500419 png_size_t lengthw = 0, lengthh = 0;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600420
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500421 png_debug1(1, "in %s storage function", "sCAL");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500422
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600423 if (png_ptr == NULL || info_ptr == NULL)
424 return;
425
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500426 /* Double check the unit (should never get here with an invalid
427 * unit unless this is an API call.)
428 */
429 if (unit != 1 && unit != 2)
430 png_error(png_ptr, "Invalid sCAL unit");
431
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600432 if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -0500433 swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500434 png_error(png_ptr, "Invalid sCAL width");
435
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600436 if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -0500437 sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500438 png_error(png_ptr, "Invalid sCAL height");
439
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600440 info_ptr->scal_unit = (png_byte)unit;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600441
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500442 ++lengthw;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500443
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -0600444 png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500445
John Bowlerfcd301d2011-12-28 21:34:27 -0600446 info_ptr->scal_s_width = png_voidcast(png_charp,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500447 png_malloc_warn(png_ptr, lengthw));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500448
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500449 if (info_ptr->scal_s_width == NULL)
450 {
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500451 png_warning(png_ptr, "Memory allocation failed while processing sCAL");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600452
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500453 return;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500454 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500455
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600456 memcpy(info_ptr->scal_s_width, swidth, lengthw);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600457
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500458 ++lengthh;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500459
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -0600460 png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500461
John Bowlerfcd301d2011-12-28 21:34:27 -0600462 info_ptr->scal_s_height = png_voidcast(png_charp,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500463 png_malloc_warn(png_ptr, lengthh));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500464
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500465 if (info_ptr->scal_s_height == NULL)
466 {
467 png_free (png_ptr, info_ptr->scal_s_width);
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500468 info_ptr->scal_s_width = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500469
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500470 png_warning(png_ptr, "Memory allocation failed while processing sCAL");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600471
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500472 return;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500473 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500474
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600475 memcpy(info_ptr->scal_s_height, sheight, lengthh);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500476
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600477 info_ptr->valid |= PNG_INFO_sCAL;
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500478 info_ptr->free_me |= PNG_FREE_SCAL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600479}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500480
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500481# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500482void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600483png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
484 double width, double height)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500485{
486 png_debug1(1, "in %s storage function", "sCAL");
487
488 /* Check the arguments. */
489 if (width <= 0)
490 png_warning(png_ptr, "Invalid sCAL width ignored");
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500491
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500492 else if (height <= 0)
493 png_warning(png_ptr, "Invalid sCAL height ignored");
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500494
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500495 else
496 {
497 /* Convert 'width' and 'height' to ASCII. */
498 char swidth[PNG_sCAL_MAX_DIGITS+1];
499 char sheight[PNG_sCAL_MAX_DIGITS+1];
500
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600501 png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500502 PNG_sCAL_PRECISION);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600503 png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500504 PNG_sCAL_PRECISION);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500505
506 png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
507 }
508}
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500509# endif
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500510
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500511# ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500512void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600513png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500514 png_fixed_point width, png_fixed_point height)
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500515{
516 png_debug1(1, "in %s storage function", "sCAL");
517
518 /* Check the arguments. */
519 if (width <= 0)
520 png_warning(png_ptr, "Invalid sCAL width ignored");
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500521
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500522 else if (height <= 0)
523 png_warning(png_ptr, "Invalid sCAL height ignored");
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500524
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500525 else
526 {
527 /* Convert 'width' and 'height' to ASCII. */
528 char swidth[PNG_sCAL_MAX_DIGITS+1];
529 char sheight[PNG_sCAL_MAX_DIGITS+1];
530
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600531 png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
532 png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -0500533
534 png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
535 }
536}
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500537# endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600538#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600539
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500540#ifdef PNG_pHYs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500541void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600542png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -0600543 png_uint_32 res_x, png_uint_32 res_y, int unit_type)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500544{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500545 png_debug1(1, "in %s storage function", "pHYs");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500546
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600547 if (png_ptr == NULL || info_ptr == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500548 return;
549
550 info_ptr->x_pixels_per_unit = res_x;
551 info_ptr->y_pixels_per_unit = res_y;
552 info_ptr->phys_unit_type = (png_byte)unit_type;
553 info_ptr->valid |= PNG_INFO_pHYs;
554}
555#endif
556
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500557void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600558png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500559 png_const_colorp palette, int num_palette)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500560{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600561
Glenn Randers-Pehrsona901eb32015-10-30 07:57:49 -0500562 png_uint_32 max_palette_length;
563
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500564 png_debug1(1, "in %s storage function", "PLTE");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500565
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600566 if (png_ptr == NULL || info_ptr == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500567 return;
568
Glenn Randers-Pehrson0a9afc12015-11-22 20:53:02 -0600569 max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
570 (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
Glenn Randers-Pehrsona901eb32015-10-30 07:57:49 -0500571
Glenn Randers-Pehrson1bef8e92015-10-30 11:34:37 -0500572 if (num_palette < 0 || num_palette > (int) max_palette_length)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500573 {
574 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600575 png_error(png_ptr, "Invalid palette length");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500576
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500577 else
578 {
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600579 png_warning(png_ptr, "Invalid palette length");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600580
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600581 return;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500582 }
583 }
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600584
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600585 if ((num_palette > 0 && palette == NULL) ||
586 (num_palette == 0
587# ifdef PNG_MNG_FEATURES_SUPPORTED
588 && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
589# endif
590 ))
591 {
Glenn Randers-Pehrson67f101e2013-12-14 12:36:28 -0600592 png_error(png_ptr, "Invalid palette");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600593 }
594
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600595 /* It may not actually be necessary to set png_ptr->palette here;
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600596 * we do it for backward compatibility with the way the png_handle_tRNS
597 * function used to do the allocation.
John Bowler4f67e402011-12-28 08:43:37 -0600598 *
599 * 1.6.0: the above statement appears to be incorrect; something has to set
600 * the palette inside png_struct on read.
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600601 */
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600602 png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500603
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600604 /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
Glenn Randers-Pehrsona901eb32015-10-30 07:57:49 -0500605 * of num_palette entries, in case of an invalid PNG file or incorrect
606 * call to png_set_PLTE() with too-large sample values.
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500607 */
John Bowlerfcd301d2011-12-28 21:34:27 -0600608 png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600609 PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500610
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600611 if (num_palette > 0)
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -0500612 memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
613 (sizeof (png_color)));
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600614 info_ptr->palette = png_ptr->palette;
615 info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600616
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600617 info_ptr->free_me |= PNG_FREE_PLTE;
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600618
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600619 info_ptr->valid |= PNG_INFO_PLTE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500620}
621
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500622#ifdef PNG_sBIT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500623void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600624png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500625 png_const_color_8p sig_bit)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500627 png_debug1(1, "in %s storage function", "sBIT");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500628
John Bowlerfcd301d2011-12-28 21:34:27 -0600629 if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500630 return;
631
John Bowlerfcd301d2011-12-28 21:34:27 -0600632 info_ptr->sig_bit = *sig_bit;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500633 info_ptr->valid |= PNG_INFO_sBIT;
634}
635#endif
636
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500637#ifdef PNG_sRGB_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500638void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600639png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600640{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500641 png_debug1(1, "in %s storage function", "sRGB");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500642
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600643 if (png_ptr == NULL || info_ptr == NULL)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600644 return;
645
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600646 (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
647 png_colorspace_sync_info(png_ptr, info_ptr);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600648}
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600649
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500650void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600651png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson8d0bc0f2011-01-25 22:15:58 -0600652 int srgb_intent)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600653{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500654 png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500655
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600656 if (png_ptr == NULL || info_ptr == NULL)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600657 return;
658
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500659 if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
660 srgb_intent) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600661 {
662 /* This causes the gAMA and cHRM to be written too */
663 info_ptr->colorspace.flags |=
664 PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
665 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600666
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600667 png_colorspace_sync_info(png_ptr, info_ptr);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600668}
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -0600669#endif /* sRGB */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600670
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600671
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500672#ifdef PNG_iCCP_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500673void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600674png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500675 png_const_charp name, int compression_type,
676 png_const_bytep profile, png_uint_32 proflen)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600677{
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500678 png_charp new_iccp_name;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500679 png_bytep new_iccp_profile;
John Bowlerf3f7e142011-09-09 07:32:37 -0500680 png_size_t length;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500681
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500682 png_debug1(1, "in %s storage function", "iCCP");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500683
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600684 if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
685 return;
686
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600687 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
688 png_app_error(png_ptr, "Invalid iCCP compression method");
689
690 /* Set the colorspace first because this validates the profile; do not
691 * override previously set app cHRM or gAMA here (because likely as not the
692 * application knows better than libpng what the correct values are.) Pass
693 * the info_ptr color_type field to png_colorspace_set_ICC because in the
694 * write case it has not yet been stored in png_ptr.
695 */
696 {
697 int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500698 proflen, profile, info_ptr->color_type);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600699
700 png_colorspace_sync_info(png_ptr, info_ptr);
701
702 /* Don't do any of the copying if the profile was bad, or inconsistent. */
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600703 if (result == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600704 return;
705
706 /* But do write the gAMA and cHRM chunks from the profile. */
707 info_ptr->colorspace.flags |=
708 PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
709 }
710
711 length = strlen(name)+1;
John Bowlerfcd301d2011-12-28 21:34:27 -0600712 new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500713
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500714 if (new_iccp_name == NULL)
715 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600716 png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600717
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500718 return;
719 }
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500720
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600721 memcpy(new_iccp_name, name, length);
John Bowlerfcd301d2011-12-28 21:34:27 -0600722 new_iccp_profile = png_voidcast(png_bytep,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500723 png_malloc_warn(png_ptr, proflen));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500724
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500725 if (new_iccp_profile == NULL)
726 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600727 png_free(png_ptr, new_iccp_name);
728 png_benign_error(png_ptr,
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600729 "Insufficient memory to process iCCP profile");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600730
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500731 return;
732 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500733
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600734 memcpy(new_iccp_profile, profile, proflen);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500735
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500736 png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500737
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600738 info_ptr->iccp_proflen = proflen;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500739 info_ptr->iccp_name = new_iccp_name;
740 info_ptr->iccp_profile = new_iccp_profile;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600741 info_ptr->free_me |= PNG_FREE_ICCP;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600742 info_ptr->valid |= PNG_INFO_iCCP;
743}
744#endif
745
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500746#ifdef PNG_TEXT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500747void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600748png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
749 png_const_textp text_ptr, int num_text)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500750{
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500751 int ret;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500752 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500753
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600754 if (ret != 0)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500755 png_error(png_ptr, "Insufficient memory to store text");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500756}
757
758int /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -0600759png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500760 png_const_textp text_ptr, int num_text)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500761{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500762 int i;
763
Glenn Randers-Pehrsona8242fe2015-08-17 20:46:27 -0500764 png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500765 (unsigned long)png_ptr->chunk_name);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500766
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600767 if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500768 return(0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500769
770 /* Make sure we have enough space in the "text" array in info_struct
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600771 * to hold all of the incoming text_ptr objects. This compare can't overflow
772 * because max_text >= num_text (anyway, subtract of two positive integers
773 * can't overflow in any case.)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500774 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600775 if (num_text > info_ptr->max_text - info_ptr->num_text)
Glenn Randers-Pehrson590c8b02013-01-19 08:49:12 -0600776 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600777 int old_num_text = info_ptr->num_text;
778 int max_text;
779 png_textp new_text = NULL;
780
781 /* Calculate an appropriate max_text, checking for overflow. */
782 max_text = old_num_text;
783 if (num_text <= INT_MAX - max_text)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500784 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600785 max_text += num_text;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500786
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600787 /* Round up to a multiple of 8 */
788 if (max_text < INT_MAX-8)
789 max_text = (max_text + 8) & ~0x7;
Glenn Randers-Pehrson96027d92012-03-29 06:15:55 -0500790
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600791 else
792 max_text = INT_MAX;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500793
Glenn Randers-Pehrson91271382014-10-03 20:23:31 -0500794 /* Now allocate a new array and copy the old members in; this does all
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600795 * the overflow checks.
796 */
797 new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500798 info_ptr->text, old_num_text, max_text-old_num_text,
799 sizeof *new_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500800 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500801
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600802 if (new_text == NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500803 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600804 png_chunk_report(png_ptr, "too many text chunks",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500805 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600806
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600807 return 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500808 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500809
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600810 png_free(png_ptr, info_ptr->text);
811
812 info_ptr->text = new_text;
813 info_ptr->free_me |= PNG_FREE_TEXT;
814 info_ptr->max_text = max_text;
815 /* num_text is adjusted below as the entries are copied in */
816
817 png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500818 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600819
Andreas Dilger47a0c421997-05-16 02:46:07 -0500820 for (i = 0; i < num_text; i++)
821 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600822 size_t text_length, key_len;
823 size_t lang_len, lang_key_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500824 png_textp textp = &(info_ptr->text[info_ptr->num_text]);
825
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500826 if (text_ptr[i].key == NULL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600827 continue;
828
Glenn Randers-Pehrson79b2d642010-10-13 07:31:14 -0500829 if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
830 text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
Glenn Randers-Pehrsone34f80e2010-10-13 06:55:30 -0500831 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600832 png_chunk_report(png_ptr, "text compression mode is out of range",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500833 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsone34f80e2010-10-13 06:55:30 -0500834 continue;
835 }
836
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600837 key_len = strlen(text_ptr[i].key);
Glenn Randers-Pehrson79b2d642010-10-13 07:31:14 -0500838
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500839 if (text_ptr[i].compression <= 0)
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500840 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500841 lang_len = 0;
842 lang_key_len = 0;
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500843 }
Glenn Randers-Pehrsonef29a5e2009-10-31 19:37:05 -0500844
Glenn Randers-Pehrsondd78d522010-03-30 08:34:02 -0500845 else
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500846# ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600847 {
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500848 /* Set iTXt data */
Glenn Randers-Pehrsond6ea40a2009-11-02 07:32:00 -0600849
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500850 if (text_ptr[i].lang != NULL)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600851 lang_len = strlen(text_ptr[i].lang);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500852
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500853 else
854 lang_len = 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500855
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500856 if (text_ptr[i].lang_key != NULL)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600857 lang_key_len = strlen(text_ptr[i].lang_key);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500858
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500859 else
860 lang_key_len = 0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600861 }
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600862# else /* iTXt */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500863 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600864 png_chunk_report(png_ptr, "iTXt chunk not supported",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500865 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500866 continue;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500867 }
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500868# endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500869
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500870 if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
Andreas Dilger47a0c421997-05-16 02:46:07 -0500871 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600872 text_length = 0;
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500873# ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500874 if (text_ptr[i].compression > 0)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600875 textp->compression = PNG_ITXT_COMPRESSION_NONE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500876
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600877 else
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500878# endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600879 textp->compression = PNG_TEXT_COMPRESSION_NONE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500880 }
Glenn Randers-Pehrsonef29a5e2009-10-31 19:37:05 -0500881
Andreas Dilger47a0c421997-05-16 02:46:07 -0500882 else
883 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600884 text_length = strlen(text_ptr[i].text);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500885 textp->compression = text_ptr[i].compression;
886 }
Glenn Randers-Pehrson6d8f3b01999-10-23 08:39:18 -0500887
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600888 textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
889 key_len + text_length + lang_len + lang_key_len + 4));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500890
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500891 if (textp->key == NULL)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600892 {
893 png_chunk_report(png_ptr, "text chunk: out of memory",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500894 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600895
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600896 return 1;
897 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500898
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -0600899 png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -0600900 (unsigned long)(png_uint_32)
901 (key_len + lang_len + lang_key_len + text_length + 4),
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -0600902 textp->key);
Glenn Randers-Pehrson6d8f3b01999-10-23 08:39:18 -0500903
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600904 memcpy(textp->key, text_ptr[i].key, key_len);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500905 *(textp->key + key_len) = '\0';
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500906
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600907 if (text_ptr[i].compression > 0)
908 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500909 textp->lang = textp->key + key_len + 1;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600910 memcpy(textp->lang, text_ptr[i].lang, lang_len);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500911 *(textp->lang + lang_len) = '\0';
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500912 textp->lang_key = textp->lang + lang_len + 1;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600913 memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500914 *(textp->lang_key + lang_key_len) = '\0';
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500915 textp->text = textp->lang_key + lang_key_len + 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600916 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500917
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600918 else
919 {
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500920 textp->lang=NULL;
921 textp->lang_key=NULL;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500922 textp->text = textp->key + key_len + 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600923 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500924
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600925 if (text_length != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600926 memcpy(textp->text, text_ptr[i].text, text_length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500927
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500928 *(textp->text + text_length) = '\0';
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600929
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500930# ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500931 if (textp->compression > 0)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600932 {
933 textp->text_length = 0;
934 textp->itxt_length = text_length;
935 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500936
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600937 else
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -0500938# endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600939 {
940 textp->text_length = text_length;
941 textp->itxt_length = 0;
942 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500943
Andreas Dilger47a0c421997-05-16 02:46:07 -0500944 info_ptr->num_text++;
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500945 png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500946 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600947
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500948 return(0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500949}
950#endif
951
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500952#ifdef PNG_tIME_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500953void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -0600954png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
955 png_const_timep mod_time)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500956{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500957 png_debug1(1, "in %s storage function", "tIME");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500958
John Bowlerfcd301d2011-12-28 21:34:27 -0600959 if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500960 (png_ptr->mode & PNG_WROTE_tIME) != 0)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500961 return;
962
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600963 if (mod_time->month == 0 || mod_time->month > 12 ||
964 mod_time->day == 0 || mod_time->day > 31 ||
965 mod_time->hour > 23 || mod_time->minute > 59 ||
966 mod_time->second > 60)
967 {
968 png_warning(png_ptr, "Ignoring invalid time value");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600969
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600970 return;
971 }
972
John Bowlerfcd301d2011-12-28 21:34:27 -0600973 info_ptr->mod_time = *mod_time;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500974 info_ptr->valid |= PNG_INFO_tIME;
975}
976#endif
977
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500978#ifdef PNG_tRNS_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500979void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600980png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500981 png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500982{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500983 png_debug1(1, "in %s storage function", "tRNS");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500984
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600985 if (png_ptr == NULL || info_ptr == NULL)
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -0600986
Andreas Dilger47a0c421997-05-16 02:46:07 -0500987 return;
988
Glenn Randers-Pehrson6abea752009-08-08 16:52:06 -0500989 if (trans_alpha != NULL)
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600990 {
Glenn Randers-Pehrsonef29a5e2009-10-31 19:37:05 -0500991 /* It may not actually be necessary to set png_ptr->trans_alpha here;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500992 * we do it for backward compatibility with the way the png_handle_tRNS
993 * function used to do the allocation.
John Bowler4f67e402011-12-28 08:43:37 -0600994 *
995 * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
996 * relies on png_set_tRNS storing the information in png_struct
997 * (otherwise it won't be there for the code in pngrtran.c).
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500998 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500999
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001000 png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001001
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001002 if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
Glenn Randers-Pehrson8d167252016-05-27 19:55:44 -05001003 {
1004 /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
Glenn Randers-Pehrson6c7459e2016-05-27 20:09:23 -05001005 info_ptr->trans_alpha = png_voidcast(png_bytep,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001006 png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001007 memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
Glenn Randers-Pehrson8d167252016-05-27 19:55:44 -05001008 }
Glenn Randers-Pehrson6c7459e2016-05-27 20:09:23 -05001009 png_ptr->trans_alpha = info_ptr->trans_alpha;
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001010 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001011
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001012 if (trans_color != NULL)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001013 {
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001014#ifdef PNG_WARNINGS_SUPPORTED
Glenn Randers-Pehrson2f56fe42015-01-13 09:25:48 -06001015 if (info_ptr->bit_depth < 16)
1016 {
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001017 int sample_max = (1 << info_ptr->bit_depth) - 1;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001018
Glenn Randers-Pehrson2f56fe42015-01-13 09:25:48 -06001019 if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
1020 trans_color->gray > sample_max) ||
1021 (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
1022 (trans_color->red > sample_max ||
1023 trans_color->green > sample_max ||
1024 trans_color->blue > sample_max)))
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001025 png_warning(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001026 "tRNS chunk has out-of-range samples for bit_depth");
Glenn Randers-Pehrson2f56fe42015-01-13 09:25:48 -06001027 }
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001028#endif
1029
1030 info_ptr->trans_color = *trans_color;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001031
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001032 if (num_trans == 0)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001033 num_trans = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001034 }
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001035
Andreas Dilger47a0c421997-05-16 02:46:07 -05001036 info_ptr->num_trans = (png_uint_16)num_trans;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001037
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001038 if (num_trans != 0)
1039 {
1040 info_ptr->valid |= PNG_INFO_tRNS;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001041 info_ptr->free_me |= PNG_FREE_TRNS;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001042 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001043}
1044#endif
1045
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001046#ifdef PNG_sPLT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001047void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -06001048png_set_sPLT(png_const_structrp png_ptr,
John Bowler5d567862011-12-24 09:12:00 -06001049 png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
Glenn Randers-Pehrson3779c692006-11-07 20:38:11 -06001050/*
1051 * entries - array of png_sPLT_t structures
1052 * to be added to the list of palettes
1053 * in the info structure.
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -05001054 *
Glenn Randers-Pehrson3779c692006-11-07 20:38:11 -06001055 * nentries - number of palette structures to be
1056 * added.
1057 */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001058{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001059 png_sPLT_tp np;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001060
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001061 if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001062 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001063
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001064 /* Use the internal realloc function, which checks for all the possible
1065 * overflows. Notice that the parameters are (int) and (size_t)
1066 */
1067 np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001068 info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
1069 sizeof *np));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001070
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001071 if (np == NULL)
1072 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001073 /* Out of memory or too many chunks */
1074 png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001075
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -06001076 return;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001077 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001078
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001079 png_free(png_ptr, info_ptr->splt_palettes);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001080 info_ptr->splt_palettes = np;
1081 info_ptr->free_me |= PNG_FREE_SPLT;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001082
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001083 np += info_ptr->splt_palettes_num;
1084
1085 do
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001086 {
John Bowlerf3f7e142011-09-09 07:32:37 -05001087 png_size_t length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001088
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001089 /* Skip invalid input entries */
1090 if (entries->name == NULL || entries->entries == NULL)
1091 {
1092 /* png_handle_sPLT doesn't do this, so this is an app error */
1093 png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
1094 /* Just skip the invalid entry */
1095 continue;
1096 }
1097
1098 np->depth = entries->depth;
1099
Glenn Randers-Pehrson91271382014-10-03 20:23:31 -05001100 /* In the event of out-of-memory just return - there's no point keeping
1101 * on trying to add sPLT chunks.
Glenn Randers-Pehrsonf3af7062012-02-02 23:11:45 -06001102 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001103 length = strlen(entries->name) + 1;
1104 np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
Glenn Randers-Pehrsonf3af7062012-02-02 23:11:45 -06001105
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001106 if (np->name == NULL)
1107 break;
Glenn Randers-Pehrsonf3af7062012-02-02 23:11:45 -06001108
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001109 memcpy(np->name, entries->name, length);
Glenn Randers-Pehrsonf3af7062012-02-02 23:11:45 -06001110
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001111 /* IMPORTANT: we have memory now that won't get freed if something else
Glenn Randers-Pehrson91271382014-10-03 20:23:31 -05001112 * goes wrong; this code must free it. png_malloc_array produces no
1113 * warnings; use a png_chunk_report (below) if there is an error.
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001114 */
1115 np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
1116 entries->nentries, sizeof (png_sPLT_entry)));
1117
1118 if (np->entries == NULL)
John Bowler2414bd92013-01-19 23:18:59 -06001119 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001120 png_free(png_ptr, np->name);
Glenn Randers-Pehrson11d4a2a2014-10-29 08:23:19 -05001121 np->name = NULL;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001122 break;
John Bowler2414bd92013-01-19 23:18:59 -06001123 }
1124
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001125 np->nentries = entries->nentries;
1126 /* This multiply can't overflow because png_malloc_array has already
1127 * checked it when doing the allocation.
1128 */
1129 memcpy(np->entries, entries->entries,
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -05001130 (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
John Bowler2414bd92013-01-19 23:18:59 -06001131
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001132 /* Note that 'continue' skips the advance of the out pointer and out
1133 * count, so an invalid entry is not added.
1134 */
1135 info_ptr->valid |= PNG_INFO_sPLT;
1136 ++(info_ptr->splt_palettes_num);
1137 ++np;
Viktor Szakats8c50acb2017-03-29 23:54:40 +00001138 ++entries;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001139 }
Viktor Szakats8c50acb2017-03-29 23:54:40 +00001140 while (--nentries);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001141
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001142 if (nentries > 0)
1143 png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001144}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -06001145#endif /* sPLT */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001146
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001147#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
1148static png_byte
1149check_location(png_const_structrp png_ptr, int location)
1150{
1151 location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
1152
1153 /* New in 1.6.0; copy the location and check it. This is an API
Glenn Randers-Pehrson91271382014-10-03 20:23:31 -05001154 * change; previously the app had to use the
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001155 * png_set_unknown_chunk_location API below for each chunk.
1156 */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001157 if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001158 {
1159 /* Write struct, so unknown chunks come from the app */
1160 png_app_warning(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001161 "png_set_unknown_chunks now expects a valid location");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001162 /* Use the old behavior */
1163 location = (png_byte)(png_ptr->mode &
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001164 (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001165 }
1166
1167 /* This need not be an internal error - if the app calls
1168 * png_set_unknown_chunks on a read pointer it must get the location right.
1169 */
1170 if (location == 0)
1171 png_error(png_ptr, "invalid location in png_set_unknown_chunks");
1172
1173 /* Now reduce the location to the top-most set bit by removing each least
1174 * significant bit in turn.
1175 */
1176 while (location != (location & -location))
1177 location &= ~(location & -location);
1178
1179 /* The cast is safe because 'location' is a bit mask and only the low four
1180 * bits are significant.
1181 */
1182 return (png_byte)location;
1183}
1184
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001185void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -06001186png_set_unknown_chunks(png_const_structrp png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001187 png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001188{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001189 png_unknown_chunkp np;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001190
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001191 if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001192 unknowns == NULL)
Glenn Randers-Pehrson83fb8552009-06-16 17:52:23 -05001193 return;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001194
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001195 /* Check for the failure cases where support has been disabled at compile
1196 * time. This code is hardly ever compiled - it's here because
1197 * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
1198 * code) but may be meaningless if the read or write handling of unknown
1199 * chunks is not compiled in.
1200 */
1201# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
1202 defined(PNG_READ_SUPPORTED)
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001203 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001204 {
1205 png_app_error(png_ptr, "no unknown chunk support on read");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001206
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001207 return;
1208 }
1209# endif
1210# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
1211 defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001212 if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001213 {
1214 png_app_error(png_ptr, "no unknown chunk support on write");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001215
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001216 return;
1217 }
1218# endif
1219
1220 /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
1221 * unknown critical chunks could be lost with just a warning resulting in
1222 * undefined behavior. Now png_chunk_report is used to provide behavior
1223 * appropriate to read or write.
1224 */
1225 np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001226 info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
1227 sizeof *np));
Glenn Randers-Pehrson590c8b02013-01-19 08:49:12 -06001228
1229 if (np == NULL)
1230 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001231 png_chunk_report(png_ptr, "too many unknown chunks",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001232 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001233
John Bowler1c6e22a2013-01-10 10:55:34 -06001234 return;
1235 }
1236
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001237 png_free(png_ptr, info_ptr->unknown_chunks);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001238 info_ptr->unknown_chunks = np; /* safe because it is initialized */
1239 info_ptr->free_me |= PNG_FREE_UNKN;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001240
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001241 np += info_ptr->unknown_chunks_num;
1242
1243 /* Increment unknown_chunks_num each time round the loop to protect the
1244 * just-allocated chunk data.
1245 */
1246 for (; num_unknowns > 0; --num_unknowns, ++unknowns)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001247 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001248 memcpy(np->name, unknowns->name, (sizeof np->name));
1249 np->name[(sizeof np->name)-1] = '\0';
1250 np->location = check_location(png_ptr, unknowns->location);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001251
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001252 if (unknowns->size == 0)
1253 {
1254 np->data = NULL;
1255 np->size = 0;
1256 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001257
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001258 else
1259 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001260 np->data = png_voidcast(png_bytep,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001261 png_malloc_base(png_ptr, unknowns->size));
John Bowler2414bd92013-01-19 23:18:59 -06001262
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001263 if (np->data == NULL)
John Bowler2414bd92013-01-19 23:18:59 -06001264 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001265 png_chunk_report(png_ptr, "unknown chunk: out of memory",
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001266 PNG_CHUNK_WRITE_ERROR);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001267 /* But just skip storing the unknown chunk */
1268 continue;
John Bowler2414bd92013-01-19 23:18:59 -06001269 }
1270
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001271 memcpy(np->data, unknowns->data, unknowns->size);
1272 np->size = unknowns->size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001273 }
Glenn Randers-Pehrsonf3af7062012-02-02 23:11:45 -06001274
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001275 /* These increments are skipped on out-of-memory for the data - the
1276 * unknown chunk entry gets overwritten if the png_chunk_report returns.
1277 * This is correct in the read case (the chunk is just dropped.)
1278 */
1279 ++np;
1280 ++(info_ptr->unknown_chunks_num);
1281 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001282}
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05001283
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001284void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -06001285png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -06001286 int chunk, int location)
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -05001287{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001288 /* This API is pretty pointless in 1.6.0 because the location can be set
1289 * before the call to png_set_unknown_chunks.
1290 *
1291 * TODO: add a png_app_warning in 1.7
1292 */
1293 if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
1294 chunk < info_ptr->unknown_chunks_num)
1295 {
1296 if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
1297 {
1298 png_app_error(png_ptr, "invalid unknown chunk location");
1299 /* Fake out the pre 1.6.0 behavior: */
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -05001300 if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001301 location = PNG_AFTER_IDAT;
1302
1303 else
1304 location = PNG_HAVE_IHDR; /* also undocumented */
1305 }
1306
1307 info_ptr->unknown_chunks[chunk].location =
1308 check_location(png_ptr, location);
1309 }
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -05001310}
Glenn Randers-Pehrson217d38c2015-03-07 10:35:03 -06001311#endif /* STORE_UNKNOWN_CHUNKS */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001312
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001313#ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001314png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001315png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001316{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001317 png_debug(1, "in png_permit_mng_features");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -05001318
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001319 if (png_ptr == NULL)
John Bowler4f67e402011-12-28 08:43:37 -06001320 return 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001321
John Bowler4f67e402011-12-28 08:43:37 -06001322 png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001323
John Bowler4f67e402011-12-28 08:43:37 -06001324 return png_ptr->mng_features_permitted;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001325}
1326#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001327
Glenn Randers-Pehrson6ba90882009-12-25 14:26:13 -06001328#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001329static unsigned int
1330add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
1331{
1332 unsigned int i;
1333
1334 /* Utility function: update the 'keep' state of a chunk if it is already in
1335 * the list, otherwise add it to the list.
1336 */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001337 for (i=0; i<count; ++i, list += 5)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001338 {
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001339 if (memcmp(list, add, 4) == 0)
1340 {
1341 list[4] = (png_byte)keep;
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001342
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001343 return count;
1344 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001345 }
1346
1347 if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
1348 {
1349 ++count;
1350 memcpy(list, add, 4);
1351 list[4] = (png_byte)keep;
1352 }
1353
1354 return count;
1355}
1356
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001357void PNGAPI
John Bowlere9567512012-08-15 22:53:00 -05001358png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001359 png_const_bytep chunk_list, int num_chunks_in)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001360{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001361 png_bytep new_list;
1362 unsigned int num_chunks, old_num_chunks;
1363
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001364 if (png_ptr == NULL)
1365 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001366
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001367 if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
John Bowleraa9dea52012-08-10 19:04:08 -05001368 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001369 png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001370
John Bowlere9567512012-08-15 22:53:00 -05001371 return;
John Bowleraa9dea52012-08-10 19:04:08 -05001372 }
1373
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001374 if (num_chunks_in <= 0)
1375 {
1376 png_ptr->unknown_default = keep;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001377
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001378 /* '0' means just set the flags, so stop here */
1379 if (num_chunks_in == 0)
1380 return;
1381 }
1382
1383 if (num_chunks_in < 0)
1384 {
1385 /* Ignore all unknown chunks and all chunks recognized by
1386 * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
1387 */
1388 static PNG_CONST png_byte chunks_to_ignore[] = {
1389 98, 75, 71, 68, '\0', /* bKGD */
1390 99, 72, 82, 77, '\0', /* cHRM */
1391 103, 65, 77, 65, '\0', /* gAMA */
1392 104, 73, 83, 84, '\0', /* hIST */
1393 105, 67, 67, 80, '\0', /* iCCP */
1394 105, 84, 88, 116, '\0', /* iTXt */
1395 111, 70, 70, 115, '\0', /* oFFs */
1396 112, 67, 65, 76, '\0', /* pCAL */
1397 112, 72, 89, 115, '\0', /* pHYs */
1398 115, 66, 73, 84, '\0', /* sBIT */
1399 115, 67, 65, 76, '\0', /* sCAL */
1400 115, 80, 76, 84, '\0', /* sPLT */
1401 115, 84, 69, 82, '\0', /* sTER */
1402 115, 82, 71, 66, '\0', /* sRGB */
1403 116, 69, 88, 116, '\0', /* tEXt */
1404 116, 73, 77, 69, '\0', /* tIME */
1405 122, 84, 88, 116, '\0' /* zTXt */
1406 };
1407
1408 chunk_list = chunks_to_ignore;
John Bowler03df1892014-11-05 17:19:36 -06001409 num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001410 }
1411
1412 else /* num_chunks_in > 0 */
1413 {
1414 if (chunk_list == NULL)
1415 {
1416 /* Prior to 1.6.0 this was silently ignored, now it is an app_error
1417 * which can be switched off.
1418 */
1419 png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001420
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001421 return;
1422 }
1423
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -05001424 num_chunks = (unsigned int)num_chunks_in;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001425 }
John Bowlerfcd301d2011-12-28 21:34:27 -06001426
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001427 old_num_chunks = png_ptr->num_chunk_list;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001428 if (png_ptr->chunk_list == NULL)
1429 old_num_chunks = 0;
John Bowleraa9dea52012-08-10 19:04:08 -05001430
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001431 /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
1432 */
1433 if (num_chunks + old_num_chunks > UINT_MAX/5)
John Bowleraa9dea52012-08-10 19:04:08 -05001434 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001435 png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001436
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001437 return;
John Bowleraa9dea52012-08-10 19:04:08 -05001438 }
1439
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001440 /* If these chunks are being reset to the default then no more memory is
1441 * required because add_one_chunk above doesn't extend the list if the 'keep'
1442 * parameter is the default.
1443 */
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -06001444 if (keep != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001445 {
1446 new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
1447 5 * (num_chunks + old_num_chunks)));
John Bowlere9567512012-08-15 22:53:00 -05001448
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001449 if (old_num_chunks > 0)
1450 memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
1451 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001452
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001453 else if (old_num_chunks > 0)
1454 new_list = png_ptr->chunk_list;
1455
1456 else
1457 new_list = NULL;
1458
1459 /* Add the new chunks together with each one's handling code. If the chunk
1460 * already exists the code is updated, otherwise the chunk is added to the
1461 * end. (In libpng 1.6.0 order no longer matters because this code enforces
1462 * the earlier convention that the last setting is the one that is used.)
1463 */
1464 if (new_list != NULL)
1465 {
1466 png_const_bytep inlist;
1467 png_bytep outlist;
1468 unsigned int i;
1469
1470 for (i=0; i<num_chunks; ++i)
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001471 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001472 old_num_chunks = add_one_chunk(new_list, old_num_chunks,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001473 chunk_list+5*i, keep);
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001474 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001475
1476 /* Now remove any spurious 'default' entries. */
1477 num_chunks = 0;
1478 for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001479 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001480 if (inlist[4])
1481 {
1482 if (outlist != inlist)
1483 memcpy(outlist, inlist, 5);
1484 outlist += 5;
1485 ++num_chunks;
1486 }
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001487 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001488
1489 /* This means the application has removed all the specialized handling. */
1490 if (num_chunks == 0)
1491 {
1492 if (png_ptr->chunk_list != new_list)
1493 png_free(png_ptr, new_list);
1494
1495 new_list = NULL;
1496 }
1497 }
1498
1499 else
1500 num_chunks = 0;
1501
1502 png_ptr->num_chunk_list = num_chunks;
1503
1504 if (png_ptr->chunk_list != new_list)
1505 {
1506 if (png_ptr->chunk_list != NULL)
1507 png_free(png_ptr, png_ptr->chunk_list);
1508
1509 png_ptr->chunk_list = new_list;
1510 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001511}
1512#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001513
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001514#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001515void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001516png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
Glenn Randers-Pehrsonda301352010-03-06 06:42:48 -06001517 png_user_chunk_ptr read_user_chunk_fn)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001518{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001519 png_debug(1, "in png_set_read_user_chunk_fn");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -05001520
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -06001521 if (png_ptr == NULL)
1522 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -05001523
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001524 png_ptr->read_user_chunk_fn = read_user_chunk_fn;
1525 png_ptr->user_chunk_ptr = user_chunk_ptr;
1526}
1527#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001528
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001529#ifdef PNG_INFO_IMAGE_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001530void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -06001531png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
1532 png_bytepp row_pointers)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001533{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001534 png_debug1(1, "in %s storage function", "rows");
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001535
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001536 if (png_ptr == NULL || info_ptr == NULL)
1537 return;
1538
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001539 if (info_ptr->row_pointers != NULL &&
1540 (info_ptr->row_pointers != row_pointers))
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001541 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001542
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001543 info_ptr->row_pointers = row_pointers;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001544
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -06001545 if (row_pointers != NULL)
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001546 info_ptr->valid |= PNG_INFO_IDAT;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001547}
1548#endif
1549
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001550void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001551png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -05001552{
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001553 if (png_ptr == NULL)
1554 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001555
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001556 if (size == 0 || size > PNG_UINT_31_MAX)
1557 png_error(png_ptr, "invalid compression buffer size");
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -05001558
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001559# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001560 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
1561 {
1562 png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
1563 return;
1564 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001565# endif
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -05001566
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001567# ifdef PNG_WRITE_SUPPORTED
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001568 if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
1569 {
1570 if (png_ptr->zowner != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001571 {
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001572 png_warning(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001573 "Compression buffer size cannot be changed because it is in use");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001574
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001575 return;
1576 }
John Bowleraa9dea52012-08-10 19:04:08 -05001577
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001578#ifndef __COVERITY__
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001579 /* Some compilers complain that this is always false. However, it
1580 * can be true when integer overflow happens.
1581 */
1582 if (size > ZLIB_IO_MAX)
1583 {
1584 png_warning(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001585 "Compression buffer size limited to system maximum");
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001586 size = ZLIB_IO_MAX; /* must fit */
1587 }
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001588#endif
John Bowleraa9dea52012-08-10 19:04:08 -05001589
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001590 if (size < 6)
1591 {
1592 /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
1593 * if this is permitted.
1594 */
1595 png_warning(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -05001596 "Compression buffer size cannot be reduced below 6");
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001597
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001598 return;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001599 }
Glenn Randers-Pehrson192e92d2016-07-13 14:43:42 -05001600
1601 if (png_ptr->zbuffer_size != size)
1602 {
1603 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
1604 png_ptr->zbuffer_size = (uInt)size;
1605 }
1606 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001607# endif
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -05001608}
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001609
1610void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001611png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001612{
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -05001613 if (png_ptr != NULL && info_ptr != NULL)
Glenn Randers-Pehrson3875d9a2016-10-02 17:08:46 -05001614 info_ptr->valid &= (unsigned int)(~mask);
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -05001615}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001616
Glenn Randers-Pehrsone68f5a32001-05-14 09:20:53 -05001617
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001618#ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001619/* This function was added to libpng 1.2.6 */
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001620void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001621png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001622 png_uint_32 user_height_max)
1623{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001624 /* Images with dimensions larger than these limits will be
1625 * rejected by png_set_IHDR(). To accept any PNG datastream
Glenn Randers-Pehrsonf1cdf4e2015-11-12 22:16:56 -06001626 * regardless of dimensions, set both limits to 0x7fffffff.
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001627 */
1628 if (png_ptr == NULL)
1629 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001630
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001631 png_ptr->user_width_max = user_width_max;
1632 png_ptr->user_height_max = user_height_max;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001633}
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001634
Glenn Randers-Pehrson17ca3402009-11-09 06:51:16 -06001635/* This function was added to libpng 1.4.0 */
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001636void PNGAPI
John Bowler4f67e402011-12-28 08:43:37 -06001637png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001638{
Glenn Randers-Pehrsonbd769652015-01-27 06:53:56 -06001639 if (png_ptr != NULL)
1640 png_ptr->user_chunk_cache_max = user_chunk_cache_max;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001641}
1642
1643/* This function was added to libpng 1.4.1 */
1644void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001645png_set_chunk_malloc_max (png_structrp png_ptr,
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -05001646 png_alloc_size_t user_chunk_malloc_max)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001647{
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -06001648 if (png_ptr != NULL)
Glenn Randers-Pehrson62333ba2010-10-23 08:48:51 -05001649 png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001650}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -06001651#endif /* ?SET_USER_LIMITS */
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001652
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001653
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001654#ifdef PNG_BENIGN_ERRORS_SUPPORTED
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001655void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001656png_set_benign_errors(png_structrp png_ptr, int allowed)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001657{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001658 png_debug(1, "in png_set_benign_errors");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -05001659
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001660 /* If allowed is 1, png_benign_error() is treated as a warning.
1661 *
1662 * If allowed is 0, png_benign_error() is treated as an error (which
1663 * is the default behavior if png_set_benign_errors() is not called).
1664 */
1665
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -06001666 if (allowed != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001667 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
1668 PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001669
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001670 else
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001671 png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
1672 PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001673}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -06001674#endif /* BENIGN_ERRORS */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001675
1676#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
1677 /* Whether to report invalid palette index; added at libng-1.5.10.
1678 * It is possible for an indexed (color-type==3) PNG file to contain
1679 * pixels with invalid (out-of-range) indexes if the PLTE chunk has
1680 * fewer entries than the image's bit-depth would allow. We recover
Glenn Randers-Pehrson6cae24c2014-10-13 11:11:21 -05001681 * from this gracefully by filling any incomplete palette with zeros
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001682 * (opaque black). By default, when this occurs libpng will issue
1683 * a benign error. This API can be used to override that behavior.
1684 */
1685void PNGAPI
1686png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
1687{
1688 png_debug(1, "in png_set_check_for_invalid_index");
1689
1690 if (allowed > 0)
1691 png_ptr->num_palette_max = 0;
1692
1693 else
1694 png_ptr->num_palette_max = -1;
1695}
1696#endif
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001697
1698#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
1699 defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
1700/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1701 * and if invalid, correct the keyword rather than discarding the entire
1702 * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
1703 * length, forbids leading or trailing whitespace, multiple internal spaces,
1704 * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
1705 *
1706 * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
1707 * trailing '\0'). If this routine returns 0 then there was no keyword, or a
1708 * valid one could not be generated, and the caller must png_error.
1709 */
1710png_uint_32 /* PRIVATE */
1711png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
1712{
John Bowler0ac91cc2016-06-28 19:18:09 -07001713#ifdef PNG_WARNINGS_SUPPORTED
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001714 png_const_charp orig_key = key;
John Bowler0ac91cc2016-06-28 19:18:09 -07001715#endif
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001716 png_uint_32 key_len = 0;
1717 int bad_character = 0;
1718 int space = 1;
1719
1720 png_debug(1, "in png_check_keyword");
1721
1722 if (key == NULL)
1723 {
1724 *new_key = 0;
1725 return 0;
1726 }
1727
1728 while (*key && key_len < 79)
1729 {
1730 png_byte ch = (png_byte)*key++;
1731
1732 if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
Viktor Szakats8c50acb2017-03-29 23:54:40 +00001733 {
1734 *new_key++ = ch; ++key_len; space = 0;
1735 }
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001736
1737 else if (space == 0)
1738 {
1739 /* A space or an invalid character when one wasn't seen immediately
1740 * before; output just a space.
1741 */
Viktor Szakats8c50acb2017-03-29 23:54:40 +00001742 *new_key++ = 32; ++key_len; space = 1;
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001743
1744 /* If the character was not a space then it is invalid. */
1745 if (ch != 32)
1746 bad_character = ch;
1747 }
1748
1749 else if (bad_character == 0)
1750 bad_character = ch; /* just skip it, record the first error */
1751 }
1752
1753 if (key_len > 0 && space != 0) /* trailing space */
1754 {
Viktor Szakats8c50acb2017-03-29 23:54:40 +00001755 --key_len; --new_key;
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001756 if (bad_character == 0)
1757 bad_character = 32;
1758 }
1759
1760 /* Terminate the keyword */
1761 *new_key = 0;
1762
1763 if (key_len == 0)
1764 return 0;
1765
1766#ifdef PNG_WARNINGS_SUPPORTED
1767 /* Try to only output one warning per keyword: */
1768 if (*key != 0) /* keyword too long */
1769 png_warning(png_ptr, "keyword truncated");
1770
1771 else if (bad_character != 0)
1772 {
1773 PNG_WARNING_PARAMETERS(p)
1774
1775 png_warning_parameter(p, 1, orig_key);
1776 png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
1777
1778 png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
1779 }
John Bowler0ac91cc2016-06-28 19:18:09 -07001780#else /* !WARNINGS */
1781 PNG_UNUSED(png_ptr)
1782#endif /* !WARNINGS */
Glenn Randers-Pehrson975cbbb2015-12-13 15:04:18 -06001783
1784 return key_len;
1785}
1786#endif /* TEXT || pCAL || iCCP || sPLT */
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -06001787#endif /* READ || WRITE */