已合并
fix: 增强WebP解码缓冲区增强计算逻辑的健壮性 #5211
fix: 增强WebP解码缓冲区增强计算逻辑的健壮性 #5211
已合并
AFWEF147创建于 3月16日
2 个文件变更+40-8
Mplugins/common/libs/image/libwebpplugin/include/webp_decoder.h+2-2
@@ -65,8 +65,8 @@ private:
65 WEBP_CSP_MODE GetWebpDecodeMode(const PixelFormat &pixelFormat, bool premul);65 WEBP_CSP_MODE GetWebpDecodeMode(const PixelFormat &pixelFormat, bool premul);
66 uint32_t ReadIncrementalHead();66 uint32_t ReadIncrementalHead();
67 uint32_t DecodeHeader();67 uint32_t DecodeHeader();
68- bool AllocOutputBuffer(DecodeContext &context, bool isIncremental);68+ bool AllocOutputBuffer(DecodeContext &context, bool isIncremental, uint32_t byteCount);
69- void InitWebpOutput(const DecodeContext &context, WebPDecBuffer &output);69+ void InitWebpOutput(const DecodeContext &context, WebPDecBuffer &output, int32_t stride);
70 bool PreDecodeProc(DecodeContext &context, WebPDecoderConfig &config, bool isIncremental);70 bool PreDecodeProc(DecodeContext &context, WebPDecoderConfig &config, bool isIncremental);
71 uint32_t DoCommonDecode(DecodeContext &context);71 uint32_t DoCommonDecode(DecodeContext &context);
72 uint32_t DoIncrementalDecode(ProgDecodeContext &context);72 uint32_t DoIncrementalDecode(ProgDecodeContext &context);
Mplugins/common/libs/image/libwebpplugin/src/webp_decoder.cpp+38-6
@@ -21,6 +21,7 @@
21#include "media_errors.h"21#include "media_errors.h"
22#include "multimedia_templates.h"22#include "multimedia_templates.h"
23#include "securec.h"23#include "securec.h"
24+#include <limits>
24#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)25#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
25#include "surface_buffer.h"26#include "surface_buffer.h"
26#endif27#endif
@@ -41,6 +42,27 @@ namespace {
41constexpr int32_t WEBP_IMAGE_NUM = 1;42constexpr int32_t WEBP_IMAGE_NUM = 1;
42constexpr int32_t EXTERNAL_MEMORY = 1;43constexpr int32_t EXTERNAL_MEMORY = 1;
43constexpr size_t DECODE_VP8CHUNK_MIN_SIZE = 4096;44constexpr size_t DECODE_VP8CHUNK_MIN_SIZE = 4096;
45+ 
46+bool GetWebpBufferInfo(const Size &webpSize, int32_t bytesPerPixel, uint32_t &stride, uint32_t &byteCount)
47+{
48+ if (webpSize.width <= 0 || webpSize.height <= 0 || bytesPerPixel <= 0) {
49+ IMAGE_LOGE("Invalid webp size(%{public}d, %{public}d) or bytesPerPixel:%{public}d.",
50+ webpSize.width, webpSize.height, bytesPerPixel);
51+ return false;
52+ }
53+ uint64_t stride64 = static_cast<uint64_t>(webpSize.width) * static_cast<uint64_t>(bytesPerPixel);
54+ uint64_t byteCount64 = stride64 * static_cast<uint64_t>(webpSize.height);
55+ if (stride64 > static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) ||
56+ byteCount64 > static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) ||
57+ byteCount64 > static_cast<uint64_t>(PIXEL_MAP_MAX_RAM_SIZE)) {
58+ IMAGE_LOGE("overflow check failed. width:%{public}d, height:%{public}d, bytesPerPixel:%{public}d.",
59+ webpSize.width, webpSize.height, bytesPerPixel);
60+ return false;
61+ }
62+ stride = static_cast<uint32_t>(stride64);
63+ byteCount = static_cast<uint32_t>(byteCount64);
64+ return true;
65+}
44} // namespace66} // namespace
45 67 
46WebpDecoder::WebpDecoder()68WebpDecoder::WebpDecoder()
@@ -360,11 +382,11 @@ uint32_t WebpDecoder::DoIncrementalDecode(ProgDecodeContext &context) __attribut
360 return SUCCESS;382 return SUCCESS;
361}383}
362 384 
363-void WebpDecoder::InitWebpOutput(const DecodeContext &context, WebPDecBuffer &output)385+void WebpDecoder::InitWebpOutput(const DecodeContext &context, WebPDecBuffer &output, int32_t stride)
364{386{
365 output.is_external_memory = EXTERNAL_MEMORY; // external allocated space387 output.is_external_memory = EXTERNAL_MEMORY; // external allocated space
366 output.u.RGBA.rgba = static_cast<uint8_t *>(context.pixelsBuffer.buffer);388 output.u.RGBA.rgba = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
367- output.u.RGBA.stride = webpSize_.width * bytesPerPixel_;389+ output.u.RGBA.stride = stride;
368 output.u.RGBA.size = context.pixelsBuffer.bufferSize;390 output.u.RGBA.size = context.pixelsBuffer.bufferSize;
369 output.colorspace = webpMode_;391 output.colorspace = webpMode_;
370}392}
@@ -375,12 +397,23 @@ bool WebpDecoder::PreDecodeProc(DecodeContext &context, WebPDecoderConfig &confi
375 IMAGE_LOGE("init config failed.");397 IMAGE_LOGE("init config failed.");
376 return false;398 return false;
377 }399 }
378- if (!AllocOutputBuffer(context, isIncremental)) {400+ uint32_t stride = 0;
401+ uint32_t byteCount = 0;
402+ if (!GetWebpBufferInfo(webpSize_, bytesPerPixel_, stride, byteCount)) {
403+ IMAGE_LOGE("check webp buffer info failed.");
404+ return false;
405+ }
406+ if (!AllocOutputBuffer(context, isIncremental, byteCount)) {
379 IMAGE_LOGE("get pixels memory failed.");407 IMAGE_LOGE("get pixels memory failed.");
380 return false;408 return false;
381 }409 }
410+ if (context.pixelsBuffer.bufferSize < byteCount) {
411+ IMAGE_LOGE("invalid webp output buffer size. actual:%{public}u, expected:%{public}u.",
412+ context.pixelsBuffer.bufferSize, byteCount);
413+ return false;
414+ }
382 415 
383- InitWebpOutput(context, config.output);416+ InitWebpOutput(context, config.output, static_cast<int32_t>(stride));
384 return true;417 return true;
385}418}
386 419 
@@ -505,7 +538,7 @@ static bool DmaMemoryCreate(DecodeContext &context, const uint32_t &byteCount, c
505#endif538#endif
506}539}
507 540 
508-bool WebpDecoder::AllocOutputBuffer(DecodeContext &context, bool isIncremental)541+bool WebpDecoder::AllocOutputBuffer(DecodeContext &context, bool isIncremental, uint32_t byteCount)
509{542{
510 if (isIncremental) {543 if (isIncremental) {
511 if (context.pixelsBuffer.buffer != nullptr && context.allocatorType == AllocatorType::HEAP_ALLOC) {544 if (context.pixelsBuffer.buffer != nullptr && context.allocatorType == AllocatorType::HEAP_ALLOC) {
@@ -514,7 +547,6 @@ bool WebpDecoder::AllocOutputBuffer(DecodeContext &context, bool isIncremental)
514 }547 }
515 }548 }
516 if (context.pixelsBuffer.buffer == nullptr) {549 if (context.pixelsBuffer.buffer == nullptr) {
517- uint64_t byteCount = static_cast<uint64_t>(webpSize_.width * webpSize_.height * bytesPerPixel_);
518 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {550 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
519 return SharedMemoryCreate(context, byteCount);551 return SharedMemoryCreate(context, byteCount);
520 } else if (context.allocatorType == Media::AllocatorType::HEAP_ALLOC) {552 } else if (context.allocatorType == Media::AllocatorType::HEAP_ALLOC) {