pngset.c 50.5 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25 26 27 28 29 30 31
 */

/* pngset.c - storage of image information into info struct
 *
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file and, per its terms, should not be removed:
 *
P
prr 已提交
32
 * Last changed in libpng 1.6.26 [October 20, 2016]
33
 * Copyright (c) 1998-2016 Glenn Randers-Pehrson
D
duke 已提交
34 35 36
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
 *
B
bae 已提交
37 38 39 40
 * This code is released under the libpng license.
 * For conditions of distribution and use, see the disclaimer
 * and license in png.h
 *
D
duke 已提交
41 42 43 44 45 46
 * The functions here are used during reads to store data from the file
 * into the info struct, and during writes to store application data
 * into the info struct for writing into the file.  This abstracts the
 * info struct and allows us to change the structure in the future.
 */

B
bae 已提交
47
#include "pngpriv.h"
D
duke 已提交
48 49 50

#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

B
bae 已提交
51
#ifdef PNG_bKGD_SUPPORTED
D
duke 已提交
52
void PNGAPI
53
png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
54
    png_const_color_16p background)
D
duke 已提交
55
{
B
bae 已提交
56 57
   png_debug1(1, "in %s storage function", "bKGD");

58
   if (png_ptr == NULL || info_ptr == NULL || background == NULL)
D
duke 已提交
59 60
      return;

61
   info_ptr->background = *background;
D
duke 已提交
62 63 64 65
   info_ptr->valid |= PNG_INFO_bKGD;
}
#endif

B
bae 已提交
66 67
#ifdef PNG_cHRM_SUPPORTED
void PNGFAPI
68
png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
69 70 71
    png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
    png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
    png_fixed_point blue_x, png_fixed_point blue_y)
D
duke 已提交
72
{
73 74
   png_xy xy;

B
bae 已提交
75 76
   png_debug1(1, "in %s storage function", "cHRM fixed");

D
duke 已提交
77 78 79
   if (png_ptr == NULL || info_ptr == NULL)
      return;

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
   xy.redx = red_x;
   xy.redy = red_y;
   xy.greenx = green_x;
   xy.greeny = green_y;
   xy.bluex = blue_x;
   xy.bluey = blue_y;
   xy.whitex = white_x;
   xy.whitey = white_y;

   if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
       2/* override with app values*/) != 0)
      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;

   png_colorspace_sync_info(png_ptr, info_ptr);
}

void PNGFAPI
png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    png_fixed_point int_red_X, png_fixed_point int_red_Y,
    png_fixed_point int_red_Z, png_fixed_point int_green_X,
    png_fixed_point int_green_Y, png_fixed_point int_green_Z,
    png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
    png_fixed_point int_blue_Z)
{
   png_XYZ XYZ;

   png_debug1(1, "in %s storage function", "cHRM XYZ fixed");

   if (png_ptr == NULL || info_ptr == NULL)
      return;

   XYZ.red_X = int_red_X;
   XYZ.red_Y = int_red_Y;
   XYZ.red_Z = int_red_Z;
   XYZ.green_X = int_green_X;
   XYZ.green_Y = int_green_Y;
   XYZ.green_Z = int_green_Z;
   XYZ.blue_X = int_blue_X;
   XYZ.blue_Y = int_blue_Y;
   XYZ.blue_Z = int_blue_Z;

   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
       &XYZ, 2) != 0)
      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;

   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
126 127
}

B
bae 已提交
128
#  ifdef PNG_FLOATING_POINT_SUPPORTED
D
duke 已提交
129
void PNGAPI
130
png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
131 132
    double white_x, double white_y, double red_x, double red_y,
    double green_x, double green_y, double blue_x, double blue_y)
D
duke 已提交
133
{
B
bae 已提交
134
   png_set_cHRM_fixed(png_ptr, info_ptr,
P
prr 已提交
135 136 137 138 139 140 141 142
       png_fixed(png_ptr, white_x, "cHRM White X"),
       png_fixed(png_ptr, white_y, "cHRM White Y"),
       png_fixed(png_ptr, red_x, "cHRM Red X"),
       png_fixed(png_ptr, red_y, "cHRM Red Y"),
       png_fixed(png_ptr, green_x, "cHRM Green X"),
       png_fixed(png_ptr, green_y, "cHRM Green Y"),
       png_fixed(png_ptr, blue_x, "cHRM Blue X"),
       png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
D
duke 已提交
143
}
B
bae 已提交
144

145 146 147 148 149 150
void PNGAPI
png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
    double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
    double blue_X, double blue_Y, double blue_Z)
{
   png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
P
prr 已提交
151 152 153 154 155 156 157 158 159
       png_fixed(png_ptr, red_X, "cHRM Red X"),
       png_fixed(png_ptr, red_Y, "cHRM Red Y"),
       png_fixed(png_ptr, red_Z, "cHRM Red Z"),
       png_fixed(png_ptr, green_X, "cHRM Green X"),
       png_fixed(png_ptr, green_Y, "cHRM Green Y"),
       png_fixed(png_ptr, green_Z, "cHRM Green Z"),
       png_fixed(png_ptr, blue_X, "cHRM Blue X"),
       png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
       png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
160 161 162 163
}
#  endif /* FLOATING_POINT */

#endif /* cHRM */
B
bae 已提交
164 165 166

#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
167 168
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    png_fixed_point file_gamma)
D
duke 已提交
169
{
B
bae 已提交
170
   png_debug1(1, "in %s storage function", "gAMA");
D
duke 已提交
171 172 173 174

   if (png_ptr == NULL || info_ptr == NULL)
      return;

175 176
   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
177
}
B
bae 已提交
178 179 180

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
181
png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
B
bae 已提交
182 183 184 185 186
{
   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
       "png_set_gAMA"));
}
#  endif
D
duke 已提交
187 188
#endif

B
bae 已提交
189
#ifdef PNG_hIST_SUPPORTED
D
duke 已提交
190
void PNGAPI
191 192
png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_uint_16p hist)
D
duke 已提交
193 194 195
{
   int i;

B
bae 已提交
196 197
   png_debug1(1, "in %s storage function", "hIST");

D
duke 已提交
198 199
   if (png_ptr == NULL || info_ptr == NULL)
      return;
B
bae 已提交
200 201

   if (info_ptr->num_palette == 0 || info_ptr->num_palette
D
duke 已提交
202 203
       > PNG_MAX_PALETTE_LENGTH)
   {
B
bae 已提交
204 205 206 207
      png_warning(png_ptr,
          "Invalid palette size, hIST allocation skipped");

      return;
D
duke 已提交
208 209 210
   }

   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
B
bae 已提交
211 212 213 214

   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
    * version 1.2.1
    */
215 216
   info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
       PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
B
bae 已提交
217

218
   if (info_ptr->hist == NULL)
B
bae 已提交
219 220
   {
      png_warning(png_ptr, "Insufficient memory for hIST chunk data");
221

B
bae 已提交
222 223
      return;
   }
D
duke 已提交
224

225 226
   info_ptr->free_me |= PNG_FREE_HIST;

D
duke 已提交
227
   for (i = 0; i < info_ptr->num_palette; i++)
228
      info_ptr->hist[i] = hist[i];
B
bae 已提交
229

D
duke 已提交
230 231 232 233 234
   info_ptr->valid |= PNG_INFO_hIST;
}
#endif

void PNGAPI
235
png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
236 237 238
    png_uint_32 width, png_uint_32 height, int bit_depth,
    int color_type, int interlace_type, int compression_type,
    int filter_type)
D
duke 已提交
239
{
B
bae 已提交
240 241
   png_debug1(1, "in %s storage function", "IHDR");

D
duke 已提交
242 243 244 245 246 247
   if (png_ptr == NULL || info_ptr == NULL)
      return;

   info_ptr->width = width;
   info_ptr->height = height;
   info_ptr->bit_depth = (png_byte)bit_depth;
B
bae 已提交
248
   info_ptr->color_type = (png_byte)color_type;
D
duke 已提交
249 250 251
   info_ptr->compression_type = (png_byte)compression_type;
   info_ptr->filter_type = (png_byte)filter_type;
   info_ptr->interlace_type = (png_byte)interlace_type;
B
bae 已提交
252 253 254 255 256

   png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
       info_ptr->compression_type, info_ptr->filter_type);

D
duke 已提交
257 258
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
B
bae 已提交
259

260
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
D
duke 已提交
261
      info_ptr->channels = 3;
B
bae 已提交
262

D
duke 已提交
263 264
   else
      info_ptr->channels = 1;
B
bae 已提交
265

266
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
D
duke 已提交
267
      info_ptr->channels++;
B
bae 已提交
268

D
duke 已提交
269 270
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);

271
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
D
duke 已提交
272 273
}

B
bae 已提交
274
#ifdef PNG_oFFs_SUPPORTED
D
duke 已提交
275
void PNGAPI
276
png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
277
    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
D
duke 已提交
278
{
B
bae 已提交
279 280
   png_debug1(1, "in %s storage function", "oFFs");

D
duke 已提交
281 282 283 284 285 286 287 288 289 290
   if (png_ptr == NULL || info_ptr == NULL)
      return;

   info_ptr->x_offset = offset_x;
   info_ptr->y_offset = offset_y;
   info_ptr->offset_unit_type = (png_byte)unit_type;
   info_ptr->valid |= PNG_INFO_oFFs;
}
#endif

B
bae 已提交
291
#ifdef PNG_pCAL_SUPPORTED
D
duke 已提交
292
void PNGAPI
293
png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
294 295
    png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
    int nparams, png_const_charp units, png_charpp params)
D
duke 已提交
296
{
B
bae 已提交
297
   png_size_t length;
D
duke 已提交
298 299
   int i;

B
bae 已提交
300 301
   png_debug1(1, "in %s storage function", "pCAL");

302 303
   if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
       || (nparams > 0 && params == NULL))
D
duke 已提交
304 305
      return;

306
   length = strlen(purpose) + 1;
B
bae 已提交
307 308 309 310 311 312 313
   png_debug1(3, "allocating purpose for info (%lu bytes)",
       (unsigned long)length);

   /* TODO: validate format of calibration name and unit name */

   /* Check that the type matches the specification. */
   if (type < 0 || type > 3)
P
prr 已提交
314 315 316 317 318
   {
      png_chunk_report(png_ptr, "Invalid pCAL equation type",
            PNG_CHUNK_WRITE_ERROR);
      return;
   }
B
bae 已提交
319

320
   if (nparams < 0 || nparams > 255)
P
prr 已提交
321 322 323 324 325
   {
      png_chunk_report(png_ptr, "Invalid pCAL parameter count",
            PNG_CHUNK_WRITE_ERROR);
      return;
   }
326

B
bae 已提交
327 328
   /* Validate params[nparams] */
   for (i=0; i<nparams; ++i)
329 330 331
   {
      if (params[i] == NULL ||
          !png_check_fp_string(params[i], strlen(params[i])))
P
prr 已提交
332 333 334 335 336
      {
         png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
               PNG_CHUNK_WRITE_ERROR);
         return;
      }
337
   }
B
bae 已提交
338

339 340
   info_ptr->pcal_purpose = png_voidcast(png_charp,
       png_malloc_warn(png_ptr, length));
B
bae 已提交
341

D
duke 已提交
342
   if (info_ptr->pcal_purpose == NULL)
B
bae 已提交
343
   {
P
prr 已提交
344 345
      png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
            PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
346 347 348
      return;
   }

349
   memcpy(info_ptr->pcal_purpose, purpose, length);
D
duke 已提交
350

B
bae 已提交
351
   png_debug(3, "storing X0, X1, type, and nparams in info");
D
duke 已提交
352 353 354 355 356
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

357
   length = strlen(units) + 1;
B
bae 已提交
358
   png_debug1(3, "allocating units for info (%lu bytes)",
P
prr 已提交
359
       (unsigned long)length);
B
bae 已提交
360

361
   info_ptr->pcal_units = png_voidcast(png_charp,
P
prr 已提交
362
       png_malloc_warn(png_ptr, length));
B
bae 已提交
363

D
duke 已提交
364
   if (info_ptr->pcal_units == NULL)
B
bae 已提交
365 366
   {
      png_warning(png_ptr, "Insufficient memory for pCAL units");
367

B
bae 已提交
368 369 370
      return;
   }

371
   memcpy(info_ptr->pcal_units, units, length);
D
duke 已提交
372

373
   info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
P
prr 已提交
374
       (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
B
bae 已提交
375

D
duke 已提交
376
   if (info_ptr->pcal_params == NULL)
B
bae 已提交
377 378
   {
      png_warning(png_ptr, "Insufficient memory for pCAL params");
379

B
bae 已提交
380 381
      return;
   }
D
duke 已提交
382

P
prr 已提交
383 384
   memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
       (sizeof (png_charp)));
D
duke 已提交
385 386 387

   for (i = 0; i < nparams; i++)
   {
388
      length = strlen(params[i]) + 1;
B
bae 已提交
389 390 391
      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
          (unsigned long)length);

D
duke 已提交
392
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
B
bae 已提交
393

D
duke 已提交
394
      if (info_ptr->pcal_params[i] == NULL)
B
bae 已提交
395 396
      {
         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
397

B
bae 已提交
398 399 400
         return;
      }

401
      memcpy(info_ptr->pcal_params[i], params[i], length);
D
duke 已提交
402 403 404 405 406 407 408
   }

   info_ptr->valid |= PNG_INFO_pCAL;
   info_ptr->free_me |= PNG_FREE_PCAL;
}
#endif

B
bae 已提交
409
#ifdef PNG_sCAL_SUPPORTED
D
duke 已提交
410
void PNGAPI
411
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
412
    int unit, png_const_charp swidth, png_const_charp sheight)
D
duke 已提交
413
{
B
bae 已提交
414 415 416 417
   png_size_t lengthw = 0, lengthh = 0;

   png_debug1(1, "in %s storage function", "sCAL");

D
duke 已提交
418 419 420
   if (png_ptr == NULL || info_ptr == NULL)
      return;

B
bae 已提交
421 422 423 424 425
   /* Double check the unit (should never get here with an invalid
    * unit unless this is an API call.)
    */
   if (unit != 1 && unit != 2)
      png_error(png_ptr, "Invalid sCAL unit");
D
duke 已提交
426

427
   if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
B
bae 已提交
428 429
       swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
      png_error(png_ptr, "Invalid sCAL width");
D
duke 已提交
430

431
   if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
B
bae 已提交
432 433
       sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
      png_error(png_ptr, "Invalid sCAL height");
D
duke 已提交
434 435 436

   info_ptr->scal_unit = (png_byte)unit;

B
bae 已提交
437 438 439 440
   ++lengthw;

   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);

441
   info_ptr->scal_s_width = png_voidcast(png_charp,
P
prr 已提交
442
       png_malloc_warn(png_ptr, lengthw));
B
bae 已提交
443

D
duke 已提交
444 445
   if (info_ptr->scal_s_width == NULL)
   {
B
bae 已提交
446
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
447

B
bae 已提交
448
      return;
D
duke 已提交
449 450
   }

451
   memcpy(info_ptr->scal_s_width, swidth, lengthw);
B
bae 已提交
452 453 454 455 456

   ++lengthh;

   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);

457
   info_ptr->scal_s_height = png_voidcast(png_charp,
P
prr 已提交
458
       png_malloc_warn(png_ptr, lengthh));
B
bae 已提交
459

D
duke 已提交
460 461 462
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
B
bae 已提交
463 464 465
      info_ptr->scal_s_width = NULL;

      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
466

B
bae 已提交
467
      return;
D
duke 已提交
468
   }
B
bae 已提交
469

470
   memcpy(info_ptr->scal_s_height, sheight, lengthh);
D
duke 已提交
471 472 473 474

   info_ptr->valid |= PNG_INFO_sCAL;
   info_ptr->free_me |= PNG_FREE_SCAL;
}
B
bae 已提交
475 476 477

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
478 479
png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
    double width, double height)
B
bae 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
{
   png_debug1(1, "in %s storage function", "sCAL");

   /* Check the arguments. */
   if (width <= 0)
      png_warning(png_ptr, "Invalid sCAL width ignored");

   else if (height <= 0)
      png_warning(png_ptr, "Invalid sCAL height ignored");

   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

496
      png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
P
prr 已提交
497
          PNG_sCAL_PRECISION);
498
      png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
P
prr 已提交
499
          PNG_sCAL_PRECISION);
B
bae 已提交
500 501 502 503 504 505 506 507

      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
   }
}
#  endif

#  ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
508
png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
B
bae 已提交
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    png_fixed_point width, png_fixed_point height)
{
   png_debug1(1, "in %s storage function", "sCAL");

   /* Check the arguments. */
   if (width <= 0)
      png_warning(png_ptr, "Invalid sCAL width ignored");

   else if (height <= 0)
      png_warning(png_ptr, "Invalid sCAL height ignored");

   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

526 527
      png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
      png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
B
bae 已提交
528 529 530 531 532

      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
   }
}
#  endif
D
duke 已提交
533 534
#endif

B
bae 已提交
535
#ifdef PNG_pHYs_SUPPORTED
D
duke 已提交
536
void PNGAPI
537
png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
538
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
D
duke 已提交
539
{
B
bae 已提交
540 541
   png_debug1(1, "in %s storage function", "pHYs");

D
duke 已提交
542 543 544 545 546 547 548 549 550 551 552
   if (png_ptr == NULL || info_ptr == NULL)
      return;

   info_ptr->x_pixels_per_unit = res_x;
   info_ptr->y_pixels_per_unit = res_y;
   info_ptr->phys_unit_type = (png_byte)unit_type;
   info_ptr->valid |= PNG_INFO_pHYs;
}
#endif

void PNGAPI
553
png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
554
    png_const_colorp palette, int num_palette)
D
duke 已提交
555 556
{

557 558
   png_uint_32 max_palette_length;

B
bae 已提交
559 560
   png_debug1(1, "in %s storage function", "PLTE");

D
duke 已提交
561 562 563
   if (png_ptr == NULL || info_ptr == NULL)
      return;

564 565 566 567
   max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
      (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;

   if (num_palette < 0 || num_palette > (int) max_palette_length)
B
bae 已提交
568 569
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
D
duke 已提交
570
         png_error(png_ptr, "Invalid palette length");
B
bae 已提交
571 572 573

      else
      {
D
duke 已提交
574
         png_warning(png_ptr, "Invalid palette length");
575

D
duke 已提交
576
         return;
B
bae 已提交
577 578
      }
   }
D
duke 已提交
579

S
serb 已提交
580 581 582 583 584 585 586 587 588 589
   if ((num_palette > 0 && palette == NULL) ||
      (num_palette == 0
#        ifdef PNG_MNG_FEATURES_SUPPORTED
            && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
#        endif
      ))
   {
      png_error(png_ptr, "Invalid palette");
   }

B
bae 已提交
590
   /* It may not actually be necessary to set png_ptr->palette here;
D
duke 已提交
591 592
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
593 594 595
    *
    * 1.6.0: the above statement appears to be incorrect; something has to set
    * the palette inside png_struct on read.
D
duke 已提交
596 597 598 599
    */
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);

   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
600 601
    * of num_palette entries, in case of an invalid PNG file or incorrect
    * call to png_set_PLTE() with too-large sample values.
B
bae 已提交
602
    */
603 604
   png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
B
bae 已提交
605

606
   if (num_palette > 0)
P
prr 已提交
607 608
      memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
          (sizeof (png_color)));
D
duke 已提交
609 610 611 612 613 614 615 616
   info_ptr->palette = png_ptr->palette;
   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;

   info_ptr->free_me |= PNG_FREE_PLTE;

   info_ptr->valid |= PNG_INFO_PLTE;
}

B
bae 已提交
617
#ifdef PNG_sBIT_SUPPORTED
D
duke 已提交
618
void PNGAPI
619
png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
620
    png_const_color_8p sig_bit)
D
duke 已提交
621
{
B
bae 已提交
622 623
   png_debug1(1, "in %s storage function", "sBIT");

624
   if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
D
duke 已提交
625 626
      return;

627
   info_ptr->sig_bit = *sig_bit;
D
duke 已提交
628 629 630 631
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

B
bae 已提交
632
#ifdef PNG_sRGB_SUPPORTED
D
duke 已提交
633
void PNGAPI
634
png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
D
duke 已提交
635
{
B
bae 已提交
636 637
   png_debug1(1, "in %s storage function", "sRGB");

D
duke 已提交
638 639 640
   if (png_ptr == NULL || info_ptr == NULL)
      return;

641 642
   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
643 644 645
}

void PNGAPI
646
png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
647
    int srgb_intent)
D
duke 已提交
648
{
B
bae 已提交
649 650
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");

D
duke 已提交
651 652 653
   if (png_ptr == NULL || info_ptr == NULL)
      return;

654 655 656 657 658 659 660
   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
       srgb_intent) != 0)
   {
      /* This causes the gAMA and cHRM to be written too */
      info_ptr->colorspace.flags |=
         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
   }
D
duke 已提交
661

662
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
663
}
B
bae 已提交
664
#endif /* sRGB */
D
duke 已提交
665 666


B
bae 已提交
667
#ifdef PNG_iCCP_SUPPORTED
D
duke 已提交
668
void PNGAPI
669
png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
670 671
    png_const_charp name, int compression_type,
    png_const_bytep profile, png_uint_32 proflen)
D
duke 已提交
672 673
{
   png_charp new_iccp_name;
B
bae 已提交
674
   png_bytep new_iccp_profile;
675
   png_size_t length;
B
bae 已提交
676 677

   png_debug1(1, "in %s storage function", "iCCP");
D
duke 已提交
678 679 680 681

   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

682 683 684 685 686 687 688 689 690 691 692
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_app_error(png_ptr, "Invalid iCCP compression method");

   /* Set the colorspace first because this validates the profile; do not
    * override previously set app cHRM or gAMA here (because likely as not the
    * application knows better than libpng what the correct values are.)  Pass
    * the info_ptr color_type field to png_colorspace_set_ICC because in the
    * write case it has not yet been stored in png_ptr.
    */
   {
      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
P
prr 已提交
693
          proflen, profile, info_ptr->color_type);
694 695 696 697 698 699 700 701 702 703 704 705 706 707

      png_colorspace_sync_info(png_ptr, info_ptr);

      /* Don't do any of the copying if the profile was bad, or inconsistent. */
      if (result == 0)
         return;

      /* But do write the gAMA and cHRM chunks from the profile. */
      info_ptr->colorspace.flags |=
         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
   }

   length = strlen(name)+1;
   new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
B
bae 已提交
708

D
duke 已提交
709 710
   if (new_iccp_name == NULL)
   {
711 712
      png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");

D
duke 已提交
713 714
      return;
   }
B
bae 已提交
715

716 717
   memcpy(new_iccp_name, name, length);
   new_iccp_profile = png_voidcast(png_bytep,
P
prr 已提交
718
       png_malloc_warn(png_ptr, proflen));
B
bae 已提交
719

D
duke 已提交
720 721
   if (new_iccp_profile == NULL)
   {
722 723
      png_free(png_ptr, new_iccp_name);
      png_benign_error(png_ptr,
B
bae 已提交
724
          "Insufficient memory to process iCCP profile");
725

D
duke 已提交
726 727
      return;
   }
B
bae 已提交
728

729
   memcpy(new_iccp_profile, profile, proflen);
D
duke 已提交
730 731 732 733 734 735 736 737 738 739 740

   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);

   info_ptr->iccp_proflen = proflen;
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
   info_ptr->free_me |= PNG_FREE_ICCP;
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

B
bae 已提交
741
#ifdef PNG_TEXT_SUPPORTED
D
duke 已提交
742
void PNGAPI
743 744
png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_textp text_ptr, int num_text)
D
duke 已提交
745 746
{
   int ret;
B
bae 已提交
747 748
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);

749
   if (ret != 0)
B
bae 已提交
750
      png_error(png_ptr, "Insufficient memory to store text");
D
duke 已提交
751 752 753
}

int /* PRIVATE */
754
png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
755
    png_const_textp text_ptr, int num_text)
D
duke 已提交
756 757 758
{
   int i;

759 760
   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
      (unsigned long)png_ptr->chunk_name);
D
duke 已提交
761

762
   if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
D
duke 已提交
763 764 765
      return(0);

   /* Make sure we have enough space in the "text" array in info_struct
766 767 768
    * to hold all of the incoming text_ptr objects.  This compare can't overflow
    * because max_text >= num_text (anyway, subtract of two positive integers
    * can't overflow in any case.)
D
duke 已提交
769
    */
770
   if (num_text > info_ptr->max_text - info_ptr->num_text)
D
duke 已提交
771
   {
772 773 774
      int old_num_text = info_ptr->num_text;
      int max_text;
      png_textp new_text = NULL;
B
bae 已提交
775

776 777 778 779 780
      /* Calculate an appropriate max_text, checking for overflow. */
      max_text = old_num_text;
      if (num_text <= INT_MAX - max_text)
      {
         max_text += num_text;
B
bae 已提交
781

782 783 784
         /* Round up to a multiple of 8 */
         if (max_text < INT_MAX-8)
            max_text = (max_text + 8) & ~0x7;
A
azvegint 已提交
785

786 787 788 789 790 791 792
         else
            max_text = INT_MAX;

         /* Now allocate a new array and copy the old members in; this does all
          * the overflow checks.
          */
         new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
P
prr 已提交
793 794
             info_ptr->text, old_num_text, max_text-old_num_text,
             sizeof *new_text));
D
duke 已提交
795
      }
B
bae 已提交
796

797
      if (new_text == NULL)
D
duke 已提交
798
      {
799
         png_chunk_report(png_ptr, "too many text chunks",
P
prr 已提交
800
             PNG_CHUNK_WRITE_ERROR);
801 802

         return 1;
D
duke 已提交
803
      }
B
bae 已提交
804

805 806 807 808 809 810 811 812
      png_free(png_ptr, info_ptr->text);

      info_ptr->text = new_text;
      info_ptr->free_me |= PNG_FREE_TEXT;
      info_ptr->max_text = max_text;
      /* num_text is adjusted below as the entries are copied in */

      png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
D
duke 已提交
813
   }
814

D
duke 已提交
815 816
   for (i = 0; i < num_text; i++)
   {
817 818
      size_t text_length, key_len;
      size_t lang_len, lang_key_len;
D
duke 已提交
819 820 821 822 823
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

      if (text_ptr[i].key == NULL)
          continue;

B
bae 已提交
824 825 826
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
      {
827
         png_chunk_report(png_ptr, "text compression mode is out of range",
P
prr 已提交
828
             PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
829 830 831
         continue;
      }

832
      key_len = strlen(text_ptr[i].key);
D
duke 已提交
833

B
bae 已提交
834
      if (text_ptr[i].compression <= 0)
D
duke 已提交
835
      {
B
bae 已提交
836 837
         lang_len = 0;
         lang_key_len = 0;
D
duke 已提交
838
      }
B
bae 已提交
839

D
duke 已提交
840
      else
B
bae 已提交
841
#  ifdef PNG_iTXt_SUPPORTED
D
duke 已提交
842
      {
B
bae 已提交
843 844 845
         /* Set iTXt data */

         if (text_ptr[i].lang != NULL)
846
            lang_len = strlen(text_ptr[i].lang);
B
bae 已提交
847 848 849 850 851

         else
            lang_len = 0;

         if (text_ptr[i].lang_key != NULL)
852
            lang_key_len = strlen(text_ptr[i].lang_key);
B
bae 已提交
853 854 855

         else
            lang_key_len = 0;
D
duke 已提交
856
      }
857
#  else /* iTXt */
D
duke 已提交
858
      {
859
         png_chunk_report(png_ptr, "iTXt chunk not supported",
P
prr 已提交
860
             PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
861
         continue;
D
duke 已提交
862
      }
B
bae 已提交
863
#  endif
D
duke 已提交
864 865 866 867

      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
      {
         text_length = 0;
B
bae 已提交
868 869
#  ifdef PNG_iTXt_SUPPORTED
         if (text_ptr[i].compression > 0)
D
duke 已提交
870
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
B
bae 已提交
871

D
duke 已提交
872
         else
B
bae 已提交
873
#  endif
D
duke 已提交
874 875
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
      }
B
bae 已提交
876

D
duke 已提交
877 878
      else
      {
879
         text_length = strlen(text_ptr[i].text);
D
duke 已提交
880 881 882
         textp->compression = text_ptr[i].compression;
      }

883 884
      textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
          key_len + text_length + lang_len + lang_key_len + 4));
B
bae 已提交
885

D
duke 已提交
886
      if (textp->key == NULL)
887 888
      {
         png_chunk_report(png_ptr, "text chunk: out of memory",
P
prr 已提交
889
             PNG_CHUNK_WRITE_ERROR);
890 891 892

         return 1;
      }
B
bae 已提交
893 894 895 896 897 898

      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
          (unsigned long)(png_uint_32)
          (key_len + lang_len + lang_key_len + text_length + 4),
          textp->key);

899
      memcpy(textp->key, text_ptr[i].key, key_len);
B
bae 已提交
900 901
      *(textp->key + key_len) = '\0';

D
duke 已提交
902 903
      if (text_ptr[i].compression > 0)
      {
B
bae 已提交
904
         textp->lang = textp->key + key_len + 1;
905
         memcpy(textp->lang, text_ptr[i].lang, lang_len);
B
bae 已提交
906 907
         *(textp->lang + lang_len) = '\0';
         textp->lang_key = textp->lang + lang_len + 1;
908
         memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
B
bae 已提交
909 910
         *(textp->lang_key + lang_key_len) = '\0';
         textp->text = textp->lang_key + lang_key_len + 1;
D
duke 已提交
911
      }
B
bae 已提交
912

D
duke 已提交
913 914 915 916
      else
      {
         textp->lang=NULL;
         textp->lang_key=NULL;
B
bae 已提交
917
         textp->text = textp->key + key_len + 1;
D
duke 已提交
918
      }
B
bae 已提交
919

920 921
      if (text_length != 0)
         memcpy(textp->text, text_ptr[i].text, text_length);
D
duke 已提交
922

B
bae 已提交
923 924 925 926
      *(textp->text + text_length) = '\0';

#  ifdef PNG_iTXt_SUPPORTED
      if (textp->compression > 0)
D
duke 已提交
927 928 929 930
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
B
bae 已提交
931

D
duke 已提交
932
      else
B
bae 已提交
933
#  endif
D
duke 已提交
934 935 936 937
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
B
bae 已提交
938

D
duke 已提交
939
      info_ptr->num_text++;
B
bae 已提交
940
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
D
duke 已提交
941
   }
942

D
duke 已提交
943 944 945 946
   return(0);
}
#endif

B
bae 已提交
947
#ifdef PNG_tIME_SUPPORTED
D
duke 已提交
948
void PNGAPI
949 950
png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_timep mod_time)
D
duke 已提交
951
{
B
bae 已提交
952 953
   png_debug1(1, "in %s storage function", "tIME");

954 955
   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
       (png_ptr->mode & PNG_WROTE_tIME) != 0)
D
duke 已提交
956 957
      return;

958 959 960 961 962 963 964 965 966 967 968
   if (mod_time->month == 0   || mod_time->month > 12  ||
       mod_time->day   == 0   || mod_time->day   > 31  ||
       mod_time->hour  > 23   || mod_time->minute > 59 ||
       mod_time->second > 60)
   {
      png_warning(png_ptr, "Ignoring invalid time value");

      return;
   }

   info_ptr->mod_time = *mod_time;
D
duke 已提交
969 970 971 972
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

B
bae 已提交
973
#ifdef PNG_tRNS_SUPPORTED
D
duke 已提交
974
void PNGAPI
975
png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
976
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
D
duke 已提交
977
{
B
bae 已提交
978 979
   png_debug1(1, "in %s storage function", "tRNS");

D
duke 已提交
980
   if (png_ptr == NULL || info_ptr == NULL)
981

D
duke 已提交
982 983
      return;

B
bae 已提交
984
   if (trans_alpha != NULL)
D
duke 已提交
985
   {
B
bae 已提交
986
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
D
duke 已提交
987 988
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
989 990 991 992
        *
        * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
        * relies on png_set_tRNS storing the information in png_struct
        * (otherwise it won't be there for the code in pngrtran.c).
D
duke 已提交
993
        */
B
bae 已提交
994

D
duke 已提交
995
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
B
bae 已提交
996 997

       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
998 999 1000
       {
         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
          info_ptr->trans_alpha = png_voidcast(png_bytep,
P
prr 已提交
1001
              png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
1002
          memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
1003 1004
       }
       png_ptr->trans_alpha = info_ptr->trans_alpha;
D
duke 已提交
1005 1006
   }

B
bae 已提交
1007
   if (trans_color != NULL)
D
duke 已提交
1008
   {
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
#ifdef PNG_WARNINGS_SUPPORTED
      if (info_ptr->bit_depth < 16)
      {
         int sample_max = (1 << info_ptr->bit_depth) - 1;

         if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
             trans_color->gray > sample_max) ||
             (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
             (trans_color->red > sample_max ||
             trans_color->green > sample_max ||
             trans_color->blue > sample_max)))
            png_warning(png_ptr,
P
prr 已提交
1021
                "tRNS chunk has out-of-range samples for bit_depth");
1022 1023
      }
#endif
B
bae 已提交
1024

1025
      info_ptr->trans_color = *trans_color;
B
bae 已提交
1026

D
duke 已提交
1027
      if (num_trans == 0)
B
bae 已提交
1028
         num_trans = 1;
D
duke 已提交
1029
   }
B
bae 已提交
1030

D
duke 已提交
1031
   info_ptr->num_trans = (png_uint_16)num_trans;
B
bae 已提交
1032 1033 1034 1035 1036 1037

   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
      info_ptr->free_me |= PNG_FREE_TRNS;
   }
D
duke 已提交
1038 1039 1040
}
#endif

B
bae 已提交
1041
#ifdef PNG_sPLT_SUPPORTED
D
duke 已提交
1042
void PNGAPI
1043 1044
png_set_sPLT(png_const_structrp png_ptr,
    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
B
bae 已提交
1045 1046 1047 1048 1049 1050 1051 1052
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
 *
 *  nentries       - number of palette structures to be
 *                   added.
 */
D
duke 已提交
1053
{
B
bae 已提交
1054
   png_sPLT_tp np;
D
duke 已提交
1055

1056
   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
B
bae 已提交
1057
      return;
D
duke 已提交
1058

1059 1060 1061 1062
   /* Use the internal realloc function, which checks for all the possible
    * overflows.  Notice that the parameters are (int) and (size_t)
    */
   np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
P
prr 已提交
1063 1064
       info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
       sizeof *np));
B
bae 已提交
1065 1066 1067

   if (np == NULL)
   {
1068 1069 1070
      /* Out of memory or too many chunks */
      png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);

D
duke 已提交
1071
      return;
B
bae 已提交
1072
   }
D
duke 已提交
1073

A
azvegint 已提交
1074
   png_free(png_ptr, info_ptr->splt_palettes);
1075 1076
   info_ptr->splt_palettes = np;
   info_ptr->free_me |= PNG_FREE_SPLT;
B
bae 已提交
1077

1078
   np += info_ptr->splt_palettes_num;
A
azvegint 已提交
1079

1080 1081 1082
   do
   {
      png_size_t length;
B
bae 已提交
1083

1084 1085
      /* Skip invalid input entries */
      if (entries->name == NULL || entries->entries == NULL)
B
bae 已提交
1086
      {
1087 1088 1089
         /* png_handle_sPLT doesn't do this, so this is an app error */
         png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
         /* Just skip the invalid entry */
B
bae 已提交
1090 1091 1092
         continue;
      }

1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
      np->depth = entries->depth;

      /* In the event of out-of-memory just return - there's no point keeping
       * on trying to add sPLT chunks.
       */
      length = strlen(entries->name) + 1;
      np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));

      if (np->name == NULL)
         break;

      memcpy(np->name, entries->name, length);

      /* IMPORTANT: we have memory now that won't get freed if something else
       * goes wrong; this code must free it.  png_malloc_array produces no
       * warnings; use a png_chunk_report (below) if there is an error.
       */
      np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
          entries->nentries, sizeof (png_sPLT_entry)));
B
bae 已提交
1112

1113
      if (np->entries == NULL)
B
bae 已提交
1114
      {
1115 1116 1117
         png_free(png_ptr, np->name);
         np->name = NULL;
         break;
B
bae 已提交
1118 1119
      }

1120 1121 1122 1123 1124
      np->nentries = entries->nentries;
      /* This multiply can't overflow because png_malloc_array has already
       * checked it when doing the allocation.
       */
      memcpy(np->entries, entries->entries,
P
prr 已提交
1125
          (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145

      /* Note that 'continue' skips the advance of the out pointer and out
       * count, so an invalid entry is not added.
       */
      info_ptr->valid |= PNG_INFO_sPLT;
      ++(info_ptr->splt_palettes_num);
      ++np;
   }
   while (++entries, --nentries);

   if (nentries > 0)
      png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
}
#endif /* sPLT */

#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_byte
check_location(png_const_structrp png_ptr, int location)
{
   location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
B
bae 已提交
1146

1147 1148 1149 1150 1151 1152 1153 1154
   /* New in 1.6.0; copy the location and check it.  This is an API
    * change; previously the app had to use the
    * png_set_unknown_chunk_location API below for each chunk.
    */
   if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
   {
      /* Write struct, so unknown chunks come from the app */
      png_app_warning(png_ptr,
P
prr 已提交
1155
          "png_set_unknown_chunks now expects a valid location");
1156 1157
      /* Use the old behavior */
      location = (png_byte)(png_ptr->mode &
P
prr 已提交
1158
          (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
B
bae 已提交
1159 1160
   }

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
   /* This need not be an internal error - if the app calls
    * png_set_unknown_chunks on a read pointer it must get the location right.
    */
   if (location == 0)
      png_error(png_ptr, "invalid location in png_set_unknown_chunks");

   /* Now reduce the location to the top-most set bit by removing each least
    * significant bit in turn.
    */
   while (location != (location & -location))
      location &= ~(location & -location);

   /* The cast is safe because 'location' is a bit mask and only the low four
    * bits are significant.
    */
   return (png_byte)location;
D
duke 已提交
1177 1178 1179
}

void PNGAPI
1180
png_set_unknown_chunks(png_const_structrp png_ptr,
P
prr 已提交
1181
    png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
D
duke 已提交
1182
{
B
bae 已提交
1183 1184
   png_unknown_chunkp np;

1185 1186
   if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
       unknowns == NULL)
B
bae 已提交
1187
      return;
D
duke 已提交
1188

1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
   /* Check for the failure cases where support has been disabled at compile
    * time.  This code is hardly ever compiled - it's here because
    * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
    * code) but may be meaningless if the read or write handling of unknown
    * chunks is not compiled in.
    */
#  if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
      defined(PNG_READ_SUPPORTED)
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
      {
         png_app_error(png_ptr, "no unknown chunk support on read");

         return;
      }
#  endif
#  if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
      defined(PNG_WRITE_SUPPORTED)
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
      {
         png_app_error(png_ptr, "no unknown chunk support on write");

         return;
      }
#  endif

   /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
    * unknown critical chunks could be lost with just a warning resulting in
    * undefined behavior.  Now png_chunk_report is used to provide behavior
    * appropriate to read or write.
    */
   np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
P
prr 已提交
1220 1221
       info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
       sizeof *np));
D
duke 已提交
1222

B
bae 已提交
1223 1224
   if (np == NULL)
   {
1225
      png_chunk_report(png_ptr, "too many unknown chunks",
P
prr 已提交
1226
          PNG_CHUNK_WRITE_ERROR);
1227

B
bae 已提交
1228 1229
      return;
   }
D
duke 已提交
1230

A
azvegint 已提交
1231
   png_free(png_ptr, info_ptr->unknown_chunks);
1232 1233
   info_ptr->unknown_chunks = np; /* safe because it is initialized */
   info_ptr->free_me |= PNG_FREE_UNKN;
B
bae 已提交
1234

1235
   np += info_ptr->unknown_chunks_num;
A
azvegint 已提交
1236

1237 1238 1239 1240 1241 1242 1243 1244
   /* Increment unknown_chunks_num each time round the loop to protect the
    * just-allocated chunk data.
    */
   for (; num_unknowns > 0; --num_unknowns, ++unknowns)
   {
      memcpy(np->name, unknowns->name, (sizeof np->name));
      np->name[(sizeof np->name)-1] = '\0';
      np->location = check_location(png_ptr, unknowns->location);
A
azvegint 已提交
1245

1246 1247 1248 1249 1250
      if (unknowns->size == 0)
      {
         np->data = NULL;
         np->size = 0;
      }
B
bae 已提交
1251 1252 1253

      else
      {
1254
         np->data = png_voidcast(png_bytep,
P
prr 已提交
1255
             png_malloc_base(png_ptr, unknowns->size));
B
bae 已提交
1256

1257
         if (np->data == NULL)
B
bae 已提交
1258
         {
1259
            png_chunk_report(png_ptr, "unknown chunk: out of memory",
P
prr 已提交
1260
                PNG_CHUNK_WRITE_ERROR);
1261 1262
            /* But just skip storing the unknown chunk */
            continue;
B
bae 已提交
1263 1264
         }

1265 1266
         memcpy(np->data, unknowns->data, unknowns->size);
         np->size = unknowns->size;
B
bae 已提交
1267
      }
A
azvegint 已提交
1268

1269 1270 1271 1272 1273 1274 1275
      /* These increments are skipped on out-of-memory for the data - the
       * unknown chunk entry gets overwritten if the png_chunk_report returns.
       * This is correct in the read case (the chunk is just dropped.)
       */
      ++np;
      ++(info_ptr->unknown_chunks_num);
   }
D
duke 已提交
1276
}
B
bae 已提交
1277

D
duke 已提交
1278
void PNGAPI
1279
png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
1280
    int chunk, int location)
D
duke 已提交
1281
{
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
   /* This API is pretty pointless in 1.6.0 because the location can be set
    * before the call to png_set_unknown_chunks.
    *
    * TODO: add a png_app_warning in 1.7
    */
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
      chunk < info_ptr->unknown_chunks_num)
   {
      if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
      {
         png_app_error(png_ptr, "invalid unknown chunk location");
         /* Fake out the pre 1.6.0 behavior: */
P
prr 已提交
1294
         if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
1295 1296 1297 1298 1299
            location = PNG_AFTER_IDAT;

         else
            location = PNG_HAVE_IHDR; /* also undocumented */
      }
D
duke 已提交
1300

1301 1302 1303 1304 1305
      info_ptr->unknown_chunks[chunk].location =
         check_location(png_ptr, location);
   }
}
#endif /* STORE_UNKNOWN_CHUNKS */
D
duke 已提交
1306

B
bae 已提交
1307
#ifdef PNG_MNG_FEATURES_SUPPORTED
D
duke 已提交
1308
png_uint_32 PNGAPI
1309
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
D
duke 已提交
1310
{
B
bae 已提交
1311 1312
   png_debug(1, "in png_permit_mng_features");

D
duke 已提交
1313
   if (png_ptr == NULL)
1314
      return 0;
B
bae 已提交
1315

1316
   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
B
bae 已提交
1317

1318
   return png_ptr->mng_features_permitted;
D
duke 已提交
1319 1320 1321
}
#endif

B
bae 已提交
1322
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
static unsigned int
add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
{
   unsigned int i;

   /* Utility function: update the 'keep' state of a chunk if it is already in
    * the list, otherwise add it to the list.
    */
   for (i=0; i<count; ++i, list += 5)
   {
      if (memcmp(list, add, 4) == 0)
      {
         list[4] = (png_byte)keep;

         return count;
      }
   }

   if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
   {
      ++count;
      memcpy(list, add, 4);
      list[4] = (png_byte)keep;
   }

   return count;
}

D
duke 已提交
1351
void PNGAPI
1352 1353
png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
    png_const_bytep chunk_list, int num_chunks_in)
D
duke 已提交
1354
{
1355 1356 1357
   png_bytep new_list;
   unsigned int num_chunks, old_num_chunks;

B
bae 已提交
1358 1359 1360
   if (png_ptr == NULL)
      return;

1361
   if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
B
bae 已提交
1362
   {
1363
      png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
B
bae 已提交
1364

1365 1366
      return;
   }
B
bae 已提交
1367

1368 1369 1370
   if (num_chunks_in <= 0)
   {
      png_ptr->unknown_default = keep;
A
azvegint 已提交
1371

1372 1373 1374 1375
      /* '0' means just set the flags, so stop here */
      if (num_chunks_in == 0)
        return;
   }
A
azvegint 已提交
1376

1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
   if (num_chunks_in < 0)
   {
      /* Ignore all unknown chunks and all chunks recognized by
       * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
       */
      static PNG_CONST png_byte chunks_to_ignore[] = {
         98,  75,  71,  68, '\0',  /* bKGD */
         99,  72,  82,  77, '\0',  /* cHRM */
        103,  65,  77,  65, '\0',  /* gAMA */
        104,  73,  83,  84, '\0',  /* hIST */
        105,  67,  67,  80, '\0',  /* iCCP */
        105,  84,  88, 116, '\0',  /* iTXt */
        111,  70,  70, 115, '\0',  /* oFFs */
        112,  67,  65,  76, '\0',  /* pCAL */
        112,  72,  89, 115, '\0',  /* pHYs */
        115,  66,  73,  84, '\0',  /* sBIT */
        115,  67,  65,  76, '\0',  /* sCAL */
        115,  80,  76,  84, '\0',  /* sPLT */
        115,  84,  69,  82, '\0',  /* sTER */
        115,  82,  71,  66, '\0',  /* sRGB */
        116,  69,  88, 116, '\0',  /* tEXt */
        116,  73,  77,  69, '\0',  /* tIME */
        122,  84,  88, 116, '\0'   /* zTXt */
      };

      chunk_list = chunks_to_ignore;
      num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
A
azvegint 已提交
1404
   }
B
bae 已提交
1405

1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
   else /* num_chunks_in > 0 */
   {
      if (chunk_list == NULL)
      {
         /* Prior to 1.6.0 this was silently ignored, now it is an app_error
          * which can be switched off.
          */
         png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");

         return;
      }

P
prr 已提交
1418
      num_chunks = (unsigned int)num_chunks_in;
1419
   }
A
azvegint 已提交
1420

A
azvegint 已提交
1421
   old_num_chunks = png_ptr->num_chunk_list;
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
   if (png_ptr->chunk_list == NULL)
      old_num_chunks = 0;

   /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
    */
   if (num_chunks + old_num_chunks > UINT_MAX/5)
   {
      png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");

      return;
   }

   /* If these chunks are being reset to the default then no more memory is
    * required because add_one_chunk above doesn't extend the list if the 'keep'
    * parameter is the default.
    */
   if (keep != 0)
   {
      new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
          5 * (num_chunks + old_num_chunks)));
B
bae 已提交
1442

1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
      if (old_num_chunks > 0)
         memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
   }

   else if (old_num_chunks > 0)
      new_list = png_ptr->chunk_list;

   else
      new_list = NULL;

   /* Add the new chunks together with each one's handling code.  If the chunk
    * already exists the code is updated, otherwise the chunk is added to the
    * end.  (In libpng 1.6.0 order no longer matters because this code enforces
    * the earlier convention that the last setting is the one that is used.)
    */
   if (new_list != NULL)
B
bae 已提交
1459
   {
1460 1461 1462 1463 1464 1465 1466
      png_const_bytep inlist;
      png_bytep outlist;
      unsigned int i;

      for (i=0; i<num_chunks; ++i)
      {
         old_num_chunks = add_one_chunk(new_list, old_num_chunks,
P
prr 已提交
1467
             chunk_list+5*i, keep);
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
      }

      /* Now remove any spurious 'default' entries. */
      num_chunks = 0;
      for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
      {
         if (inlist[4])
         {
            if (outlist != inlist)
               memcpy(outlist, inlist, 5);
            outlist += 5;
            ++num_chunks;
         }
      }

      /* This means the application has removed all the specialized handling. */
      if (num_chunks == 0)
      {
         if (png_ptr->chunk_list != new_list)
            png_free(png_ptr, new_list);

         new_list = NULL;
      }
B
bae 已提交
1491 1492
   }

1493 1494 1495 1496
   else
      num_chunks = 0;

   png_ptr->num_chunk_list = num_chunks;
B
bae 已提交
1497

1498 1499 1500 1501
   if (png_ptr->chunk_list != new_list)
   {
      if (png_ptr->chunk_list != NULL)
         png_free(png_ptr, png_ptr->chunk_list);
B
bae 已提交
1502

1503 1504
      png_ptr->chunk_list = new_list;
   }
D
duke 已提交
1505 1506 1507
}
#endif

B
bae 已提交
1508
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
D
duke 已提交
1509
void PNGAPI
1510
png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
B
bae 已提交
1511
    png_user_chunk_ptr read_user_chunk_fn)
D
duke 已提交
1512
{
B
bae 已提交
1513 1514
   png_debug(1, "in png_set_read_user_chunk_fn");

D
duke 已提交
1515 1516
   if (png_ptr == NULL)
      return;
B
bae 已提交
1517

D
duke 已提交
1518 1519 1520 1521 1522
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif

B
bae 已提交
1523
#ifdef PNG_INFO_IMAGE_SUPPORTED
D
duke 已提交
1524
void PNGAPI
1525 1526
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
    png_bytepp row_pointers)
D
duke 已提交
1527
{
B
bae 已提交
1528
   png_debug1(1, "in %s storage function", "rows");
D
duke 已提交
1529 1530 1531 1532

   if (png_ptr == NULL || info_ptr == NULL)
      return;

1533 1534
   if (info_ptr->row_pointers != NULL &&
       (info_ptr->row_pointers != row_pointers))
D
duke 已提交
1535
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
B
bae 已提交
1536

D
duke 已提交
1537
   info_ptr->row_pointers = row_pointers;
B
bae 已提交
1538

1539
   if (row_pointers != NULL)
D
duke 已提交
1540 1541 1542 1543 1544
      info_ptr->valid |= PNG_INFO_IDAT;
}
#endif

void PNGAPI
1545
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
D
duke 已提交
1546
{
P
prr 已提交
1547 1548
   if (png_ptr == NULL)
      return;
B
bae 已提交
1549

P
prr 已提交
1550 1551
   if (size == 0 || size > PNG_UINT_31_MAX)
      png_error(png_ptr, "invalid compression buffer size");
B
bae 已提交
1552

1553
#  ifdef PNG_SEQUENTIAL_READ_SUPPORTED
P
prr 已提交
1554 1555 1556 1557 1558
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
   {
      png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
      return;
   }
1559 1560 1561
#  endif

#  ifdef PNG_WRITE_SUPPORTED
P
prr 已提交
1562 1563 1564
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
   {
      if (png_ptr->zowner != 0)
1565
      {
P
prr 已提交
1566 1567
         png_warning(png_ptr,
             "Compression buffer size cannot be changed because it is in use");
1568

P
prr 已提交
1569 1570
         return;
      }
B
bae 已提交
1571

1572
#ifndef __COVERITY__
P
prr 已提交
1573 1574 1575 1576 1577 1578 1579 1580 1581
      /* Some compilers complain that this is always false.  However, it
       * can be true when integer overflow happens.
       */
      if (size > ZLIB_IO_MAX)
      {
         png_warning(png_ptr,
             "Compression buffer size limited to system maximum");
         size = ZLIB_IO_MAX; /* must fit */
      }
1582
#endif
B
bae 已提交
1583

P
prr 已提交
1584 1585 1586 1587 1588 1589 1590
      if (size < 6)
      {
         /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
          * if this is permitted.
          */
         png_warning(png_ptr,
             "Compression buffer size cannot be reduced below 6");
1591

P
prr 已提交
1592 1593
         return;
      }
B
bae 已提交
1594

P
prr 已提交
1595 1596 1597 1598
      if (png_ptr->zbuffer_size != size)
      {
         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
         png_ptr->zbuffer_size = (uInt)size;
1599
      }
P
prr 已提交
1600
   }
1601
#  endif
D
duke 已提交
1602 1603 1604
}

void PNGAPI
1605
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
D
duke 已提交
1606
{
1607
   if (png_ptr != NULL && info_ptr != NULL)
P
prr 已提交
1608
      info_ptr->valid &= (unsigned int)(~mask);
D
duke 已提交
1609 1610 1611
}


B
bae 已提交
1612 1613
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
D
duke 已提交
1614
void PNGAPI
1615
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
B
bae 已提交
1616
    png_uint_32 user_height_max)
D
duke 已提交
1617
{
B
bae 已提交
1618 1619
   /* Images with dimensions larger than these limits will be
    * rejected by png_set_IHDR().  To accept any PNG datastream
1620
    * regardless of dimensions, set both limits to 0x7fffffff.
B
bae 已提交
1621 1622 1623
    */
   if (png_ptr == NULL)
      return;
D
duke 已提交
1624

B
bae 已提交
1625 1626
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
D
duke 已提交
1627 1628
}

B
bae 已提交
1629
/* This function was added to libpng 1.4.0 */
D
duke 已提交
1630
void PNGAPI
1631
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
D
duke 已提交
1632
{
1633 1634
   if (png_ptr != NULL)
      png_ptr->user_chunk_cache_max = user_chunk_cache_max;
D
duke 已提交
1635 1636
}

B
bae 已提交
1637
/* This function was added to libpng 1.4.1 */
D
duke 已提交
1638
void PNGAPI
1639
png_set_chunk_malloc_max (png_structrp png_ptr,
B
bae 已提交
1640
    png_alloc_size_t user_chunk_malloc_max)
D
duke 已提交
1641
{
1642
   if (png_ptr != NULL)
B
bae 已提交
1643
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
D
duke 已提交
1644
}
1645
#endif /* ?SET_USER_LIMITS */
D
duke 已提交
1646

B
bae 已提交
1647 1648 1649

#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
1650
png_set_benign_errors(png_structrp png_ptr, int allowed)
B
bae 已提交
1651 1652 1653
{
   png_debug(1, "in png_set_benign_errors");

1654 1655 1656 1657 1658 1659 1660 1661 1662
   /* If allowed is 1, png_benign_error() is treated as a warning.
    *
    * If allowed is 0, png_benign_error() is treated as an error (which
    * is the default behavior if png_set_benign_errors() is not called).
    */

   if (allowed != 0)
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
B
bae 已提交
1663 1664

   else
1665 1666
      png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
B
bae 已提交
1667
}
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690
#endif /* BENIGN_ERRORS */

#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
   /* Whether to report invalid palette index; added at libng-1.5.10.
    * It is possible for an indexed (color-type==3) PNG file to contain
    * pixels with invalid (out-of-range) indexes if the PLTE chunk has
    * fewer entries than the image's bit-depth would allow. We recover
    * from this gracefully by filling any incomplete palette with zeros
    * (opaque black).  By default, when this occurs libpng will issue
    * a benign error.  This API can be used to override that behavior.
    */
void PNGAPI
png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
{
   png_debug(1, "in png_set_check_for_invalid_index");

   if (allowed > 0)
      png_ptr->num_palette_max = 0;

   else
      png_ptr->num_palette_max = -1;
}
#endif
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706

#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
 * and if invalid, correct the keyword rather than discarding the entire
 * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
 * length, forbids leading or trailing whitespace, multiple internal spaces,
 * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
 *
 * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
 * trailing '\0').  If this routine returns 0 then there was no keyword, or a
 * valid one could not be generated, and the caller must png_error.
 */
png_uint_32 /* PRIVATE */
png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
{
P
prr 已提交
1707
#ifdef PNG_WARNINGS_SUPPORTED
1708
   png_const_charp orig_key = key;
P
prr 已提交
1709
#endif
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
   png_uint_32 key_len = 0;
   int bad_character = 0;
   int space = 1;

   png_debug(1, "in png_check_keyword");

   if (key == NULL)
   {
      *new_key = 0;
      return 0;
   }

   while (*key && key_len < 79)
   {
      png_byte ch = (png_byte)*key++;

      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
         *new_key++ = ch, ++key_len, space = 0;

      else if (space == 0)
      {
         /* A space or an invalid character when one wasn't seen immediately
          * before; output just a space.
          */
         *new_key++ = 32, ++key_len, space = 1;

         /* If the character was not a space then it is invalid. */
         if (ch != 32)
            bad_character = ch;
      }

      else if (bad_character == 0)
         bad_character = ch; /* just skip it, record the first error */
   }

   if (key_len > 0 && space != 0) /* trailing space */
   {
      --key_len, --new_key;
      if (bad_character == 0)
         bad_character = 32;
   }

   /* Terminate the keyword */
   *new_key = 0;

   if (key_len == 0)
      return 0;

#ifdef PNG_WARNINGS_SUPPORTED
   /* Try to only output one warning per keyword: */
   if (*key != 0) /* keyword too long */
      png_warning(png_ptr, "keyword truncated");

   else if (bad_character != 0)
   {
      PNG_WARNING_PARAMETERS(p)

      png_warning_parameter(p, 1, orig_key);
      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);

      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   }
P
prr 已提交
1772 1773 1774
#else /* !WARNINGS */
   PNG_UNUSED(png_ptr)
#endif /* !WARNINGS */
1775 1776 1777 1778

   return key_len;
}
#endif /* TEXT || pCAL || iCCP || sPLT */
1779
#endif /* READ || WRITE */