LCOV - code coverage report
Current view: top level - media/libpng - pngpread.c (source / functions) Hit Total Coverage
Test: output.info Lines: 246 483 50.9 %
Date: 2017-07-14 16:53:18 Functions: 17 20 85.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /* pngpread.c - read a png file in push mode
       3             :  *
       4             :  * Last changed in libpng 1.6.24 [August 4, 2016]
       5             :  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
       6             :  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
       7             :  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
       8             :  *
       9             :  * This code is released under the libpng license.
      10             :  * For conditions of distribution and use, see the disclaimer
      11             :  * and license in png.h
      12             :  */
      13             : 
      14             : #include "pngpriv.h"
      15             : 
      16             : #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
      17             : 
      18             : /* Push model modes */
      19             : #define PNG_READ_SIG_MODE   0
      20             : #define PNG_READ_CHUNK_MODE 1
      21             : #define PNG_READ_IDAT_MODE  2
      22             : #define PNG_READ_tEXt_MODE  4
      23             : #define PNG_READ_zTXt_MODE  5
      24             : #define PNG_READ_DONE_MODE  6
      25             : #define PNG_READ_iTXt_MODE  7
      26             : #define PNG_ERROR_MODE      8
      27             : 
      28             : #define PNG_PUSH_SAVE_BUFFER_IF_FULL \
      29             : if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
      30             :    { png_push_save_buffer(png_ptr); return; }
      31             : #define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
      32             : if (png_ptr->buffer_size < N) \
      33             :    { png_push_save_buffer(png_ptr); return; }
      34             : 
      35             : void PNGAPI
      36          65 : png_process_data(png_structrp png_ptr, png_inforp info_ptr,
      37             :     png_bytep buffer, png_size_t buffer_size)
      38             : {
      39          65 :    if (png_ptr == NULL || info_ptr == NULL)
      40           0 :       return;
      41             : 
      42          65 :    png_push_restore_buffer(png_ptr, buffer, buffer_size);
      43             : 
      44         461 :    while (png_ptr->buffer_size)
      45             :    {
      46         331 :       png_process_some_data(png_ptr, info_ptr);
      47             :    }
      48             : }
      49             : 
      50             : png_size_t PNGAPI
      51          65 : png_process_data_pause(png_structrp png_ptr, int save)
      52             : {
      53          65 :    if (png_ptr != NULL)
      54             :    {
      55             :       /* It's easiest for the caller if we do the save; then the caller doesn't
      56             :        * have to supply the same data again:
      57             :        */
      58          65 :       if (save != 0)
      59           0 :          png_push_save_buffer(png_ptr);
      60             :       else
      61             :       {
      62             :          /* This includes any pending saved bytes: */
      63          65 :          png_size_t remaining = png_ptr->buffer_size;
      64          65 :          png_ptr->buffer_size = 0;
      65             : 
      66             :          /* So subtract the saved buffer size, unless all the data
      67             :           * is actually 'saved', in which case we just return 0
      68             :           */
      69          65 :          if (png_ptr->save_buffer_size < remaining)
      70          52 :             return remaining - png_ptr->save_buffer_size;
      71             :       }
      72             :    }
      73             : 
      74          13 :    return 0;
      75             : }
      76             : 
      77             : png_uint_32 PNGAPI
      78           0 : png_process_data_skip(png_structrp png_ptr)
      79             : {
      80             : /* TODO: Deprecate and remove this API.
      81             :  * Somewhere the implementation of this seems to have been lost,
      82             :  * or abandoned.  It was only to support some internal back-door access
      83             :  * to png_struct) in libpng-1.4.x.
      84             :  */
      85           0 :    png_app_warning(png_ptr,
      86             : "png_process_data_skip is not implemented in any current version of libpng");
      87           0 :    return 0;
      88             : }
      89             : 
      90             : /* What we do with the incoming data depends on what we were previously
      91             :  * doing before we ran out of data...
      92             :  */
      93             : void /* PRIVATE */
      94         331 : png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
      95             : {
      96         331 :    if (png_ptr == NULL)
      97           0 :       return;
      98             : 
      99         331 :    switch (png_ptr->process_mode)
     100             :    {
     101             :       case PNG_READ_SIG_MODE:
     102             :       {
     103          31 :          png_push_read_sig(png_ptr, info_ptr);
     104          31 :          break;
     105             :       }
     106             : 
     107             :       case PNG_READ_CHUNK_MODE:
     108             :       {
     109         206 :          png_push_read_chunk(png_ptr, info_ptr);
     110         206 :          break;
     111             :       }
     112             : 
     113             :       case PNG_READ_IDAT_MODE:
     114             :       {
     115          94 :          png_push_read_IDAT(png_ptr);
     116          94 :          break;
     117             :       }
     118             : 
     119             :       default:
     120             :       {
     121           0 :          png_ptr->buffer_size = 0;
     122           0 :          break;
     123             :       }
     124             :    }
     125             : }
     126             : 
     127             : /* Read any remaining signature bytes from the stream and compare them with
     128             :  * the correct PNG signature.  It is possible that this routine is called
     129             :  * with bytes already read from the signature, either because they have been
     130             :  * checked by the calling application, or because of multiple calls to this
     131             :  * routine.
     132             :  */
     133             : void /* PRIVATE */
     134          31 : png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
     135             : {
     136          31 :    png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
     137          31 :        num_to_check = 8 - num_checked;
     138             : 
     139          31 :    if (png_ptr->buffer_size < num_to_check)
     140             :    {
     141           0 :       num_to_check = png_ptr->buffer_size;
     142             :    }
     143             : 
     144          31 :    png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
     145             :        num_to_check);
     146          31 :    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
     147             : 
     148          31 :    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
     149             :    {
     150           0 :       if (num_checked < 4 &&
     151           0 :           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
     152           0 :          png_error(png_ptr, "Not a PNG file");
     153             : 
     154             :       else
     155           0 :          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
     156             :    }
     157             :    else
     158             :    {
     159          31 :       if (png_ptr->sig_bytes >= 8)
     160             :       {
     161          31 :          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
     162             :       }
     163             :    }
     164          31 : }
     165             : 
     166             : void /* PRIVATE */
     167         206 : png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
     168             : {
     169             :    png_uint_32 chunk_name;
     170             : #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
     171             :    int keep; /* unknown handling method */
     172             : #endif
     173             : 
     174             :    /* First we make sure we have enough data for the 4-byte chunk name
     175             :     * and the 4-byte chunk length before proceeding with decoding the
     176             :     * chunk data.  To fully decode each of these chunks, we also make
     177             :     * sure we have enough data in the buffer for the 4-byte CRC at the
     178             :     * end of every chunk (except IDAT, which is handled separately).
     179             :     */
     180         206 :    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
     181             :    {
     182             :       png_byte chunk_length[4];
     183             :       png_byte chunk_tag[4];
     184             : 
     185         159 :       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
     186         159 :       png_push_fill_buffer(png_ptr, chunk_length, 4);
     187         159 :       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
     188         159 :       png_reset_crc(png_ptr);
     189         159 :       png_crc_read(png_ptr, chunk_tag, 4);
     190         159 :       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
     191         159 :       png_check_chunk_name(png_ptr, png_ptr->chunk_name);
     192         159 :       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
     193             :    }
     194             : 
     195         206 :    chunk_name = png_ptr->chunk_name;
     196             : 
     197             : #ifdef PNG_READ_APNG_SUPPORTED
     198         289 :    if (png_ptr->num_frames_read > 0 &&
     199          83 :        png_ptr->num_frames_read < info_ptr->num_frames)
     200             :    {
     201          68 :       if (chunk_name == png_IDAT)
     202             :       {
     203             :          /* Discard trailing IDATs for the first frame */
     204           0 :          if ((png_ptr->mode & PNG_HAVE_fcTL) != 0 ||
     205           0 :              png_ptr->num_frames_read > 1)
     206           0 :             png_error(png_ptr, "out of place IDAT");
     207             : 
     208           0 :          PNG_PUSH_SAVE_BUFFER_IF_FULL
     209           0 :          png_crc_finish(png_ptr, png_ptr->push_length);
     210           0 :          png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     211             :       }
     212             : 
     213          68 :       else if (chunk_name == png_fdAT)
     214             :       {
     215          34 :          PNG_PUSH_SAVE_BUFFER_IF_LT(4)
     216          34 :          png_ensure_sequence_number(png_ptr, 4);
     217             : 
     218          34 :          if ((png_ptr->mode & PNG_HAVE_fcTL) == 0)
     219             :          {
     220             :             /* Discard trailing fdATs for frames other than the first */
     221           0 :             if (png_ptr->num_frames_read < 2)
     222           0 :                png_error(png_ptr, "out of place fdAT");
     223             : 
     224           0 :             PNG_PUSH_SAVE_BUFFER_IF_FULL
     225           0 :             png_crc_finish(png_ptr, png_ptr->push_length);
     226           0 :             png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     227             :          }
     228             : 
     229             :          else
     230             :          {
     231             :             /* frame data follows */
     232          34 :             png_ptr->idat_size = png_ptr->push_length - 4;
     233          34 :             png_ptr->mode |= PNG_HAVE_IDAT;
     234          34 :             png_ptr->process_mode = PNG_READ_IDAT_MODE;
     235             :          }
     236             :       }
     237             : 
     238          34 :       else if (chunk_name == png_fcTL)
     239             :       {
     240          34 :          PNG_PUSH_SAVE_BUFFER_IF_FULL
     241          34 :          png_read_reset(png_ptr);
     242          34 :          png_ptr->mode &= ~PNG_HAVE_fcTL;
     243             : 
     244          34 :          png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
     245             : 
     246          34 :          if ((png_ptr->mode & PNG_HAVE_fcTL) == 0)
     247           0 :             png_error(png_ptr, "missing required fcTL chunk");
     248             : 
     249          34 :          png_read_reinit(png_ptr, info_ptr);
     250          34 :          png_progressive_read_reset(png_ptr);
     251             : 
     252          34 :          if (png_ptr->frame_info_fn != NULL)
     253          34 :             (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
     254             : 
     255          34 :          png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     256             :       }
     257             : 
     258           0 :       else if (chunk_name == png_IEND)
     259             :       {
     260           0 :          PNG_PUSH_SAVE_BUFFER_IF_FULL
     261           0 :          png_warning(png_ptr, "Number of actual frames fewer than expected");
     262           0 :          png_crc_finish(png_ptr, png_ptr->push_length);
     263           0 :          png_ptr->process_mode = PNG_READ_DONE_MODE;
     264           0 :          png_push_have_end(png_ptr, info_ptr);
     265             :       }
     266             : 
     267             :       else
     268             :       {
     269           0 :          PNG_PUSH_SAVE_BUFFER_IF_FULL
     270           0 :          png_warning(png_ptr, "Skipped (ignored) a chunk "
     271             :                               "between APNG chunks");
     272           0 :          png_crc_finish(png_ptr, png_ptr->push_length);
     273           0 :          png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     274             :       }
     275             : 
     276          68 :       return;
     277             :    }
     278             : #endif /* READ_APNG */
     279             : 
     280         138 :    if (chunk_name == png_IDAT)
     281             :    {
     282          31 :       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
     283           0 :          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
     284             : 
     285             :       /* If we reach an IDAT chunk, this means we have read all of the
     286             :        * header chunks, and we can start reading the image (or if this
     287             :        * is called after the image has been read - we have an error).
     288             :        */
     289          31 :       if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
     290           0 :          png_error(png_ptr, "Missing IHDR before IDAT");
     291             : 
     292          33 :       else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
     293           2 :           (png_ptr->mode & PNG_HAVE_PLTE) == 0)
     294           0 :          png_error(png_ptr, "Missing PLTE before IDAT");
     295             : 
     296          31 :       png_ptr->process_mode = PNG_READ_IDAT_MODE;
     297             : 
     298          31 :       if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
     299           0 :          if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
     300           0 :             if (png_ptr->push_length == 0)
     301           0 :                return;
     302             : 
     303          31 :       png_ptr->mode |= PNG_HAVE_IDAT;
     304             : 
     305          31 :       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
     306           0 :          png_benign_error(png_ptr, "Too many IDATs found");
     307             :    }
     308             : 
     309         138 :    if (chunk_name == png_IHDR)
     310             :    {
     311          31 :       if (png_ptr->push_length != 13)
     312           0 :          png_error(png_ptr, "Invalid IHDR length");
     313             : 
     314          31 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     315          31 :       png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
     316             :    }
     317             : 
     318         107 :    else if (chunk_name == png_IEND)
     319             :    {
     320          13 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     321          13 :       png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
     322             : 
     323          13 :       png_ptr->process_mode = PNG_READ_DONE_MODE;
     324          13 :       png_push_have_end(png_ptr, info_ptr);
     325             :    }
     326             : 
     327             : #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
     328             :    else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
     329             :    {
     330             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     331             :       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
     332             : 
     333             :       if (chunk_name == png_PLTE)
     334             :          png_ptr->mode |= PNG_HAVE_PLTE;
     335             :    }
     336             : #endif
     337             : 
     338          94 :    else if (chunk_name == png_PLTE)
     339             :    {
     340           2 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     341           2 :       png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
     342             :    }
     343             : 
     344          92 :    else if (chunk_name == png_IDAT)
     345             :    {
     346             : #ifdef PNG_READ_APNG_SUPPORTED
     347          31 :       png_have_info(png_ptr, info_ptr);
     348             : #endif
     349          31 :       png_ptr->idat_size = png_ptr->push_length;
     350          31 :       png_ptr->process_mode = PNG_READ_IDAT_MODE;
     351          31 :       png_push_have_info(png_ptr, info_ptr);
     352          31 :       png_ptr->zstream.avail_out =
     353          62 :           (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
     354          62 :           png_ptr->iwidth) + 1;
     355          31 :       png_ptr->zstream.next_out = png_ptr->row_buf;
     356          31 :       return;
     357             :    }
     358             : 
     359             : #ifdef PNG_READ_gAMA_SUPPORTED
     360          61 :    else if (png_ptr->chunk_name == png_gAMA)
     361             :    {
     362           0 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     363           0 :       png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
     364             :    }
     365             : 
     366             : #endif
     367             : #ifdef PNG_READ_sBIT_SUPPORTED
     368             :    else if (png_ptr->chunk_name == png_sBIT)
     369             :    {
     370             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     371             :       png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
     372             :    }
     373             : 
     374             : #endif
     375             : #ifdef PNG_READ_cHRM_SUPPORTED
     376          61 :    else if (png_ptr->chunk_name == png_cHRM)
     377             :    {
     378           0 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     379           0 :       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
     380             :    }
     381             : 
     382             : #endif
     383             : #ifdef PNG_READ_sRGB_SUPPORTED
     384          61 :    else if (chunk_name == png_sRGB)
     385             :    {
     386           8 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     387           8 :       png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
     388             :    }
     389             : 
     390             : #endif
     391             : #ifdef PNG_READ_iCCP_SUPPORTED
     392          53 :    else if (png_ptr->chunk_name == png_iCCP)
     393             :    {
     394           0 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     395           0 :       png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
     396             :    }
     397             : 
     398             : #endif
     399             : #ifdef PNG_READ_sPLT_SUPPORTED
     400             :    else if (chunk_name == png_sPLT)
     401             :    {
     402             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     403             :       png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
     404             :    }
     405             : 
     406             : #endif
     407             : #ifdef PNG_READ_tRNS_SUPPORTED
     408          53 :    else if (chunk_name == png_tRNS)
     409             :    {
     410           2 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     411           2 :       png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
     412             :    }
     413             : 
     414             : #endif
     415             : #ifdef PNG_READ_bKGD_SUPPORTED
     416             :    else if (chunk_name == png_bKGD)
     417             :    {
     418             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     419             :       png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
     420             :    }
     421             : 
     422             : #endif
     423             : #ifdef PNG_READ_hIST_SUPPORTED
     424             :    else if (chunk_name == png_hIST)
     425             :    {
     426             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     427             :       png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
     428             :    }
     429             : 
     430             : #endif
     431             : #ifdef PNG_READ_pHYs_SUPPORTED
     432             :    else if (chunk_name == png_pHYs)
     433             :    {
     434             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     435             :       png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
     436             :    }
     437             : 
     438             : #endif
     439             : #ifdef PNG_READ_oFFs_SUPPORTED
     440             :    else if (chunk_name == png_oFFs)
     441             :    {
     442             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     443             :       png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
     444             :    }
     445             : #endif
     446             : 
     447             : #ifdef PNG_READ_pCAL_SUPPORTED
     448             :    else if (chunk_name == png_pCAL)
     449             :    {
     450             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     451             :       png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
     452             :    }
     453             : 
     454             : #endif
     455             : #ifdef PNG_READ_sCAL_SUPPORTED
     456             :    else if (chunk_name == png_sCAL)
     457             :    {
     458             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     459             :       png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
     460             :    }
     461             : 
     462             : #endif
     463             : #ifdef PNG_READ_tIME_SUPPORTED
     464             :    else if (chunk_name == png_tIME)
     465             :    {
     466             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     467             :       png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
     468             :    }
     469             : 
     470             : #endif
     471             : #ifdef PNG_READ_tEXt_SUPPORTED
     472             :    else if (chunk_name == png_tEXt)
     473             :    {
     474             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     475             :       png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
     476             :    }
     477             : 
     478             : #endif
     479             : #ifdef PNG_READ_zTXt_SUPPORTED
     480             :    else if (chunk_name == png_zTXt)
     481             :    {
     482             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     483             :       png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
     484             :    }
     485             : 
     486             : #endif
     487             : #ifdef PNG_READ_iTXt_SUPPORTED
     488             :    else if (chunk_name == png_iTXt)
     489             :    {
     490             :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     491             :       png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
     492             :    }
     493             : #endif
     494             : 
     495             : #ifdef PNG_READ_APNG_SUPPORTED
     496          51 :    else if (chunk_name == png_acTL)
     497             :    {
     498           4 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     499           4 :       png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
     500             :    }
     501             : 
     502          47 :    else if (chunk_name == png_fcTL)
     503             :    {
     504           4 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     505           4 :       png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
     506             :    }
     507             : 
     508             : #endif /* READ_APNG */
     509             :    else
     510             :    {
     511          43 :       PNG_PUSH_SAVE_BUFFER_IF_FULL
     512          43 :       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
     513             :           PNG_HANDLE_CHUNK_AS_DEFAULT);
     514             :    }
     515             : 
     516         107 :    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     517             : }
     518             : 
     519             : void PNGCBAPI
     520         939 : png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
     521             : {
     522             :    png_bytep ptr;
     523             : 
     524         939 :    if (png_ptr == NULL)
     525           0 :       return;
     526             : 
     527         939 :    ptr = buffer;
     528         939 :    if (png_ptr->save_buffer_size != 0)
     529             :    {
     530             :       png_size_t save_size;
     531             : 
     532           0 :       if (length < png_ptr->save_buffer_size)
     533           0 :          save_size = length;
     534             : 
     535             :       else
     536           0 :          save_size = png_ptr->save_buffer_size;
     537             : 
     538           0 :       memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
     539           0 :       length -= save_size;
     540           0 :       ptr += save_size;
     541           0 :       png_ptr->buffer_size -= save_size;
     542           0 :       png_ptr->save_buffer_size -= save_size;
     543           0 :       png_ptr->save_buffer_ptr += save_size;
     544             :    }
     545         939 :    if (length != 0 && png_ptr->current_buffer_size != 0)
     546             :    {
     547             :       png_size_t save_size;
     548             : 
     549         939 :       if (length < png_ptr->current_buffer_size)
     550         926 :          save_size = length;
     551             : 
     552             :       else
     553          13 :          save_size = png_ptr->current_buffer_size;
     554             : 
     555         939 :       memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
     556         939 :       png_ptr->buffer_size -= save_size;
     557         939 :       png_ptr->current_buffer_size -= save_size;
     558         939 :       png_ptr->current_buffer_ptr += save_size;
     559             :    }
     560             : }
     561             : 
     562             : void /* PRIVATE */
     563           0 : png_push_save_buffer(png_structrp png_ptr)
     564             : {
     565           0 :    if (png_ptr->save_buffer_size != 0)
     566             :    {
     567           0 :       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
     568             :       {
     569             :          png_size_t i, istop;
     570             :          png_bytep sp;
     571             :          png_bytep dp;
     572             : 
     573           0 :          istop = png_ptr->save_buffer_size;
     574           0 :          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
     575           0 :              i < istop; i++, sp++, dp++)
     576             :          {
     577           0 :             *dp = *sp;
     578             :          }
     579             :       }
     580             :    }
     581           0 :    if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
     582           0 :        png_ptr->save_buffer_max)
     583             :    {
     584             :       png_size_t new_max;
     585             :       png_bytep old_buffer;
     586             : 
     587           0 :       if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
     588           0 :           (png_ptr->current_buffer_size + 256))
     589             :       {
     590           0 :          png_error(png_ptr, "Potential overflow of save_buffer");
     591             :       }
     592             : 
     593           0 :       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
     594           0 :       old_buffer = png_ptr->save_buffer;
     595           0 :       png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
     596             :           (png_size_t)new_max);
     597             : 
     598           0 :       if (png_ptr->save_buffer == NULL)
     599             :       {
     600           0 :          png_free(png_ptr, old_buffer);
     601           0 :          png_error(png_ptr, "Insufficient memory for save_buffer");
     602             :       }
     603             : 
     604           0 :       if (old_buffer)
     605           0 :          memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
     606           0 :       else if (png_ptr->save_buffer_size)
     607           0 :          png_error(png_ptr, "save_buffer error");
     608           0 :       png_free(png_ptr, old_buffer);
     609           0 :       png_ptr->save_buffer_max = new_max;
     610             :    }
     611           0 :    if (png_ptr->current_buffer_size)
     612             :    {
     613           0 :       memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
     614           0 :          png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
     615           0 :       png_ptr->save_buffer_size += png_ptr->current_buffer_size;
     616           0 :       png_ptr->current_buffer_size = 0;
     617             :    }
     618           0 :    png_ptr->save_buffer_ptr = png_ptr->save_buffer;
     619           0 :    png_ptr->buffer_size = 0;
     620           0 : }
     621             : 
     622             : void /* PRIVATE */
     623          65 : png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
     624             :     png_size_t buffer_length)
     625             : {
     626          65 :    png_ptr->current_buffer = buffer;
     627          65 :    png_ptr->current_buffer_size = buffer_length;
     628          65 :    png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
     629          65 :    png_ptr->current_buffer_ptr = png_ptr->current_buffer;
     630          65 : }
     631             : 
     632             : void /* PRIVATE */
     633          94 : png_push_read_IDAT(png_structrp png_ptr)
     634             : {
     635          94 :    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
     636             :    {
     637             :       png_byte chunk_length[4];
     638             :       png_byte chunk_tag[4];
     639             : 
     640             :       /* TODO: this code can be commoned up with the same code in push_read */
     641             : #ifdef PNG_READ_APNG_SUPPORTED
     642          94 :       PNG_PUSH_SAVE_BUFFER_IF_LT(12)
     643             : #else
     644             :       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
     645             : #endif
     646          47 :       png_push_fill_buffer(png_ptr, chunk_length, 4);
     647          47 :       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
     648          47 :       png_reset_crc(png_ptr);
     649          47 :       png_crc_read(png_ptr, chunk_tag, 4);
     650          47 :       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
     651          47 :       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
     652             : 
     653             : #ifdef PNG_READ_APNG_SUPPORTED
     654          47 :       if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
     655             :       {
     656          34 :           if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) != 0)
     657             :           {
     658          34 :               png_ptr->process_mode = PNG_READ_CHUNK_MODE;
     659          34 :               if (png_ptr->frame_end_fn != NULL)
     660           0 :                  (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
     661          34 :               png_ptr->num_frames_read++;
     662          34 :               return;
     663             :           }
     664             :           else
     665             :           {
     666           0 :               if (png_ptr->chunk_name == png_IEND)
     667           0 :                   png_error(png_ptr, "Not enough image data");
     668           0 :               PNG_PUSH_SAVE_BUFFER_IF_FULL
     669           0 :               png_warning(png_ptr, "Skipping (ignoring) a chunk between "
     670             :                                    "APNG chunks");
     671           0 :               png_crc_finish(png_ptr, png_ptr->push_length);
     672           0 :               png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     673           0 :               return;
     674             :           }
     675             :       }
     676             :       else
     677             : #endif
     678             : #ifdef PNG_READ_APNG_SUPPORTED
     679          13 :       if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
     680             : #else
     681             :       if (png_ptr->chunk_name != png_IDAT)
     682             : #endif
     683             :       {
     684          13 :          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
     685             : 
     686          13 :          if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
     687           0 :             png_error(png_ptr, "Not enough compressed data");
     688             : 
     689             : #ifdef PNG_READ_APNG_SUPPORTED
     690          13 :          if (png_ptr->frame_end_fn != NULL)
     691           0 :             (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
     692          13 :          png_ptr->num_frames_read++;
     693             : #endif
     694             : 
     695          13 :          return;
     696             :       }
     697             : 
     698           0 :       png_ptr->idat_size = png_ptr->push_length;
     699             : 
     700             : #ifdef PNG_READ_APNG_SUPPORTED
     701           0 :       if (png_ptr->num_frames_read > 0)
     702             :       {
     703           0 :          png_ensure_sequence_number(png_ptr, 4);
     704           0 :          png_ptr->idat_size -= 4;
     705             :       }
     706             : #endif
     707             :    }
     708             : 
     709          47 :    if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
     710             :    {
     711           0 :       png_size_t save_size = png_ptr->save_buffer_size;
     712           0 :       png_uint_32 idat_size = png_ptr->idat_size;
     713             : 
     714             :       /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
     715             :        * are of different types and we don't know which variable has the fewest
     716             :        * bits.  Carefully select the smaller and cast it to the type of the
     717             :        * larger - this cannot overflow.  Do not cast in the following test - it
     718             :        * will break on either 16-bit or 64-bit platforms.
     719             :        */
     720           0 :       if (idat_size < save_size)
     721           0 :          save_size = (png_size_t)idat_size;
     722             : 
     723             :       else
     724           0 :          idat_size = (png_uint_32)save_size;
     725             : 
     726           0 :       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
     727             : 
     728           0 :       png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
     729             : 
     730           0 :       png_ptr->idat_size -= idat_size;
     731           0 :       png_ptr->buffer_size -= save_size;
     732           0 :       png_ptr->save_buffer_size -= save_size;
     733           0 :       png_ptr->save_buffer_ptr += save_size;
     734             :    }
     735             : 
     736          47 :    if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
     737             :    {
     738          47 :       png_size_t save_size = png_ptr->current_buffer_size;
     739          47 :       png_uint_32 idat_size = png_ptr->idat_size;
     740             : 
     741             :       /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
     742             :        * are of different types and we don't know which variable has the fewest
     743             :        * bits.  Carefully select the smaller and cast it to the type of the
     744             :        * larger - this cannot overflow.
     745             :        */
     746          47 :       if (idat_size < save_size)
     747          47 :          save_size = (png_size_t)idat_size;
     748             : 
     749             :       else
     750           0 :          idat_size = (png_uint_32)save_size;
     751             : 
     752          47 :       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
     753             : 
     754          47 :       png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
     755             : 
     756          47 :       png_ptr->idat_size -= idat_size;
     757          47 :       png_ptr->buffer_size -= save_size;
     758          47 :       png_ptr->current_buffer_size -= save_size;
     759          47 :       png_ptr->current_buffer_ptr += save_size;
     760             :    }
     761             : 
     762          47 :    if (png_ptr->idat_size == 0)
     763             :    {
     764          47 :       PNG_PUSH_SAVE_BUFFER_IF_LT(4)
     765          47 :       png_crc_finish(png_ptr, 0);
     766          47 :       png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
     767          47 :       png_ptr->mode |= PNG_AFTER_IDAT;
     768          47 :       png_ptr->zowner = 0;
     769             :    }
     770             : }
     771             : 
     772             : void /* PRIVATE */
     773          47 : png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
     774             :     png_size_t buffer_length)
     775             : {
     776             :    /* The caller checks for a non-zero buffer length. */
     777          47 :    if (!(buffer_length > 0) || buffer == NULL)
     778           0 :       png_error(png_ptr, "No IDAT data (internal error)");
     779             : 
     780             : #ifdef PNG_READ_APNG_SUPPORTED
     781             :    /* If the app is not APNG-aware, decode only the first frame */
     782          58 :    if ((png_ptr->apng_flags & PNG_APNG_APP) == 0 &&
     783          11 :       png_ptr->num_frames_read > 0)
     784             :    {
     785           0 :       png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
     786           0 :       return;
     787             :    }
     788             : #endif
     789             : 
     790             :    /* This routine must process all the data it has been given
     791             :     * before returning, calling the row callback as required to
     792             :     * handle the uncompressed results.
     793             :     */
     794          47 :    png_ptr->zstream.next_in = buffer;
     795             :    /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
     796          47 :    png_ptr->zstream.avail_in = (uInt)buffer_length;
     797             : 
     798             :    /* Keep going until the decompressed data is all processed
     799             :     * or the stream marked as finished.
     800             :     */
     801        3172 :    while (png_ptr->zstream.avail_in > 0 &&
     802        1539 :       (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
     803             :    {
     804             :       int ret;
     805             : 
     806             :       /* We have data for zlib, but we must check that zlib
     807             :        * has someplace to put the results.  It doesn't matter
     808             :        * if we don't expect any results -- it may be the input
     809             :        * data is just the LZ end code.
     810             :        */
     811        1539 :       if (!(png_ptr->zstream.avail_out > 0))
     812             :       {
     813             :          /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
     814        1492 :          png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
     815           0 :              png_ptr->iwidth) + 1);
     816             : 
     817        1492 :          png_ptr->zstream.next_out = png_ptr->row_buf;
     818             :       }
     819             : 
     820             :       /* Using Z_SYNC_FLUSH here means that an unterminated
     821             :        * LZ stream (a stream with a missing end code) can still
     822             :        * be handled, otherwise (Z_NO_FLUSH) a future zlib
     823             :        * implementation might defer output and therefore
     824             :        * change the current behavior (see comments in inflate.c
     825             :        * for why this doesn't happen at present with zlib 1.2.5).
     826             :        */
     827        1539 :       ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
     828             : 
     829             :       /* Check for any failure before proceeding. */
     830        1539 :       if (ret != Z_OK && ret != Z_STREAM_END)
     831             :       {
     832             :          /* Terminate the decompression. */
     833           0 :          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
     834           0 :          png_ptr->zowner = 0;
     835             : 
     836             :          /* This may be a truncated stream (missing or
     837             :           * damaged end code).  Treat that as a warning.
     838             :           */
     839           0 :          if (png_ptr->row_number >= png_ptr->num_rows ||
     840           0 :              png_ptr->pass > 6)
     841           0 :             png_warning(png_ptr, "Truncated compressed data in IDAT");
     842             : 
     843             :          else
     844             :          {
     845           0 :             if (ret == Z_DATA_ERROR)
     846           0 :                png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
     847             :             else
     848           0 :                png_error(png_ptr, "Decompression error in IDAT");
     849             :          }
     850             : 
     851             :          /* Skip the check on unprocessed input */
     852           0 :          return;
     853             :       }
     854             : 
     855             :       /* Did inflate output any data? */
     856        1539 :       if (png_ptr->zstream.next_out != png_ptr->row_buf)
     857             :       {
     858             :          /* Is this unexpected data after the last row?
     859             :           * If it is, artificially terminate the LZ output
     860             :           * here.
     861             :           */
     862        3078 :          if (png_ptr->row_number >= png_ptr->num_rows ||
     863        1539 :              png_ptr->pass > 6)
     864             :          {
     865             :             /* Extra data. */
     866           0 :             png_warning(png_ptr, "Extra compressed data in IDAT");
     867           0 :             png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
     868           0 :             png_ptr->zowner = 0;
     869             : 
     870             :             /* Do no more processing; skip the unprocessed
     871             :              * input check below.
     872             :              */
     873           0 :             return;
     874             :          }
     875             : 
     876             :          /* Do we have a complete row? */
     877        1539 :          if (png_ptr->zstream.avail_out == 0)
     878        1539 :             png_push_process_row(png_ptr);
     879             :       }
     880             : 
     881             :       /* And check for the end of the stream. */
     882        1539 :       if (ret == Z_STREAM_END)
     883          47 :          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
     884             :    }
     885             : 
     886             :    /* All the data should have been processed, if anything
     887             :     * is left at this point we have bytes of IDAT data
     888             :     * after the zlib end code.
     889             :     */
     890          47 :    if (png_ptr->zstream.avail_in > 0)
     891           0 :       png_warning(png_ptr, "Extra compression data in IDAT");
     892             : }
     893             : 
     894             : void /* PRIVATE */
     895        1539 : png_push_process_row(png_structrp png_ptr)
     896             : {
     897             :    /* 1.5.6: row_info moved out of png_struct to a local here. */
     898             :    png_row_info row_info;
     899             : 
     900        1539 :    row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
     901        1539 :    row_info.color_type = png_ptr->color_type;
     902        1539 :    row_info.bit_depth = png_ptr->bit_depth;
     903        1539 :    row_info.channels = png_ptr->channels;
     904        1539 :    row_info.pixel_depth = png_ptr->pixel_depth;
     905        1539 :    row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
     906             : 
     907        1539 :    if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
     908             :    {
     909        1219 :       if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
     910        2438 :          png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
     911        2438 :             png_ptr->prev_row + 1, png_ptr->row_buf[0]);
     912             :       else
     913           0 :          png_error(png_ptr, "bad adaptive filter value");
     914             :    }
     915             : 
     916             :    /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
     917             :     * 1.5.6, while the buffer really is this big in current versions of libpng
     918             :     * it may not be in the future, so this was changed just to copy the
     919             :     * interlaced row count:
     920             :     */
     921        1538 :    memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
     922             : 
     923             : #ifdef PNG_READ_TRANSFORMS_SUPPORTED
     924        1538 :    if (png_ptr->transformations != 0)
     925        1538 :       png_do_read_transformations(png_ptr, &row_info);
     926             : #endif
     927             : 
     928             :    /* The transformed pixel depth should match the depth now in row_info. */
     929        1539 :    if (png_ptr->transformed_pixel_depth == 0)
     930             :    {
     931          13 :       png_ptr->transformed_pixel_depth = row_info.pixel_depth;
     932          13 :       if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
     933           0 :          png_error(png_ptr, "progressive row overflow");
     934             :    }
     935             : 
     936        1526 :    else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
     937           0 :       png_error(png_ptr, "internal progressive row size calculation error");
     938             : 
     939             : 
     940             : #ifdef PNG_READ_INTERLACING_SUPPORTED
     941             :    /* Expand interlaced rows to full size */
     942        1539 :    if (png_ptr->interlaced != 0 &&
     943           0 :        (png_ptr->transformations & PNG_INTERLACE) != 0)
     944             :    {
     945           0 :       if (png_ptr->pass < 6)
     946           0 :          png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
     947             :              png_ptr->transformations);
     948             : 
     949           0 :       switch (png_ptr->pass)
     950             :       {
     951             :          case 0:
     952             :          {
     953             :             int i;
     954           0 :             for (i = 0; i < 8 && png_ptr->pass == 0; i++)
     955             :             {
     956           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
     957           0 :                png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
     958             :             }
     959             : 
     960           0 :             if (png_ptr->pass == 2) /* Pass 1 might be empty */
     961             :             {
     962           0 :                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
     963             :                {
     964           0 :                   png_push_have_row(png_ptr, NULL);
     965           0 :                   png_read_push_finish_row(png_ptr);
     966             :                }
     967             :             }
     968             : 
     969           0 :             if (png_ptr->pass == 4 && png_ptr->height <= 4)
     970             :             {
     971           0 :                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
     972             :                {
     973           0 :                   png_push_have_row(png_ptr, NULL);
     974           0 :                   png_read_push_finish_row(png_ptr);
     975             :                }
     976             :             }
     977             : 
     978           0 :             if (png_ptr->pass == 6 && png_ptr->height <= 4)
     979             :             {
     980           0 :                 png_push_have_row(png_ptr, NULL);
     981           0 :                 png_read_push_finish_row(png_ptr);
     982             :             }
     983             : 
     984           0 :             break;
     985             :          }
     986             : 
     987             :          case 1:
     988             :          {
     989             :             int i;
     990           0 :             for (i = 0; i < 8 && png_ptr->pass == 1; i++)
     991             :             {
     992           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
     993           0 :                png_read_push_finish_row(png_ptr);
     994             :             }
     995             : 
     996           0 :             if (png_ptr->pass == 2) /* Skip top 4 generated rows */
     997             :             {
     998           0 :                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
     999             :                {
    1000           0 :                   png_push_have_row(png_ptr, NULL);
    1001           0 :                   png_read_push_finish_row(png_ptr);
    1002             :                }
    1003             :             }
    1004             : 
    1005           0 :             break;
    1006             :          }
    1007             : 
    1008             :          case 2:
    1009             :          {
    1010             :             int i;
    1011             : 
    1012           0 :             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
    1013             :             {
    1014           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1015           0 :                png_read_push_finish_row(png_ptr);
    1016             :             }
    1017             : 
    1018           0 :             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
    1019             :             {
    1020           0 :                png_push_have_row(png_ptr, NULL);
    1021           0 :                png_read_push_finish_row(png_ptr);
    1022             :             }
    1023             : 
    1024           0 :             if (png_ptr->pass == 4) /* Pass 3 might be empty */
    1025             :             {
    1026           0 :                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
    1027             :                {
    1028           0 :                   png_push_have_row(png_ptr, NULL);
    1029           0 :                   png_read_push_finish_row(png_ptr);
    1030             :                }
    1031             :             }
    1032             : 
    1033           0 :             break;
    1034             :          }
    1035             : 
    1036             :          case 3:
    1037             :          {
    1038             :             int i;
    1039             : 
    1040           0 :             for (i = 0; i < 4 && png_ptr->pass == 3; i++)
    1041             :             {
    1042           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1043           0 :                png_read_push_finish_row(png_ptr);
    1044             :             }
    1045             : 
    1046           0 :             if (png_ptr->pass == 4) /* Skip top two generated rows */
    1047             :             {
    1048           0 :                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
    1049             :                {
    1050           0 :                   png_push_have_row(png_ptr, NULL);
    1051           0 :                   png_read_push_finish_row(png_ptr);
    1052             :                }
    1053             :             }
    1054             : 
    1055           0 :             break;
    1056             :          }
    1057             : 
    1058             :          case 4:
    1059             :          {
    1060             :             int i;
    1061             : 
    1062           0 :             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
    1063             :             {
    1064           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1065           0 :                png_read_push_finish_row(png_ptr);
    1066             :             }
    1067             : 
    1068           0 :             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
    1069             :             {
    1070           0 :                png_push_have_row(png_ptr, NULL);
    1071           0 :                png_read_push_finish_row(png_ptr);
    1072             :             }
    1073             : 
    1074           0 :             if (png_ptr->pass == 6) /* Pass 5 might be empty */
    1075             :             {
    1076           0 :                png_push_have_row(png_ptr, NULL);
    1077           0 :                png_read_push_finish_row(png_ptr);
    1078             :             }
    1079             : 
    1080           0 :             break;
    1081             :          }
    1082             : 
    1083             :          case 5:
    1084             :          {
    1085             :             int i;
    1086             : 
    1087           0 :             for (i = 0; i < 2 && png_ptr->pass == 5; i++)
    1088             :             {
    1089           0 :                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1090           0 :                png_read_push_finish_row(png_ptr);
    1091             :             }
    1092             : 
    1093           0 :             if (png_ptr->pass == 6) /* Skip top generated row */
    1094             :             {
    1095           0 :                png_push_have_row(png_ptr, NULL);
    1096           0 :                png_read_push_finish_row(png_ptr);
    1097             :             }
    1098             : 
    1099           0 :             break;
    1100             :          }
    1101             : 
    1102             :          default:
    1103             :          case 6:
    1104             :          {
    1105           0 :             png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1106           0 :             png_read_push_finish_row(png_ptr);
    1107             : 
    1108           0 :             if (png_ptr->pass != 6)
    1109           0 :                break;
    1110             : 
    1111           0 :             png_push_have_row(png_ptr, NULL);
    1112           0 :             png_read_push_finish_row(png_ptr);
    1113             :          }
    1114             :       }
    1115           0 :    }
    1116             :    else
    1117             : #endif
    1118             :    {
    1119        1539 :       png_push_have_row(png_ptr, png_ptr->row_buf + 1);
    1120        1539 :       png_read_push_finish_row(png_ptr);
    1121             :    }
    1122        1539 : }
    1123             : 
    1124             : void /* PRIVATE */
    1125        1539 : png_read_push_finish_row(png_structrp png_ptr)
    1126             : {
    1127             : #ifdef PNG_READ_INTERLACING_SUPPORTED
    1128             :    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
    1129             : 
    1130             :    /* Start of interlace block */
    1131             :    static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
    1132             : 
    1133             :    /* Offset to next interlace block */
    1134             :    static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
    1135             : 
    1136             :    /* Start of interlace block in the y direction */
    1137             :    static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
    1138             : 
    1139             :    /* Offset to next interlace block in the y direction */
    1140             :    static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
    1141             : 
    1142             :    /* Height of interlace block.  This is not currently used - if you need
    1143             :     * it, uncomment it here and in png.h
    1144             :    static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
    1145             :    */
    1146             : #endif
    1147             : 
    1148        1539 :    png_ptr->row_number++;
    1149        1539 :    if (png_ptr->row_number < png_ptr->num_rows)
    1150        1492 :       return;
    1151             : 
    1152             : #ifdef PNG_READ_INTERLACING_SUPPORTED
    1153          47 :    if (png_ptr->interlaced != 0)
    1154             :    {
    1155           0 :       png_ptr->row_number = 0;
    1156           0 :       memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
    1157             : 
    1158             :       do
    1159             :       {
    1160           0 :          png_ptr->pass++;
    1161           0 :          if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
    1162           0 :              (png_ptr->pass == 3 && png_ptr->width < 3) ||
    1163           0 :              (png_ptr->pass == 5 && png_ptr->width < 2))
    1164           0 :             png_ptr->pass++;
    1165             : 
    1166           0 :          if (png_ptr->pass > 7)
    1167           0 :             png_ptr->pass--;
    1168             : 
    1169           0 :          if (png_ptr->pass >= 7)
    1170           0 :             break;
    1171             : 
    1172           0 :          png_ptr->iwidth = (png_ptr->width +
    1173           0 :              png_pass_inc[png_ptr->pass] - 1 -
    1174           0 :              png_pass_start[png_ptr->pass]) /
    1175           0 :              png_pass_inc[png_ptr->pass];
    1176             : 
    1177           0 :          if ((png_ptr->transformations & PNG_INTERLACE) != 0)
    1178           0 :             break;
    1179             : 
    1180           0 :          png_ptr->num_rows = (png_ptr->height +
    1181           0 :              png_pass_yinc[png_ptr->pass] - 1 -
    1182           0 :              png_pass_ystart[png_ptr->pass]) /
    1183           0 :              png_pass_yinc[png_ptr->pass];
    1184             : 
    1185           0 :       } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
    1186             :    }
    1187             : #endif /* READ_INTERLACING */
    1188             : }
    1189             : 
    1190             : void /* PRIVATE */
    1191          31 : png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
    1192             : {
    1193          31 :    if (png_ptr->info_fn != NULL)
    1194          31 :       (*(png_ptr->info_fn))(png_ptr, info_ptr);
    1195          31 : }
    1196             : 
    1197             : void /* PRIVATE */
    1198          13 : png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
    1199             : {
    1200          13 :    if (png_ptr->end_fn != NULL)
    1201          13 :       (*(png_ptr->end_fn))(png_ptr, info_ptr);
    1202          13 : }
    1203             : 
    1204             : void /* PRIVATE */
    1205        1539 : png_push_have_row(png_structrp png_ptr, png_bytep row)
    1206             : {
    1207        1539 :    if (png_ptr->row_fn != NULL)
    1208        3078 :       (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
    1209        1539 :           (int)png_ptr->pass);
    1210        1539 : }
    1211             : 
    1212             : #ifdef PNG_READ_INTERLACING_SUPPORTED
    1213             : void PNGAPI
    1214           0 : png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
    1215             :     png_const_bytep new_row)
    1216             : {
    1217           0 :    if (png_ptr == NULL)
    1218           0 :       return;
    1219             : 
    1220             :    /* new_row is a flag here - if it is NULL then the app callback was called
    1221             :     * from an empty row (see the calls to png_struct::row_fn below), otherwise
    1222             :     * it must be png_ptr->row_buf+1
    1223             :     */
    1224           0 :    if (new_row != NULL)
    1225           0 :       png_combine_row(png_ptr, old_row, 1/*blocky display*/);
    1226             : }
    1227             : #endif /* READ_INTERLACING */
    1228             : 
    1229             : void PNGAPI
    1230          31 : png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
    1231             :     png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
    1232             :     png_progressive_end_ptr end_fn)
    1233             : {
    1234          31 :    if (png_ptr == NULL)
    1235           0 :       return;
    1236             : 
    1237          31 :    png_ptr->info_fn = info_fn;
    1238          31 :    png_ptr->row_fn = row_fn;
    1239          31 :    png_ptr->end_fn = end_fn;
    1240             : 
    1241          31 :    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
    1242             : }
    1243             : 
    1244             : #ifdef PNG_READ_APNG_SUPPORTED
    1245             : void PNGAPI
    1246           2 : png_set_progressive_frame_fn(png_structp png_ptr,
    1247             :    png_progressive_frame_ptr frame_info_fn,
    1248             :    png_progressive_frame_ptr frame_end_fn)
    1249             : {
    1250           2 :    png_ptr->frame_info_fn = frame_info_fn;
    1251           2 :    png_ptr->frame_end_fn = frame_end_fn;
    1252           2 :    png_ptr->apng_flags |= PNG_APNG_APP;
    1253           2 : }
    1254             : #endif
    1255             : 
    1256             : png_voidp PNGAPI
    1257        1617 : png_get_progressive_ptr(png_const_structrp png_ptr)
    1258             : {
    1259        1617 :    if (png_ptr == NULL)
    1260           0 :       return (NULL);
    1261             : 
    1262        1617 :    return png_ptr->io_ptr;
    1263             : }
    1264             : #endif /* PROGRESSIVE_READ */

Generated by: LCOV version 1.13