1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #ifndef SkJpegPriv_DEFINED 10 #define SkJpegPriv_DEFINED 11 12 #include "include/codec/SkEncodedOrigin.h" 13 #include "include/core/SkStream.h" 14 #include "include/private/base/SkTArray.h" 15 16 #include <setjmp.h> 17 // stdio is needed for jpeglib 18 #include <stdio.h> 19 20 extern "C" { 21 #include "jpeglib.h" // NO_G3_REWRITE 22 #include "jerror.h" // NO_G3_REWRITE 23 } 24 25 /* 26 * Error handling struct 27 */ 28 struct skjpeg_error_mgr : public jpeg_error_mgr { 29 class AutoPushJmpBuf { 30 public: AutoPushJmpBufskjpeg_error_mgr31 AutoPushJmpBuf(skjpeg_error_mgr* mgr) : fMgr(mgr) { fMgr->push(&fJmpBuf); } ~AutoPushJmpBufskjpeg_error_mgr32 ~AutoPushJmpBuf() { fMgr->pop(&fJmpBuf); } 33 operator jmp_buf&() { return fJmpBuf; } 34 35 private: 36 skjpeg_error_mgr* const fMgr; 37 jmp_buf fJmpBuf; 38 }; 39 40 // When libjpeg initializes the fields of a `jpeg_error_mgr` (in `jpeg_std_error`), it 41 // leaves the msg_parm fields uninitialized. This is safe, but confuses MSAN, so we 42 // explicitly zero out the structure when constructing it. (crbug.com/oss-fuzz/68691) skjpeg_error_mgrskjpeg_error_mgr43 skjpeg_error_mgr() : jpeg_error_mgr({}) {} 44 pushskjpeg_error_mgr45 void push(jmp_buf* j) { 46 SkASSERT(fStack[3] == nullptr); // if we assert here, the stack has overflowed 47 fStack[3] = fStack[2]; 48 fStack[2] = fStack[1]; 49 fStack[1] = fStack[0]; 50 fStack[0] = j; 51 } 52 popskjpeg_error_mgr53 void pop(jmp_buf* j) { 54 SkASSERT(fStack[0] == j); // if we assert here, the pushes and pops were unbalanced 55 fStack[0] = fStack[1]; 56 fStack[1] = fStack[2]; 57 fStack[2] = fStack[3]; 58 fStack[3] = nullptr; 59 } 60 61 jmp_buf* fStack[4] = {}; 62 }; 63 64 #endif 65