aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/CodecExactReadTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/CodecExactReadTest.cpp')
-rw-r--r--tests/CodecExactReadTest.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/tests/CodecExactReadTest.cpp b/tests/CodecExactReadTest.cpp
new file mode 100644
index 0000000000..7e0d8eaccc
--- /dev/null
+++ b/tests/CodecExactReadTest.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Resources.h"
+#include "Test.h"
+
+#include "SkBitmap.h"
+#include "SkCodec.h"
+#include "SkData.h"
+#include "SkStream.h"
+
+namespace {
+// This class emits a skiatest failure if a client attempts to read beyond its
+// end. Since it is used with complete, valid images, and contains nothing
+// after the encoded image data, it will emit a failure if the client attempts
+// to read beyond the logical end of the data.
+class MyStream : public SkStream {
+public:
+ static MyStream* Make(const char* path, skiatest::Reporter* r) {
+ SkASSERT(path);
+ sk_sp<SkData> data(GetResourceAsData(path));
+ if (!data) {
+ return nullptr;
+ }
+
+ return new MyStream(path, std::move(data), r);
+ }
+
+ size_t read(void* buf, size_t bytes) override {
+ const size_t remaining = fStream.getLength() - fStream.getPosition();
+ if (bytes > remaining) {
+ ERRORF(fReporter, "Tried to read %lu bytes (only %lu remaining) from %s",
+ bytes, remaining, fPath);
+ }
+ return fStream.read(buf, bytes);
+ }
+
+ bool rewind() override {
+ return fStream.rewind();
+ }
+
+ bool isAtEnd() const override {
+ return fStream.isAtEnd();
+ }
+private:
+ const char* fPath;
+ SkMemoryStream fStream;
+ skiatest::Reporter* fReporter; // Unowned
+
+ MyStream(const char* path, sk_sp<SkData> data, skiatest::Reporter* r)
+ : fPath(path)
+ , fStream(std::move(data))
+ , fReporter(r)
+ {}
+};
+} // namespace
+
+// Test that SkPngCodec does not attempt to read its input beyond the logical
+// end of its data. Some other SkCodecs do, but some Android apps rely on not
+// doing so for PNGs.
+DEF_TEST(Codec_end, r) {
+ for (const char* path : { "plane.png",
+ "yellow_rose.png",
+ "plane_interlaced.png" }) {
+ std::unique_ptr<MyStream> stream(MyStream::Make(path, r));
+ if (!stream) {
+ continue;
+ }
+
+ std::unique_ptr<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
+ if (!codec) {
+ ERRORF(r, "Failed to create a codec from %s\n", path);
+ continue;
+ }
+
+ auto info = codec->getInfo().makeColorType(kN32_SkColorType);
+ SkBitmap bm;
+ bm.allocPixels(info);
+
+ auto result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes());
+ if (result != SkCodec::kSuccess) {
+ ERRORF(r, "Failed to getPixels from %s. error %i", path, result);
+ continue;
+ }
+
+ // Rewind and do an incremental decode.
+ result = codec->startIncrementalDecode(bm.info(), bm.getPixels(), bm.rowBytes());
+ if (result != SkCodec::kSuccess) {
+ ERRORF(r, "Failed to startIncrementalDecode from %s. error %i", path, result);
+ continue;
+ }
+
+ result = codec->incrementalDecode();
+ if (result != SkCodec::kSuccess) {
+ ERRORF(r, "Failed to incrementalDecode from %s. error %i", path, result);
+ }
+ }
+}