mirror of
				https://git.code.sf.net/p/libpng/code.git
				synced 2025-07-10 18:04:09 +02:00 
			
		
		
		
	[master] Revised png_decompress_chunk() to improve speed and memory
usage when decoding large chunks.
This commit is contained in:
		
							parent
							
								
									610e7b5bd6
								
							
						
					
					
						commit
						1a86bd2a09
					
				
							
								
								
									
										7
									
								
								pngget.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								pngget.c
									
									
									
									
									
								
							@ -895,14 +895,15 @@ png_get_user_height_max (png_structp png_ptr)
 | 
				
			|||||||
png_uint_32 PNGAPI
 | 
					png_uint_32 PNGAPI
 | 
				
			||||||
png_get_chunk_cache_max (png_structp png_ptr)
 | 
					png_get_chunk_cache_max (png_structp png_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return (png_ptr? (png_ptr->user_chunk_cache_max? 0x7fffffffL :
 | 
					    return (png_ptr? (png_ptr->user_chunk_cache_max?
 | 
				
			||||||
       png_ptr->user_chunk_cache_max - 1) : 0);
 | 
					       png_ptr->user_chunk_cache_max - 1 : 0x7fffffffL) : 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* This function was added to libpng 1.4.1 */
 | 
					/* This function was added to libpng 1.4.1 */
 | 
				
			||||||
png_uint_32 PNGAPI
 | 
					png_uint_32 PNGAPI
 | 
				
			||||||
png_get_chunk_malloc_max (png_structp png_ptr)
 | 
					png_get_chunk_malloc_max (png_structp png_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return (png_ptr? png_ptr->user_chunk_cache_max : 0);
 | 
					    return (png_ptr? (png_ptr->user_chunk_malloc_max?
 | 
				
			||||||
 | 
					       png_ptr->user_chunk_malloc_max : 0x7fffffffL) : 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
 | 
					#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,7 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 | 
				
			|||||||
   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
 | 
					   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
 | 
				
			||||||
   /* Added at libpng-1.4.0 */
 | 
					   /* Added at libpng-1.4.0 */
 | 
				
			||||||
   png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
 | 
					   png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
 | 
				
			||||||
 | 
					   png_ptr->user_chunk_malloc_max = png_get_chunk_malloc_max(png_ptr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef PNG_SETJMP_SUPPORTED
 | 
					#ifdef PNG_SETJMP_SUPPORTED
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										78
									
								
								pngrutil.c
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								pngrutil.c
									
									
									
									
									
								
							@ -210,8 +210,8 @@ png_crc_error(png_structp png_ptr)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void /* PRIVATE */
 | 
					void /* PRIVATE */
 | 
				
			||||||
png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
					png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
				
			||||||
                              png_size_t chunklength,
 | 
					    png_size_t chunklength,
 | 
				
			||||||
                              png_size_t prefix_size, png_size_t *newlength)
 | 
					    png_size_t prefix_size, png_size_t *newlength)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
   static PNG_CONST char msg[] = "Error decoding compressed chunk";
 | 
					   static PNG_CONST char msg[] = "Error decoding compressed chunk";
 | 
				
			||||||
   png_charp text;
 | 
					   png_charp text;
 | 
				
			||||||
@ -248,12 +248,12 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
				
			|||||||
               text_size = prefix_size + png_sizeof(msg) + 1;
 | 
					               text_size = prefix_size + png_sizeof(msg) + 1;
 | 
				
			||||||
               text = (png_charp)png_malloc_warn(png_ptr, text_size);
 | 
					               text = (png_charp)png_malloc_warn(png_ptr, text_size);
 | 
				
			||||||
               if (text ==  NULL)
 | 
					               if (text ==  NULL)
 | 
				
			||||||
                 {
 | 
					               {
 | 
				
			||||||
                    png_error(png_ptr,
 | 
					                  png_error(png_ptr,
 | 
				
			||||||
                       "Not enough memory to decompress chunk");
 | 
					                     "Not enough memory to decompress chunk");
 | 
				
			||||||
                    text_size = 0;
 | 
					                  text_size = 0;
 | 
				
			||||||
                    break;
 | 
					                  break;
 | 
				
			||||||
                 }
 | 
					               }
 | 
				
			||||||
               png_memcpy(text, png_ptr->chunkdata, prefix_size);
 | 
					               png_memcpy(text, png_ptr->chunkdata, prefix_size);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -261,9 +261,11 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            /* Copy what we can of the error message into the text chunk */
 | 
					            /* Copy what we can of the error message into the text chunk */
 | 
				
			||||||
            text_size = (png_size_t)(chunklength -
 | 
					            text_size = (png_size_t)(chunklength -
 | 
				
			||||||
              (text - png_ptr->chunkdata) - 1);
 | 
					                (text - png_ptr->chunkdata) - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (text_size > png_sizeof(msg))
 | 
					            if (text_size > png_sizeof(msg))
 | 
				
			||||||
               text_size = png_sizeof(msg);
 | 
					               text_size = png_sizeof(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            png_memcpy(text + prefix_size, msg, text_size);
 | 
					            png_memcpy(text + prefix_size, msg, text_size);
 | 
				
			||||||
            buffer_size = text_size;
 | 
					            buffer_size = text_size;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -283,9 +285,9 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
				
			|||||||
                  text_size = 0;
 | 
					                  text_size = 0;
 | 
				
			||||||
                  break;
 | 
					                  break;
 | 
				
			||||||
               }
 | 
					               }
 | 
				
			||||||
               png_memcpy(text, png_ptr->chunkdata, prefix_size);
 | 
					 | 
				
			||||||
               png_memcpy(text + prefix_size, png_ptr->zbuf,
 | 
					               png_memcpy(text + prefix_size, png_ptr->zbuf,
 | 
				
			||||||
                    text_size - prefix_size);
 | 
					                    text_size - prefix_size);
 | 
				
			||||||
 | 
					               png_memcpy(text, png_ptr->chunkdata, prefix_size);
 | 
				
			||||||
               *(text + text_size) = 0x00;
 | 
					               *(text + text_size) = 0x00;
 | 
				
			||||||
               buffer_size = text_size;
 | 
					               buffer_size = text_size;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -303,33 +305,49 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
 | 
				
			|||||||
                     buffer_size = new_text_size;
 | 
					                     buffer_size = new_text_size;
 | 
				
			||||||
                  else
 | 
					                  else
 | 
				
			||||||
                     buffer_size += buffer_size;
 | 
					                     buffer_size += buffer_size;
 | 
				
			||||||
               }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
 | 
					#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED
 | 
				
			||||||
               if (png_ptr->user_chunk_malloc_max <= buffer_size)
 | 
					                  if (buffer_size >= png_ptr->user_chunk_malloc_max - 1)
 | 
				
			||||||
               {
 | 
					                  {
 | 
				
			||||||
                  png_free(png_ptr, tmp);
 | 
					                     if (new_text_size >=
 | 
				
			||||||
                  png_warning(png_ptr, "No space for decompressed chunk");
 | 
					                         png_ptr->user_chunk_malloc_max - 1)
 | 
				
			||||||
                  text = NULL;
 | 
					                     {
 | 
				
			||||||
               }
 | 
					                        png_free(png_ptr, tmp);
 | 
				
			||||||
 | 
					                        png_warning(png_ptr,
 | 
				
			||||||
 | 
					                            "No space for decompressed chunk");
 | 
				
			||||||
 | 
					                        text = NULL;
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                     else
 | 
				
			||||||
 | 
					                     {
 | 
				
			||||||
 | 
					                        buffer_size = png_ptr->user_chunk_malloc_max - 1;
 | 
				
			||||||
 | 
					                        text = (png_charp)png_malloc_warn(png_ptr,
 | 
				
			||||||
 | 
					                            buffer_size + 1);
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
               else
 | 
					                  else
 | 
				
			||||||
                  text = (png_charp)png_malloc_warn(png_ptr,
 | 
					                     text = (png_charp)png_malloc_warn(png_ptr,
 | 
				
			||||||
                     buffer_size + 1);
 | 
					                         buffer_size + 1);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
               text = (png_charp)png_malloc_warn(png_ptr,
 | 
					                 text = (png_charp)png_malloc_warn(png_ptr,
 | 
				
			||||||
                  buffer_size + 1);
 | 
					                    buffer_size + 1);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
               if (text == NULL)
 | 
					                 if (text == NULL)
 | 
				
			||||||
               {
 | 
					                 {
 | 
				
			||||||
                  png_warning(png_ptr,
 | 
					                    png_warning(png_ptr,
 | 
				
			||||||
                    "Not enough memory to decompress chunk");
 | 
					                      "Not enough memory to decompress chunk");
 | 
				
			||||||
                  break;
 | 
					                    break;
 | 
				
			||||||
               }
 | 
					                 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
               png_memcpy(text, tmp, text_size);
 | 
					                 png_memcpy(text, tmp, text_size);
 | 
				
			||||||
               png_free(png_ptr, tmp);
 | 
					                 png_free(png_ptr, tmp);
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					            /* FIX ME: zTXt chunk written by pngtest is 6 bytes too large */
 | 
				
			||||||
 | 
					            png_memcpy(text + text_size, png_ptr->zbuf,
 | 
				
			||||||
 | 
					               (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
 | 
				
			||||||
 | 
					            text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
 | 
				
			||||||
 | 
					            *(text + text_size) = 0x00;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
         if (ret == Z_STREAM_END)
 | 
					         if (ret == Z_STREAM_END)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user