Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: third_party/libpng/pngset.c

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

Powered by Google App Engine
This is Rietveld 408576698