From 194f740d0e2afcf0501747f11e95215b4c32788d Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Wed, 18 Feb 2015 01:57:31 +0000 Subject: [PATCH] Scan from start of buffer to handle case where an invalid size was passed. BUG=404 TESTED=libyuvTest.ValidateJpegLarge R=brucedawson@google.com, harryjin@google.com Review URL: https://webrtc-codereview.appspot.com/41989004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@1285 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/version.h | 2 +- source/mjpeg_validate.cc | 76 +++++++++++++++++++++++++++++++++------ unit_test/convert_test.cc | 5 +-- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/README.chromium b/README.chromium index 51c6f1c42..d7e620034 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1284 +Version: 1285 License: BSD License File: LICENSE diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 313063603..0334e9b13 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1284 +#define LIBYUV_VERSION 1285 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/mjpeg_validate.cc b/source/mjpeg_validate.cc index 23d22d099..40ce2f787 100644 --- a/source/mjpeg_validate.cc +++ b/source/mjpeg_validate.cc @@ -10,15 +10,66 @@ #include "libyuv/mjpeg_decoder.h" +#include // For memchr. + #ifdef __cplusplus namespace libyuv { extern "C" { #endif +// Enable this to try scasb implementation. +// #define ENABLE_SCASB 1 + +#ifdef ENABLE_SCASB + +// Multiple of 1. +__declspec(naked) __declspec(align(16)) +const uint8* ScanRow_ERMS(const uint8* src, uint32 val, int count) { + __asm { + mov edx, edi + mov edi, [esp + 4] // src + mov eax, [esp + 8] // val + mov ecx, [esp + 12] // count + repne scasb + jne sr99 + mov eax, edi + sub eax, 1 + mov edi, edx + ret + + sr99: + mov eax, 0 + mov edi, edx + ret + } +} +#endif + +// Helper function to scan for EOI marker. +static LIBYUV_BOOL ScanEOI(const uint8* sample, size_t sample_size) { + const uint8* end = sample + sample_size - 1; + const uint8* it = sample; + for (;;) { +#ifdef ENABLE_SCASB + it = ScanRow_ERMS(it, 0xff, end - it); +#else + it = static_cast(memchr(it, 0xff, end - it)); +#endif + if (it == NULL) { + break; + } + if (it[1] == 0xd9) { + return LIBYUV_TRUE; // Success: Valid jpeg. + } + ++it; // Skip over current 0xff. + } + // ERROR: Invalid jpeg end code not found. Size sample_size + return LIBYUV_FALSE; +} + // Helper function to validate the jpeg appears intact. -// TODO(fbarchard): Optimize case where SOI is found but EOI is not. LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size) { - size_t i; + const size_t kBackSearchSize = 1024; if (sample_size < 64) { // ERROR: Invalid jpeg size: sample_size return LIBYUV_FALSE; @@ -27,17 +78,20 @@ LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size) { // ERROR: Invalid jpeg initial start code return LIBYUV_FALSE; } - for (i = sample_size - 2; i > 1;) { - if (sample[i] != 0xd9) { - if (sample[i] == 0xff && sample[i + 1] == 0xd9) { // End Of Image - return LIBYUV_TRUE; // Success: Valid jpeg. - } - --i; + // Step over SOI marker. + sample += 2; + sample_size -= 2; + + // Look for the End Of Image (EOI) marker in the end kilobyte of the buffer. + if (sample_size > kBackSearchSize) { + if (ScanEOI(sample + sample_size - kBackSearchSize, kBackSearchSize)) { + return LIBYUV_TRUE; // Success: Valid jpeg. } - --i; + // Reduce search size for forward search. + sample_size = sample_size - kBackSearchSize + 1; } - // ERROR: Invalid jpeg end code not found. Size sample_size - return LIBYUV_FALSE; + return ScanEOI(sample, sample_size); + } #ifdef __cplusplus diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 8de8dba2d..d9a6d450d 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -66,7 +66,7 @@ TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \ srandom(time(NULL)); \ for (int i = 0; i < kHeight; ++i) \ for (int j = 0; j < kWidth; ++j) \ - src_y[i * kWidth + j + OFF] = (random() & 0xff); \ + src_y[i * kWidth + j + OFF] = (random() & 0xff); \ for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \ for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \ src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ @@ -1035,7 +1035,8 @@ TEST_F(libyuvTest, ValidateJpegLarge) { const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ? benchmark_width_ * benchmark_height_ : kMinJpeg; const int kSize = kImageSize + kOff; - const int kBufSize = kImageSize * 10 + kOff; + const int kMultiple = 10; + const int kBufSize = kImageSize * kMultiple + kOff; align_buffer_64(orig_pixels, kBufSize); // No SOI or EOI. Expect fail.