mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
Merge "WebPCheckMalloc() and WebPCheckCalloc():" into 0.2.0
This commit is contained in:
commit
4eb7aa64da
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user