已合并
fix: 增强WebP解码缓冲区增强计算逻辑的健壮性 #5211
AFWEF147创建于 3月16日
fix: 增强WebP解码缓冲区增强计算逻辑的健壮性 #5211
已合并
共 2 个文件变更+40-8
| @@ -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); |
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | + | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | 27 | ||
| @@ -41,6 +42,27 @@ namespace { | |||
| 41 | constexpr int32_t WEBP_IMAGE_NUM = 1; | 42 | constexpr int32_t WEBP_IMAGE_NUM = 1; |
| 42 | constexpr int32_t EXTERNAL_MEMORY = 1; | 43 | constexpr int32_t EXTERNAL_MEMORY = 1; |
| 43 | constexpr size_t DECODE_VP8CHUNK_MIN_SIZE = 4096; | 44 | constexpr 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 | } // namespace | 66 | } // namespace |
| 45 | 67 | ||
| 46 | WebpDecoder::WebpDecoder() | 68 | WebpDecoder::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 space | 387 | 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 | 538 | ||
| 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) { |