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

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

Issue 2021403002: Update libpng to 1.6.22 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rearrange pnglibconf.h Created 4 years, 6 months 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.56 [%RDATE%] 4 * Last changed in libpng 1.6.21 [January 15, 2016]
5 * Copyright (c) 1998-2002,2004,2006-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 = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? 523 max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
460 (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; 524 (1 << info_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 if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
956 {
957 /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
958 info_ptr->trans_alpha = png_voidcast(png_bytep,
959 png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
960
961 memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
962 }
963 png_ptr->trans_alpha = info_ptr->trans_alpha;
964 }
965
966 if (trans_color != NULL)
967 {
968 #ifdef PNG_WARNINGS_SUPPORTED
969 if (info_ptr->bit_depth < 16)
970 {
971 int sample_max = (1 << info_ptr->bit_depth) - 1;
972
973 if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
974 trans_color->gray > sample_max) ||
975 (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
976 (trans_color->red > sample_max ||
977 trans_color->green > sample_max ||
978 trans_color->blue > sample_max)))
979 png_warning(png_ptr,
980 "tRNS chunk has out-of-range samples for bit_depth");
981 }
884 #endif 982 #endif
885 983
886 /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ 984 info_ptr->trans_color = *trans_color;
887 png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, 985
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) 986 if (num_trans == 0)
907 num_trans = 1; 987 num_trans = 1;
908 } 988 }
909 989
910 info_ptr->num_trans = (png_uint_16)num_trans; 990 info_ptr->num_trans = (png_uint_16)num_trans;
991
911 if (num_trans != 0) 992 if (num_trans != 0)
912 { 993 {
913 info_ptr->valid |= PNG_INFO_tRNS; 994 info_ptr->valid |= PNG_INFO_tRNS;
914 #ifdef PNG_FREE_ME_SUPPORTED
915 info_ptr->free_me |= PNG_FREE_TRNS; 995 info_ptr->free_me |= PNG_FREE_TRNS;
916 #else
917 png_ptr->flags |= PNG_FLAG_FREE_TRNS;
918 #endif
919 } 996 }
920 } 997 }
921 #endif 998 #endif
922 999
923 #ifdef PNG_sPLT_SUPPORTED 1000 #ifdef PNG_sPLT_SUPPORTED
924 void PNGAPI 1001 void PNGAPI
925 png_set_sPLT(png_structp png_ptr, 1002 png_set_sPLT(png_const_structrp png_ptr,
926 png_infop info_ptr, png_sPLT_tp entries, int nentries) 1003 png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
927 /* 1004 /*
928 * entries - array of png_sPLT_t structures 1005 * entries - array of png_sPLT_t structures
929 * to be added to the list of palettes 1006 * to be added to the list of palettes
930 * in the info structure. 1007 * in the info structure.
1008 *
931 * nentries - number of palette structures to be 1009 * nentries - number of palette structures to be
932 * added. 1010 * added.
933 */ 1011 */
934 { 1012 {
935 png_sPLT_tp np; 1013 png_sPLT_tp np;
936 int i; 1014
937 1015 if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
938 if (png_ptr == NULL || info_ptr == NULL) 1016 return;
939 return; 1017
940 1018 /* Use the internal realloc function, which checks for all the possible
941 np = (png_sPLT_tp)png_malloc_warn(png_ptr, 1019 * overflows. Notice that the parameters are (int) and (size_t)
942 (info_ptr->splt_palettes_num + nentries) * 1020 */
943 (png_uint_32)png_sizeof(png_sPLT_t)); 1021 np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
1022 info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
1023 sizeof *np));
1024
944 if (np == NULL) 1025 if (np == NULL)
945 { 1026 {
946 png_warning(png_ptr, "No memory for sPLT palettes."); 1027 /* Out of memory or too many chunks */
947 return; 1028 png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
948 } 1029
949 1030 return;
950 png_memcpy(np, info_ptr->splt_palettes, 1031 }
951 info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); 1032
952 png_free(png_ptr, info_ptr->splt_palettes); 1033 png_free(png_ptr, info_ptr->splt_palettes);
953 info_ptr->splt_palettes=NULL; 1034 info_ptr->splt_palettes = np;
954 1035 info_ptr->free_me |= PNG_FREE_SPLT;
955 for (i = 0; i < nentries; i++) 1036
956 { 1037 np += info_ptr->splt_palettes_num;
957 png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; 1038
958 png_sPLT_tp from = entries + i; 1039 do
959 png_uint_32 length; 1040 {
960 1041 png_size_t length;
961 length = png_strlen(from->name) + 1; 1042
962 to->name = (png_charp)png_malloc_warn(png_ptr, length); 1043 /* Skip invalid input entries */
963 if (to->name == NULL) 1044 if (entries->name == NULL || entries->entries == NULL)
964 { 1045 {
965 png_warning(png_ptr, 1046 /* png_handle_sPLT doesn't do this, so this is an app error */
966 "Out of memory while processing sPLT chunk"); 1047 png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
1048 /* Just skip the invalid entry */
967 continue; 1049 continue;
968 } 1050 }
969 png_memcpy(to->name, from->name, length); 1051
970 to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, 1052 np->depth = entries->depth;
971 (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry))); 1053
972 if (to->entries == NULL) 1054 /* In the event of out-of-memory just return - there's no point keeping
973 { 1055 * on trying to add sPLT chunks.
974 png_warning(png_ptr, 1056 */
975 "Out of memory while processing sPLT chunk"); 1057 length = strlen(entries->name) + 1;
976 png_free(png_ptr, to->name); 1058 np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
977 to->name = NULL; 1059
978 continue; 1060 if (np->name == NULL)
979 } 1061 break;
980 png_memcpy(to->entries, from->entries, 1062
981 from->nentries * png_sizeof(png_sPLT_entry)); 1063 memcpy(np->name, entries->name, length);
982 to->nentries = from->nentries; 1064
983 to->depth = from->depth; 1065 /* IMPORTANT: we have memory now that won't get freed if something else
984 } 1066 * goes wrong; this code must free it. png_malloc_array produces no
985 1067 * warnings; use a png_chunk_report (below) if there is an error.
986 info_ptr->splt_palettes = np; 1068 */
987 info_ptr->splt_palettes_num += nentries; 1069 np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
988 info_ptr->valid |= PNG_INFO_sPLT; 1070 entries->nentries, sizeof (png_sPLT_entry)));
989 #ifdef PNG_FREE_ME_SUPPORTED 1071
990 info_ptr->free_me |= PNG_FREE_SPLT; 1072 if (np->entries == NULL)
991 #endif 1073 {
992 } 1074 png_free(png_ptr, np->name);
993 #endif /* PNG_sPLT_SUPPORTED */ 1075 np->name = NULL;
994 1076 break;
995 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED 1077 }
1078
1079 np->nentries = entries->nentries;
1080 /* This multiply can't overflow because png_malloc_array has already
1081 * checked it when doing the allocation.
1082 */
1083 memcpy(np->entries, entries->entries,
1084 entries->nentries * sizeof (png_sPLT_entry));
1085
1086 /* Note that 'continue' skips the advance of the out pointer and out
1087 * count, so an invalid entry is not added.
1088 */
1089 info_ptr->valid |= PNG_INFO_sPLT;
1090 ++(info_ptr->splt_palettes_num);
1091 ++np;
1092 }
1093 while (++entries, --nentries);
1094
1095 if (nentries > 0)
1096 png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
1097 }
1098 #endif /* sPLT */
1099
1100 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
1101 static png_byte
1102 check_location(png_const_structrp png_ptr, int location)
1103 {
1104 location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
1105
1106 /* New in 1.6.0; copy the location and check it. This is an API
1107 * change; previously the app had to use the
1108 * png_set_unknown_chunk_location API below for each chunk.
1109 */
1110 if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
1111 {
1112 /* Write struct, so unknown chunks come from the app */
1113 png_app_warning(png_ptr,
1114 "png_set_unknown_chunks now expects a valid location");
1115 /* Use the old behavior */
1116 location = (png_byte)(png_ptr->mode &
1117 (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
1118 }
1119
1120 /* This need not be an internal error - if the app calls
1121 * png_set_unknown_chunks on a read pointer it must get the location right.
1122 */
1123 if (location == 0)
1124 png_error(png_ptr, "invalid location in png_set_unknown_chunks");
1125
1126 /* Now reduce the location to the top-most set bit by removing each least
1127 * significant bit in turn.
1128 */
1129 while (location != (location & -location))
1130 location &= ~(location & -location);
1131
1132 /* The cast is safe because 'location' is a bit mask and only the low four
1133 * bits are significant.
1134 */
1135 return (png_byte)location;
1136 }
1137
996 void PNGAPI 1138 void PNGAPI
997 png_set_unknown_chunks(png_structp png_ptr, 1139 png_set_unknown_chunks(png_const_structrp png_ptr,
998 png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) 1140 png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
999 { 1141 {
1000 png_unknown_chunkp np; 1142 png_unknown_chunkp np;
1001 int i; 1143
1002 1144 if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
1003 if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) 1145 unknowns == NULL)
1004 return; 1146 return;
1005 1147
1006 np = (png_unknown_chunkp)png_malloc_warn(png_ptr, 1148 /* Check for the failure cases where support has been disabled at compile
1007 (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) * 1149 * time. This code is hardly ever compiled - it's here because
1008 png_sizeof(png_unknown_chunk))); 1150 * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
1151 * code) but may be meaningless if the read or write handling of unknown
1152 * chunks is not compiled in.
1153 */
1154 # if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
1155 defined(PNG_READ_SUPPORTED)
1156 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
1157 {
1158 png_app_error(png_ptr, "no unknown chunk support on read");
1159
1160 return;
1161 }
1162 # endif
1163 # if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
1164 defined(PNG_WRITE_SUPPORTED)
1165 if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
1166 {
1167 png_app_error(png_ptr, "no unknown chunk support on write");
1168
1169 return;
1170 }
1171 # endif
1172
1173 /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
1174 * unknown critical chunks could be lost with just a warning resulting in
1175 * undefined behavior. Now png_chunk_report is used to provide behavior
1176 * appropriate to read or write.
1177 */
1178 np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
1179 info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
1180 sizeof *np));
1181
1009 if (np == NULL) 1182 if (np == NULL)
1010 { 1183 {
1011 png_warning(png_ptr, 1184 png_chunk_report(png_ptr, "too many unknown chunks",
1012 "Out of memory while processing unknown chunk."); 1185 PNG_CHUNK_WRITE_ERROR);
1013 return; 1186
1014 } 1187 return;
1015 1188 }
1016 png_memcpy(np, info_ptr->unknown_chunks, 1189
1017 info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1018 png_free(png_ptr, info_ptr->unknown_chunks); 1190 png_free(png_ptr, info_ptr->unknown_chunks);
1019 info_ptr->unknown_chunks = NULL; 1191 info_ptr->unknown_chunks = np; /* safe because it is initialized */
1020 1192 info_ptr->free_me |= PNG_FREE_UNKN;
1021 for (i = 0; i < num_unknowns; i++) 1193
1022 { 1194 np += info_ptr->unknown_chunks_num;
1023 png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; 1195
1024 png_unknown_chunkp from = unknowns + i; 1196 /* Increment unknown_chunks_num each time round the loop to protect the
1025 1197 * just-allocated chunk data.
1026 png_memcpy((png_charp)to->name, (png_charp)from->name, 1198 */
1027 png_sizeof(from->name)); 1199 for (; num_unknowns > 0; --num_unknowns, ++unknowns)
1028 to->name[png_sizeof(to->name)-1] = '\0'; 1200 {
1029 to->size = from->size; 1201 memcpy(np->name, unknowns->name, (sizeof np->name));
1030 /* Note our location in the read or write sequence */ 1202 np->name[(sizeof np->name)-1] = '\0';
1031 to->location = (png_byte)(png_ptr->mode & 0xff); 1203 np->location = check_location(png_ptr, unknowns->location);
1032 1204
1033 if (from->size == 0) 1205 if (unknowns->size == 0)
1034 to->data=NULL; 1206 {
1207 np->data = NULL;
1208 np->size = 0;
1209 }
1210
1035 else 1211 else
1036 { 1212 {
1037 to->data = (png_bytep)png_malloc_warn(png_ptr, 1213 np->data = png_voidcast(png_bytep,
1038 (png_uint_32)from->size); 1214 png_malloc_base(png_ptr, unknowns->size));
1039 if (to->data == NULL) 1215
1216 if (np->data == NULL)
1040 { 1217 {
1041 png_warning(png_ptr, 1218 png_chunk_report(png_ptr, "unknown chunk: out of memory",
1042 "Out of memory while processing unknown chunk."); 1219 PNG_CHUNK_WRITE_ERROR);
1043 to->size = 0; 1220 /* But just skip storing the unknown chunk */
1221 continue;
1044 } 1222 }
1223
1224 memcpy(np->data, unknowns->data, unknowns->size);
1225 np->size = unknowns->size;
1226 }
1227
1228 /* These increments are skipped on out-of-memory for the data - the
1229 * unknown chunk entry gets overwritten if the png_chunk_report returns.
1230 * This is correct in the read case (the chunk is just dropped.)
1231 */
1232 ++np;
1233 ++(info_ptr->unknown_chunks_num);
1234 }
1235 }
1236
1237 void PNGAPI
1238 png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
1239 int chunk, int location)
1240 {
1241 /* This API is pretty pointless in 1.6.0 because the location can be set
1242 * before the call to png_set_unknown_chunks.
1243 *
1244 * TODO: add a png_app_warning in 1.7
1245 */
1246 if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
1247 chunk < info_ptr->unknown_chunks_num)
1248 {
1249 if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
1250 {
1251 png_app_error(png_ptr, "invalid unknown chunk location");
1252 /* Fake out the pre 1.6.0 behavior: */
1253 if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
1254 location = PNG_AFTER_IDAT;
1255
1045 else 1256 else
1046 png_memcpy(to->data, from->data, from->size); 1257 location = PNG_HAVE_IHDR; /* also undocumented */
1047 } 1258 }
1048 } 1259
1049 1260 info_ptr->unknown_chunks[chunk].location =
1050 info_ptr->unknown_chunks = np; 1261 check_location(png_ptr, location);
1051 info_ptr->unknown_chunks_num += num_unknowns; 1262 }
1052 #ifdef PNG_FREE_ME_SUPPORTED 1263 }
1053 info_ptr->free_me |= PNG_FREE_UNKN; 1264 #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 1265
1086 #ifdef PNG_MNG_FEATURES_SUPPORTED 1266 #ifdef PNG_MNG_FEATURES_SUPPORTED
1087 png_uint_32 PNGAPI 1267 png_uint_32 PNGAPI
1088 png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) 1268 png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
1089 { 1269 {
1090 png_debug(1, "in png_permit_mng_features"); 1270 png_debug(1, "in png_permit_mng_features");
1091 1271
1092 if (png_ptr == NULL) 1272 if (png_ptr == NULL)
1093 return (png_uint_32)0; 1273 return 0;
1094 png_ptr->mng_features_permitted = 1274
1095 (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); 1275 png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
1096 return (png_uint_32)png_ptr->mng_features_permitted; 1276
1277 return png_ptr->mng_features_permitted;
1097 } 1278 }
1098 #endif 1279 #endif
1099 1280
1100 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 1281 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1282 static unsigned int
1283 add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
1284 {
1285 unsigned int i;
1286
1287 /* Utility function: update the 'keep' state of a chunk if it is already in
1288 * the list, otherwise add it to the list.
1289 */
1290 for (i=0; i<count; ++i, list += 5)
1291 {
1292 if (memcmp(list, add, 4) == 0)
1293 {
1294 list[4] = (png_byte)keep;
1295
1296 return count;
1297 }
1298 }
1299
1300 if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
1301 {
1302 ++count;
1303 memcpy(list, add, 4);
1304 list[4] = (png_byte)keep;
1305 }
1306
1307 return count;
1308 }
1309
1101 void PNGAPI 1310 void PNGAPI
1102 png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep 1311 png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
1103 chunk_list, int num_chunks) 1312 png_const_bytep chunk_list, int num_chunks_in)
1104 { 1313 {
1105 png_bytep new_list, p; 1314 png_bytep new_list;
1106 int i, old_num_chunks; 1315 unsigned int num_chunks, old_num_chunks;
1316
1107 if (png_ptr == NULL) 1317 if (png_ptr == NULL)
1108 return; 1318 return;
1109 if (num_chunks == 0) 1319
1110 { 1320 if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
1111 if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) 1321 {
1112 png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; 1322 png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
1113 else 1323
1114 png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; 1324 return;
1115 1325 }
1116 if (keep == PNG_HANDLE_CHUNK_ALWAYS) 1326
1117 png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; 1327 if (num_chunks_in <= 0)
1118 else 1328 {
1119 png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; 1329 png_ptr->unknown_default = keep;
1120 return; 1330
1121 } 1331 /* '0' means just set the flags, so stop here */
1122 if (chunk_list == NULL) 1332 if (num_chunks_in == 0)
1123 return; 1333 return;
1334 }
1335
1336 if (num_chunks_in < 0)
1337 {
1338 /* Ignore all unknown chunks and all chunks recognized by
1339 * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
1340 */
1341 static PNG_CONST png_byte chunks_to_ignore[] = {
1342 98, 75, 71, 68, '\0', /* bKGD */
1343 99, 72, 82, 77, '\0', /* cHRM */
1344 103, 65, 77, 65, '\0', /* gAMA */
1345 104, 73, 83, 84, '\0', /* hIST */
1346 105, 67, 67, 80, '\0', /* iCCP */
1347 105, 84, 88, 116, '\0', /* iTXt */
1348 111, 70, 70, 115, '\0', /* oFFs */
1349 112, 67, 65, 76, '\0', /* pCAL */
1350 112, 72, 89, 115, '\0', /* pHYs */
1351 115, 66, 73, 84, '\0', /* sBIT */
1352 115, 67, 65, 76, '\0', /* sCAL */
1353 115, 80, 76, 84, '\0', /* sPLT */
1354 115, 84, 69, 82, '\0', /* sTER */
1355 115, 82, 71, 66, '\0', /* sRGB */
1356 116, 69, 88, 116, '\0', /* tEXt */
1357 116, 73, 77, 69, '\0', /* tIME */
1358 122, 84, 88, 116, '\0' /* zTXt */
1359 };
1360
1361 chunk_list = chunks_to_ignore;
1362 num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
1363 }
1364
1365 else /* num_chunks_in > 0 */
1366 {
1367 if (chunk_list == NULL)
1368 {
1369 /* Prior to 1.6.0 this was silently ignored, now it is an app_error
1370 * which can be switched off.
1371 */
1372 png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
1373
1374 return;
1375 }
1376
1377 num_chunks = num_chunks_in;
1378 }
1379
1124 old_num_chunks = png_ptr->num_chunk_list; 1380 old_num_chunks = png_ptr->num_chunk_list;
1125 new_list=(png_bytep)png_malloc(png_ptr, 1381 if (png_ptr->chunk_list == NULL)
1126 (png_uint_32) 1382 old_num_chunks = 0;
1127 (5*(num_chunks + old_num_chunks))); 1383
1128 if (png_ptr->chunk_list != NULL) 1384 /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
1129 { 1385 */
1130 png_memcpy(new_list, png_ptr->chunk_list, 1386 if (num_chunks + old_num_chunks > UINT_MAX/5)
1131 (png_size_t)(5*old_num_chunks)); 1387 {
1132 png_free(png_ptr, png_ptr->chunk_list); 1388 png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
1133 png_ptr->chunk_list=NULL; 1389
1134 } 1390 return;
1135 png_memcpy(new_list + 5*old_num_chunks, chunk_list, 1391 }
1136 (png_size_t)(5*num_chunks)); 1392
1137 for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5) 1393 /* If these chunks are being reset to the default then no more memory is
1138 *p=(png_byte)keep; 1394 * 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; 1395 * parameter is the default.
1140 png_ptr->chunk_list = new_list; 1396 */
1141 #ifdef PNG_FREE_ME_SUPPORTED 1397 if (keep != 0)
1142 png_ptr->free_me |= PNG_FREE_LIST; 1398 {
1143 #endif 1399 new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
1400 5 * (num_chunks + old_num_chunks)));
1401
1402 if (old_num_chunks > 0)
1403 memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
1404 }
1405
1406 else if (old_num_chunks > 0)
1407 new_list = png_ptr->chunk_list;
1408
1409 else
1410 new_list = NULL;
1411
1412 /* Add the new chunks together with each one's handling code. If the chunk
1413 * already exists the code is updated, otherwise the chunk is added to the
1414 * end. (In libpng 1.6.0 order no longer matters because this code enforces
1415 * the earlier convention that the last setting is the one that is used.)
1416 */
1417 if (new_list != NULL)
1418 {
1419 png_const_bytep inlist;
1420 png_bytep outlist;
1421 unsigned int i;
1422
1423 for (i=0; i<num_chunks; ++i)
1424 {
1425 old_num_chunks = add_one_chunk(new_list, old_num_chunks,
1426 chunk_list+5*i, keep);
1427 }
1428
1429 /* Now remove any spurious 'default' entries. */
1430 num_chunks = 0;
1431 for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
1432 {
1433 if (inlist[4])
1434 {
1435 if (outlist != inlist)
1436 memcpy(outlist, inlist, 5);
1437 outlist += 5;
1438 ++num_chunks;
1439 }
1440 }
1441
1442 /* This means the application has removed all the specialized handling. */
1443 if (num_chunks == 0)
1444 {
1445 if (png_ptr->chunk_list != new_list)
1446 png_free(png_ptr, new_list);
1447
1448 new_list = NULL;
1449 }
1450 }
1451
1452 else
1453 num_chunks = 0;
1454
1455 png_ptr->num_chunk_list = num_chunks;
1456
1457 if (png_ptr->chunk_list != new_list)
1458 {
1459 if (png_ptr->chunk_list != NULL)
1460 png_free(png_ptr, png_ptr->chunk_list);
1461
1462 png_ptr->chunk_list = new_list;
1463 }
1144 } 1464 }
1145 #endif 1465 #endif
1146 1466
1147 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED 1467 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1148 void PNGAPI 1468 void PNGAPI
1149 png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, 1469 png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
1150 png_user_chunk_ptr read_user_chunk_fn) 1470 png_user_chunk_ptr read_user_chunk_fn)
1151 { 1471 {
1152 png_debug(1, "in png_set_read_user_chunk_fn"); 1472 png_debug(1, "in png_set_read_user_chunk_fn");
1153 1473
1154 if (png_ptr == NULL) 1474 if (png_ptr == NULL)
1155 return; 1475 return;
1156 1476
1157 png_ptr->read_user_chunk_fn = read_user_chunk_fn; 1477 png_ptr->read_user_chunk_fn = read_user_chunk_fn;
1158 png_ptr->user_chunk_ptr = user_chunk_ptr; 1478 png_ptr->user_chunk_ptr = user_chunk_ptr;
1159 } 1479 }
1160 #endif 1480 #endif
1161 1481
1162 #ifdef PNG_INFO_IMAGE_SUPPORTED 1482 #ifdef PNG_INFO_IMAGE_SUPPORTED
1163 void PNGAPI 1483 void PNGAPI
1164 png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) 1484 png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
1485 png_bytepp row_pointers)
1165 { 1486 {
1166 png_debug1(1, "in %s storage function", "rows"); 1487 png_debug1(1, "in %s storage function", "rows");
1167 1488
1168 if (png_ptr == NULL || info_ptr == NULL) 1489 if (png_ptr == NULL || info_ptr == NULL)
1169 return; 1490 return;
1170 1491
1171 if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) 1492 if (info_ptr->row_pointers != NULL &&
1493 (info_ptr->row_pointers != row_pointers))
1172 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 1494 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1495
1173 info_ptr->row_pointers = row_pointers; 1496 info_ptr->row_pointers = row_pointers;
1174 if (row_pointers) 1497
1498 if (row_pointers != NULL)
1175 info_ptr->valid |= PNG_INFO_IDAT; 1499 info_ptr->valid |= PNG_INFO_IDAT;
1176 } 1500 }
1177 #endif 1501 #endif
1178 1502
1179 void PNGAPI 1503 void PNGAPI
1180 png_set_compression_buffer_size(png_structp png_ptr, 1504 png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
1181 png_uint_32 size)
1182 { 1505 {
1183 if (png_ptr == NULL) 1506 if (png_ptr == NULL)
1184 return; 1507 return;
1185 png_free(png_ptr, png_ptr->zbuf); 1508
1186 png_ptr->zbuf_size = (png_size_t)size; 1509 if (size == 0 || size > PNG_UINT_31_MAX)
1187 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); 1510 png_error(png_ptr, "invalid compression buffer size");
1188 png_ptr->zstream.next_out = png_ptr->zbuf; 1511
1189 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1512 # ifdef PNG_SEQUENTIAL_READ_SUPPORTED
1190 } 1513 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
1191 1514 {
1192 void PNGAPI 1515 png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
1193 png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) 1516 return;
1194 { 1517 }
1195 if (png_ptr && info_ptr) 1518 # endif
1519
1520 # ifdef PNG_WRITE_SUPPORTED
1521 if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
1522 {
1523 if (png_ptr->zowner != 0)
1524 {
1525 png_warning(png_ptr,
1526 "Compression buffer size cannot be changed because it is in use");
1527
1528 return;
1529 }
1530
1531 #ifndef __COVERITY__
1532 /* Some compilers complain that this is always false. However, it
1533 * can be true when integer overflow happens.
1534 */
1535 if (size > ZLIB_IO_MAX)
1536 {
1537 png_warning(png_ptr,
1538 "Compression buffer size limited to system maximum");
1539 size = ZLIB_IO_MAX; /* must fit */
1540 }
1541 #endif
1542
1543 if (size < 6)
1544 {
1545 /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
1546 * if this is permitted.
1547 */
1548 png_warning(png_ptr,
1549 "Compression buffer size cannot be reduced below 6");
1550
1551 return;
1552 }
1553
1554 if (png_ptr->zbuffer_size != size)
1555 {
1556 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
1557 png_ptr->zbuffer_size = (uInt)size;
1558 }
1559 }
1560 # endif
1561 }
1562
1563 void PNGAPI
1564 png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
1565 {
1566 if (png_ptr != NULL && info_ptr != NULL)
1196 info_ptr->valid &= ~mask; 1567 info_ptr->valid &= ~mask;
1197 } 1568 }
1198 1569
1199 1570
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 1571 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
1228 /* This function was added to libpng 1.2.6 */ 1572 /* This function was added to libpng 1.2.6 */
1229 void PNGAPI 1573 void PNGAPI
1230 png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, 1574 png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
1231 png_uint_32 user_height_max) 1575 png_uint_32 user_height_max)
1232 { 1576 {
1233 /* Images with dimensions larger than these limits will be 1577 /* Images with dimensions larger than these limits will be
1234 * rejected by png_set_IHDR(). To accept any PNG datastream 1578 * rejected by png_set_IHDR(). To accept any PNG datastream
1235 * regardless of dimensions, set both limits to 0x7fffffffL. 1579 * regardless of dimensions, set both limits to 0x7fffffff.
1236 */ 1580 */
1237 if (png_ptr == NULL) 1581 if (png_ptr == NULL)
1238 return; 1582 return;
1583
1239 png_ptr->user_width_max = user_width_max; 1584 png_ptr->user_width_max = user_width_max;
1240 png_ptr->user_height_max = user_height_max; 1585 png_ptr->user_height_max = user_height_max;
1241 } 1586 }
1242 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ 1587
1588 /* This function was added to libpng 1.4.0 */
1589 void PNGAPI
1590 png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
1591 {
1592 if (png_ptr != NULL)
1593 png_ptr->user_chunk_cache_max = user_chunk_cache_max;
1594 }
1595
1596 /* This function was added to libpng 1.4.1 */
1597 void PNGAPI
1598 png_set_chunk_malloc_max (png_structrp png_ptr,
1599 png_alloc_size_t user_chunk_malloc_max)
1600 {
1601 if (png_ptr != NULL)
1602 png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1603 }
1604 #endif /* ?SET_USER_LIMITS */
1243 1605
1244 1606
1245 #ifdef PNG_BENIGN_ERRORS_SUPPORTED 1607 #ifdef PNG_BENIGN_ERRORS_SUPPORTED
1246 void PNGAPI 1608 void PNGAPI
1247 png_set_benign_errors(png_structp png_ptr, int allowed) 1609 png_set_benign_errors(png_structrp png_ptr, int allowed)
1248 { 1610 {
1249 png_debug(1, "in png_set_benign_errors"); 1611 png_debug(1, "in png_set_benign_errors");
1250 1612
1251 if (allowed) 1613 /* If allowed is 1, png_benign_error() is treated as a warning.
1252 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; 1614 *
1615 * If allowed is 0, png_benign_error() is treated as an error (which
1616 * is the default behavior if png_set_benign_errors() is not called).
1617 */
1618
1619 if (allowed != 0)
1620 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
1621 PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
1622
1253 else 1623 else
1254 png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; 1624 png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
1255 } 1625 PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
1256 #endif /* PNG_BENIGN_ERRORS_SUPPORTED */ 1626 }
1257 #endif /* ?PNG_1_0_X */ 1627 #endif /* BENIGN_ERRORS */
1258 1628
1259 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ 1629 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
1260 defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 1630 /* Whether to report invalid palette index; added at libng-1.5.10.
1631 * It is possible for an indexed (color-type==3) PNG file to contain
1632 * pixels with invalid (out-of-range) indexes if the PLTE chunk has
1633 * fewer entries than the image's bit-depth would allow. We recover
1634 * from this gracefully by filling any incomplete palette with zeros
1635 * (opaque black). By default, when this occurs libpng will issue
1636 * a benign error. This API can be used to override that behavior.
1637 */
1638 void PNGAPI
1639 png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
1640 {
1641 png_debug(1, "in png_set_check_for_invalid_index");
1642
1643 if (allowed > 0)
1644 png_ptr->num_palette_max = 0;
1645
1646 else
1647 png_ptr->num_palette_max = -1;
1648 }
1649 #endif
1650
1651 #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
1652 defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
1261 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, 1653 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1262 * and if invalid, correct the keyword rather than discarding the entire 1654 * and if invalid, correct the keyword rather than discarding the entire
1263 * chunk. The PNG 1.0 specification requires keywords 1-79 characters in 1655 * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
1264 * length, forbids leading or trailing whitespace, multiple internal spaces, 1656 * length, forbids leading or trailing whitespace, multiple internal spaces,
1265 * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. 1657 * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
1266 * 1658 *
1267 * The new_key is allocated to hold the corrected keyword and must be freed 1659 * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
1268 * by the calling routine. This avoids problems with trying to write to 1660 * trailing '\0'). If this routine returns 0 then there was no keyword, or a
1269 * static keywords without having to have duplicate copies of the strings. 1661 * valid one could not be generated, and the caller must png_error.
1270 */ 1662 */
1271 png_size_t /* PRIVATE */ 1663 png_uint_32 /* PRIVATE */
1272 png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) 1664 png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
1273 { 1665 {
1274 png_size_t key_len; 1666 png_const_charp orig_key = key;
1275 png_charp kp, dp; 1667 png_uint_32 key_len = 0;
1276 int kflag; 1668 int bad_character = 0;
1277 int kwarn=0; 1669 int space = 1;
1278 1670
1279 png_debug(1, "in png_check_keyword"); 1671 png_debug(1, "in png_check_keyword");
1280 1672
1281 *new_key = NULL; 1673 if (key == NULL)
1282 1674 {
1283 if (key == NULL || (key_len = png_strlen(key)) == 0) 1675 *new_key = 0;
1284 { 1676 return 0;
1285 png_warning(png_ptr, "zero length keyword"); 1677 }
1286 return ((png_size_t)0); 1678
1287 } 1679 while (*key && key_len < 79)
1288 1680 {
1289 png_debug1(2, "Keyword to be checked is '%s'", key); 1681 png_byte ch = (png_byte)*key++;
1290 1682
1291 *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); 1683 if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
1292 if (*new_key == NULL) 1684 *new_key++ = ch, ++key_len, space = 0;
1293 { 1685
1294 png_warning(png_ptr, "Out of memory while procesing keyword"); 1686 else if (space == 0)
1295 return ((png_size_t)0);
1296 }
1297
1298 /* Replace non-printing characters with a blank and print a warning */
1299 for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
1300 {
1301 if ((png_byte)*kp < 0x20 ||
1302 ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
1303 { 1687 {
1304 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 1688 /* A space or an invalid character when one wasn't seen immediately
1305 char msg[40]; 1689 * before; output just a space.
1306 1690 */
1307 png_snprintf(msg, 40, 1691 *new_key++ = 32, ++key_len, space = 1;
1308 "invalid keyword character 0x%02X", (png_byte)*kp); 1692
1309 png_warning(png_ptr, msg); 1693 /* If the character was not a space then it is invalid. */
1310 #else 1694 if (ch != 32)
1311 png_warning(png_ptr, "invalid character in keyword"); 1695 bad_character = ch;
1312 #endif
1313 *dp = ' ';
1314 } 1696 }
1315 else 1697
1316 { 1698 else if (bad_character == 0)
1317 *dp = *kp; 1699 bad_character = ch; /* just skip it, record the first error */
1318 } 1700 }
1319 } 1701
1320 *dp = '\0'; 1702 if (key_len > 0 && space != 0) /* trailing space */
1321 1703 {
1322 /* Remove any trailing white space. */ 1704 --key_len, --new_key;
1323 kp = *new_key + key_len - 1; 1705 if (bad_character == 0)
1324 if (*kp == ' ') 1706 bad_character = 32;
1325 { 1707 }
1326 png_warning(png_ptr, "trailing spaces removed from keyword"); 1708
1327 1709 /* Terminate the keyword */
1328 while (key_len && *kp == ' ') 1710 *new_key = 0;
1329 {
1330 *(kp--) = '\0';
1331 key_len--;
1332 }
1333 }
1334
1335 /* Remove any leading white space. */
1336 kp = *new_key;
1337 if (*kp == ' ')
1338 {
1339 png_warning(png_ptr, "leading spaces removed from keyword");
1340
1341 while (*kp == ' ')
1342 {
1343 kp++;
1344 key_len--;
1345 }
1346 }
1347
1348 png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
1349
1350 /* Remove multiple internal spaces. */
1351 for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
1352 {
1353 if (*kp == ' ' && kflag == 0)
1354 {
1355 *(dp++) = *kp;
1356 kflag = 1;
1357 }
1358 else if (*kp == ' ')
1359 {
1360 key_len--;
1361 kwarn=1;
1362 }
1363 else
1364 {
1365 *(dp++) = *kp;
1366 kflag = 0;
1367 }
1368 }
1369 *dp = '\0';
1370 if (kwarn)
1371 png_warning(png_ptr, "extra interior spaces removed from keyword");
1372 1711
1373 if (key_len == 0) 1712 if (key_len == 0)
1374 { 1713 return 0;
1375 png_free(png_ptr, *new_key); 1714
1376 *new_key=NULL; 1715 #ifdef PNG_WARNINGS_SUPPORTED
1377 png_warning(png_ptr, "Zero length keyword"); 1716 /* Try to only output one warning per keyword: */
1378 } 1717 if (*key != 0) /* keyword too long */
1379 1718 png_warning(png_ptr, "keyword truncated");
1380 if (key_len > 79) 1719
1381 { 1720 else if (bad_character != 0)
1382 png_warning(png_ptr, "keyword length must be 1 - 79 characters"); 1721 {
1383 (*new_key)[79] = '\0'; 1722 PNG_WARNING_PARAMETERS(p)
1384 key_len = 79; 1723
1385 } 1724 png_warning_parameter(p, 1, orig_key);
1386 1725 png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
1387 return (key_len); 1726
1388 } 1727 png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
1389 #endif /* WRITE_TEXT || WRITE_pCAL) || WRITE_iCCP || WRITE_sPLT */ 1728 }
1390 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ 1729 #endif /* WARNINGS */
1730
1731 return key_len;
1732 }
1733 #endif /* TEXT || pCAL || iCCP || sPLT */
1734 #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