mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 18:35:41 +01:00 
			
		
		
		
	Merge "WebPCheckMalloc() and WebPCheckCalloc():" into 0.2.0
This commit is contained in:
		| @@ -47,6 +47,7 @@ LOCAL_SRC_FILES := \ | |||||||
|     src/utils/quant_levels.c \ |     src/utils/quant_levels.c \ | ||||||
|     src/utils/rescaler.c \ |     src/utils/rescaler.c \ | ||||||
|     src/utils/thread.c \ |     src/utils/thread.c \ | ||||||
|  |     src/utils/utils.c \ | ||||||
|  |  | ||||||
| LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD \ | LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD \ | ||||||
|                 -DNOT_HAVE_LOG2 -DWEBP_USE_THREAD \ |                 -DNOT_HAVE_LOG2 -DWEBP_USE_THREAD \ | ||||||
|   | |||||||
| @@ -199,6 +199,7 @@ UTILS_OBJS = \ | |||||||
|     $(DIROBJ)\utils\quant_levels.obj \ |     $(DIROBJ)\utils\quant_levels.obj \ | ||||||
|     $(DIROBJ)\utils\rescaler.obj \ |     $(DIROBJ)\utils\rescaler.obj \ | ||||||
|     $(DIROBJ)\utils\thread.obj \ |     $(DIROBJ)\utils\thread.obj \ | ||||||
|  |     $(DIROBJ)\utils\utils.obj \ | ||||||
|  |  | ||||||
| LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) $(LIBWEBP_OBJS) | LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) $(LIBWEBP_OBJS) | ||||||
| LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS) | LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS) | ||||||
|   | |||||||
| @@ -117,13 +117,12 @@ static int CountOccurrences(const char* arglist[], int list_length, | |||||||
| } | } | ||||||
|  |  | ||||||
| static const char* const kErrorMessages[] = { | static const char* const kErrorMessages[] = { | ||||||
|   "WEBP_MUX_ERROR", "WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", |   "WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA", | ||||||
|   "WEBP_MUX_INVALID_PARAMETER", "WEBP_MUX_BAD_DATA", "WEBP_MUX_MEMORY_ERROR", |   "WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA" | ||||||
|   "WEBP_MUX_NOT_ENOUGH_DATA" |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const char* ErrorString(WebPMuxError err) { | static const char* ErrorString(WebPMuxError err) { | ||||||
|   assert(err <= WEBP_MUX_ERROR && err >= WEBP_MUX_NOT_ENOUGH_DATA); |   assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA); | ||||||
|   return kErrorMessages[-err]; |   return kErrorMessages[-err]; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -130,6 +130,7 @@ UTILS_OBJS = \ | |||||||
|     src/utils/quant_levels.o \ |     src/utils/quant_levels.o \ | ||||||
|     src/utils/rescaler.o \ |     src/utils/rescaler.o \ | ||||||
|     src/utils/thread.o \ |     src/utils/thread.o \ | ||||||
|  |     src/utils/utils.o \ | ||||||
|  |  | ||||||
| LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) | LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) | ||||||
| LIBWEBPMUX_OBJS = $(MUX_OBJS) | LIBWEBPMUX_OBJS = $(MUX_OBJS) | ||||||
|   | |||||||
| @@ -17,15 +17,6 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Object to store metadata about images. |  | ||||||
| typedef struct { |  | ||||||
|   int x_offset_; |  | ||||||
|   int y_offset_; |  | ||||||
|   int duration_; |  | ||||||
|   int width_; |  | ||||||
|   int height_; |  | ||||||
| } WebPImageInfo; |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Life of a mux object. | // Life of a mux object. | ||||||
|  |  | ||||||
| @@ -111,8 +102,7 @@ static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag, | |||||||
|   const WebPData chunk_data = { data, size }; |   const WebPData chunk_data = { data, size }; | ||||||
|   assert(mux != NULL); |   assert(mux != NULL); | ||||||
|   assert(size <= MAX_CHUNK_PAYLOAD); |   assert(size <= MAX_CHUNK_PAYLOAD); | ||||||
|  |   assert(idx != IDX_NIL); | ||||||
|   if (idx == IDX_NIL) return WEBP_MUX_INVALID_PARAMETER; |  | ||||||
|   return MuxSet(mux, idx, nth, &chunk_data, copy_data); |   return MuxSet(mux, idx, nth, &chunk_data, copy_data); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,7 +148,7 @@ static WebPMuxError CreateFrameTileData(const WebPData* const image, | |||||||
| static WebPMuxError GetImageData(const WebPData* const bitstream, | static WebPMuxError GetImageData(const WebPData* const bitstream, | ||||||
|                                  WebPData* const image, WebPData* const alpha, |                                  WebPData* const image, WebPData* const alpha, | ||||||
|                                  int* const is_lossless) { |                                  int* const is_lossless) { | ||||||
|   memset(alpha, 0, sizeof(*alpha));  // Default: no alpha. |   WebPDataInit(alpha);  // Default: no alpha. | ||||||
|   if (bitstream->size_ < TAG_SIZE || |   if (bitstream->size_ < TAG_SIZE || | ||||||
|       memcmp(bitstream->bytes_, "RIFF", TAG_SIZE)) { |       memcmp(bitstream->bytes_, "RIFF", TAG_SIZE)) { | ||||||
|     // It is NOT webp file data. Return input data as is. |     // It is NOT webp file data. Return input data as is. | ||||||
| @@ -360,7 +350,7 @@ static WebPMuxError MuxPushFrameTileInternal( | |||||||
|   if (err != WEBP_MUX_OK) return err; |   if (err != WEBP_MUX_OK) return err; | ||||||
|   image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; |   image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; | ||||||
|  |  | ||||||
|   memset(&frame_tile, 0, sizeof(frame_tile)); |   WebPDataInit(&frame_tile); | ||||||
|   ChunkInit(&chunk); |   ChunkInit(&chunk); | ||||||
|   MuxImageInit(&wpi); |   MuxImageInit(&wpi); | ||||||
|  |  | ||||||
| @@ -505,30 +495,19 @@ WebPMuxError MuxGetImageWidthHeight(const WebPChunk* const image_chunk, | |||||||
| } | } | ||||||
|  |  | ||||||
| static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, | static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, | ||||||
|                                  WebPImageInfo* const image_info) { |                                  int* const x_offset, int* const y_offset, | ||||||
|  |                                  int* const duration, | ||||||
|  |                                  int* const width, int* const height) { | ||||||
|   const WebPChunk* const image_chunk = wpi->img_; |   const WebPChunk* const image_chunk = wpi->img_; | ||||||
|   const WebPChunk* const frame_tile_chunk = wpi->header_; |   const WebPChunk* const frame_tile_chunk = wpi->header_; | ||||||
|   WebPMuxError err; |  | ||||||
|   int x_offset, y_offset, duration; |  | ||||||
|   int width, height; |  | ||||||
|  |  | ||||||
|   memset(image_info, 0, sizeof(*image_info)); |  | ||||||
|  |  | ||||||
|   // Get offsets and duration from FRM/TILE chunk. |   // Get offsets and duration from FRM/TILE chunk. | ||||||
|   err = GetFrameTileInfo(frame_tile_chunk, &x_offset, &y_offset, &duration); |   const WebPMuxError err = | ||||||
|  |       GetFrameTileInfo(frame_tile_chunk, x_offset, y_offset, duration); | ||||||
|   if (err != WEBP_MUX_OK) return err; |   if (err != WEBP_MUX_OK) return err; | ||||||
|  |  | ||||||
|   // Get width and height from VP8/VP8L chunk. |   // Get width and height from VP8/VP8L chunk. | ||||||
|   err = MuxGetImageWidthHeight(image_chunk, &width, &height); |   return MuxGetImageWidthHeight(image_chunk, width, height); | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|  |  | ||||||
|   // All OK: fill up image_info. |  | ||||||
|   image_info->x_offset_ = x_offset; |  | ||||||
|   image_info->y_offset_ = y_offset; |  | ||||||
|   image_info->duration_ = duration; |  | ||||||
|   image_info->width_    = width; |  | ||||||
|   image_info->height_   = height; |  | ||||||
|   return WEBP_MUX_OK; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static WebPMuxError GetImageCanvasWidthHeight( | static WebPMuxError GetImageCanvasWidthHeight( | ||||||
| @@ -536,7 +515,7 @@ static WebPMuxError GetImageCanvasWidthHeight( | |||||||
|     int* const width, int* const height) { |     int* const width, int* const height) { | ||||||
|   WebPMuxImage* wpi = NULL; |   WebPMuxImage* wpi = NULL; | ||||||
|   assert(mux != NULL); |   assert(mux != NULL); | ||||||
|   assert(width && height); |   assert(width != NULL && height != NULL); | ||||||
|  |  | ||||||
|   wpi = mux->images_; |   wpi = mux->images_; | ||||||
|   assert(wpi != NULL); |   assert(wpi != NULL); | ||||||
| @@ -548,17 +527,18 @@ static WebPMuxError GetImageCanvasWidthHeight( | |||||||
|     int64_t image_area = 0; |     int64_t image_area = 0; | ||||||
|     // Aggregate the bounding box for animation frames & tiled images. |     // Aggregate the bounding box for animation frames & tiled images. | ||||||
|     for (; wpi != NULL; wpi = wpi->next_) { |     for (; wpi != NULL; wpi = wpi->next_) { | ||||||
|       WebPImageInfo image_info; |       int x_offset, y_offset, duration, w, h; | ||||||
|       const WebPMuxError err = GetImageInfo(wpi, &image_info); |       const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, | ||||||
|       const int max_x_pos = image_info.x_offset_ + image_info.width_; |                                             &duration, &w, &h); | ||||||
|       const int max_y_pos = image_info.y_offset_ + image_info.height_; |       const int max_x_pos = x_offset + w; | ||||||
|  |       const int max_y_pos = y_offset + h; | ||||||
|       if (err != WEBP_MUX_OK) return err; |       if (err != WEBP_MUX_OK) return err; | ||||||
|       assert(image_info.x_offset_ < MAX_POSITION_OFFSET); |       assert(x_offset < MAX_POSITION_OFFSET); | ||||||
|       assert(image_info.y_offset_ < MAX_POSITION_OFFSET); |       assert(y_offset < MAX_POSITION_OFFSET); | ||||||
|  |  | ||||||
|       if (max_x_pos > max_x) max_x = max_x_pos; |       if (max_x_pos > max_x) max_x = max_x_pos; | ||||||
|       if (max_y_pos > max_y) max_y = max_y_pos; |       if (max_y_pos > max_y) max_y = max_y_pos; | ||||||
|       image_area += (image_info.width_ * image_info.height_); |       image_area += w * h; | ||||||
|     } |     } | ||||||
|     *width = max_x; |     *width = max_x; | ||||||
|     *height = max_y; |     *height = max_y; | ||||||
|   | |||||||
| @@ -212,17 +212,23 @@ uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Manipulation of a WebPData object. | // Manipulation of a WebPData object. | ||||||
|  |  | ||||||
|  | void WebPDataInit(WebPData* webp_data) { | ||||||
|  |   if (webp_data != NULL) { | ||||||
|  |     memset(webp_data, 0, sizeof(*webp_data)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| void WebPDataClear(WebPData* webp_data) { | void WebPDataClear(WebPData* webp_data) { | ||||||
|   if (webp_data != NULL) { |   if (webp_data != NULL) { | ||||||
|     free((void*)webp_data->bytes_); |     free((void*)webp_data->bytes_); | ||||||
|     memset(webp_data, 0, sizeof(*webp_data)); |     WebPDataInit(webp_data); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| int WebPDataCopy(const WebPData* src, WebPData* dst) { | int WebPDataCopy(const WebPData* src, WebPData* dst) { | ||||||
|   if (src == NULL || dst == NULL) return 0; |   if (src == NULL || dst == NULL) return 0; | ||||||
|  |  | ||||||
|   memset(dst, 0, sizeof(*dst)); |   WebPDataInit(dst); | ||||||
|   if (src->bytes_ != NULL && src->size_ != 0) { |   if (src->bytes_ != NULL && src->size_ != 0) { | ||||||
|     dst->bytes_ = (uint8_t*)malloc(src->size_); |     dst->bytes_ = (uint8_t*)malloc(src->size_); | ||||||
|     if (dst->bytes_ == NULL) return 0; |     if (dst->bytes_ == NULL) return 0; | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, | |||||||
|                            uint32_t nth, WebPData* const data) { |                            uint32_t nth, WebPData* const data) { | ||||||
|   assert(mux != NULL); |   assert(mux != NULL); | ||||||
|   assert(!IsWPI(kChunks[idx].id)); |   assert(!IsWPI(kChunks[idx].id)); | ||||||
|   memset(data, 0, sizeof(*data)); |   WebPDataInit(data); | ||||||
|  |  | ||||||
|   SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); |   SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); | ||||||
|   SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); |   SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); | ||||||
|   | |||||||
| @@ -20,6 +20,8 @@ libwebputils_la_SOURCES += rescaler.c | |||||||
| libwebputils_la_SOURCES += rescaler.h | libwebputils_la_SOURCES += rescaler.h | ||||||
| libwebputils_la_SOURCES += thread.c | libwebputils_la_SOURCES += thread.c | ||||||
| libwebputils_la_SOURCES += thread.h | libwebputils_la_SOURCES += thread.h | ||||||
|  | libwebputils_la_SOURCES += utils.c | ||||||
|  | libwebputils_la_SOURCES += utils.h | ||||||
|  |  | ||||||
| libwebputilsinclude_HEADERS = ../webp/types.h | libwebputilsinclude_HEADERS = ../webp/types.h | ||||||
| libwebputilsincludedir = $(includedir)/webp | libwebputilsincludedir = $(includedir)/webp | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								src/utils/utils.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/utils/utils.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | // Copyright 2012 Google Inc. All Rights Reserved. | ||||||
|  | // | ||||||
|  | // This code is licensed under the same terms as WebM: | ||||||
|  | //  Software License Agreement:  http://www.webmproject.org/license/software/ | ||||||
|  | //  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/ | ||||||
|  | // ----------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // Misc. common utility functions | ||||||
|  | // | ||||||
|  | // Author: Skal (pascal.massimino@gmail.com) | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include "./utils.h" | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | // Checked memory allocation | ||||||
|  |  | ||||||
|  | static int CheckSizeArguments(uint64_t nmemb, size_t size) { | ||||||
|  |   const uint64_t total_size = nmemb * size; | ||||||
|  |   if (nmemb == 0) return 1; | ||||||
|  |   if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; | ||||||
|  |   if (total_size != (size_t)total_size) return 0; | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void* WebPSafeMalloc(uint64_t nmemb, size_t size) { | ||||||
|  |   if (!CheckSizeArguments(nmemb, size)) return NULL; | ||||||
|  |   return malloc((size_t)(nmemb * size)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void* WebPSafeCalloc(uint64_t nmemb, size_t size) { | ||||||
|  |   if (!CheckSizeArguments(nmemb, size)) return NULL; | ||||||
|  |   return calloc((size_t)nmemb, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
|  | }    // extern "C" | ||||||
|  | #endif | ||||||
							
								
								
									
										44
									
								
								src/utils/utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/utils/utils.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | // Copyright 2012 Google Inc. All Rights Reserved. | ||||||
|  | // | ||||||
|  | // This code is licensed under the same terms as WebM: | ||||||
|  | //  Software License Agreement:  http://www.webmproject.org/license/software/ | ||||||
|  | //  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/ | ||||||
|  | // ----------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // Misc. common utility functions | ||||||
|  | // | ||||||
|  | // Author: Skal (pascal.massimino@gmail.com) | ||||||
|  |  | ||||||
|  | #ifndef WEBP_UTILS_UTILS_H_ | ||||||
|  | #define WEBP_UTILS_UTILS_H_ | ||||||
|  |  | ||||||
|  | #include "../webp/types.h" | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | // Memory allocation | ||||||
|  |  | ||||||
|  | // This is the maximum memory amount that libwebp will ever try to allocate. | ||||||
|  | #define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40) | ||||||
|  |  | ||||||
|  | // size-checking safe malloc/calloc: verify that the requested size is not too | ||||||
|  | // large, or return NULL. You don't need to call these for constructs like | ||||||
|  | // malloc(sizeof(foo)), but only if there's picture-dependent size involved | ||||||
|  | // somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this | ||||||
|  | // safe malloc() borrows the signature from calloc(), pointing at the dangerous | ||||||
|  | // underlying multiply involved. | ||||||
|  | void* WebPSafeMalloc(uint64_t nmemb, size_t size); | ||||||
|  | // Note that WebPSafeCalloc() expects the second argument type to be 'size_t' | ||||||
|  | // in order to favor the "calloc(num_foo, sizeof(foo))" pattern. | ||||||
|  | void* WebPSafeCalloc(uint64_t nmemb, size_t size); | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
|  | }    // extern "C" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif  /* WEBP_UTILS_UTILS_H_ */ | ||||||
| @@ -56,13 +56,11 @@ extern "C" { | |||||||
| // Error codes | // Error codes | ||||||
| typedef enum { | typedef enum { | ||||||
|   WEBP_MUX_OK                 =  1, |   WEBP_MUX_OK                 =  1, | ||||||
|   WEBP_MUX_ERROR              =  0, |   WEBP_MUX_NOT_FOUND          =  0, | ||||||
|   WEBP_MUX_NOT_FOUND          = -1, |   WEBP_MUX_INVALID_ARGUMENT   = -1, | ||||||
|   WEBP_MUX_INVALID_ARGUMENT   = -2, |   WEBP_MUX_BAD_DATA           = -2, | ||||||
|   WEBP_MUX_INVALID_PARAMETER  = -3, |   WEBP_MUX_MEMORY_ERROR       = -3, | ||||||
|   WEBP_MUX_BAD_DATA           = -4, |   WEBP_MUX_NOT_ENOUGH_DATA    = -4 | ||||||
|   WEBP_MUX_MEMORY_ERROR       = -5, |  | ||||||
|   WEBP_MUX_NOT_ENOUGH_DATA    = -6 |  | ||||||
| } WebPMuxError; | } WebPMuxError; | ||||||
|  |  | ||||||
| // Flag values for different features used in VP8X chunk. | // Flag values for different features used in VP8X chunk. | ||||||
| @@ -100,6 +98,9 @@ typedef struct { | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Manipulation of a WebPData object. | // Manipulation of a WebPData object. | ||||||
|  |  | ||||||
|  | // Initializes the contents of the 'webp_data' object with default values. | ||||||
|  | WEBP_EXTERN(void) WebPDataInit(WebPData* webp_data); | ||||||
|  |  | ||||||
| // Clears the contents of the 'webp_data' object by calling free(). Does not | // Clears the contents of the 'webp_data' object by calling free(). Does not | ||||||
| // deallocate the object itself. | // deallocate the object itself. | ||||||
| WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data); | WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user