From 45904e5667c5bf59c67fcdc586dfba110832894c Mon Sep 17 00:00:00 2001
From: Dirk Farin <dirk.farin@gmail.com>
Date: Tue, 5 Apr 2022 20:00:20 +0200
Subject: [PATCH] fix reading invalid images where shdr references are NULL in
 part of the image (#302)

---
 libde265/deblock.cc | 127 +++++++++++++++++++++++---------------------
 libde265/sao.cc     |   5 +-
 2 files changed, 70 insertions(+), 62 deletions(-)

diff --git a/libde265/deblock.cc b/libde265/deblock.cc
index 62428832e..60fd2ca1c 100644
--- a/libde265/deblock.cc
+++ b/libde265/deblock.cc
@@ -295,67 +295,72 @@ void derive_boundaryStrength(de265_image* img, bool vertical, int yStart,int yEn
             slice_segment_header* shdrP = img->get_SliceHeader(xDiOpp,yDiOpp);
             slice_segment_header* shdrQ = img->get_SliceHeader(xDi   ,yDi);
 
-            int refPicP0 = mviP.predFlag[0] ? shdrP->RefPicList[0][ mviP.refIdx[0] ] : -1;
-            int refPicP1 = mviP.predFlag[1] ? shdrP->RefPicList[1][ mviP.refIdx[1] ] : -1;
-            int refPicQ0 = mviQ.predFlag[0] ? shdrQ->RefPicList[0][ mviQ.refIdx[0] ] : -1;
-            int refPicQ1 = mviQ.predFlag[1] ? shdrQ->RefPicList[1][ mviQ.refIdx[1] ] : -1;
-
-            bool samePics = ((refPicP0==refPicQ0 && refPicP1==refPicQ1) ||
-                             (refPicP0==refPicQ1 && refPicP1==refPicQ0));
-
-            if (!samePics) {
-              bS = 1;
-            }
-            else {
-              MotionVector mvP0 = mviP.mv[0]; if (!mviP.predFlag[0]) { mvP0.x=mvP0.y=0; }
-              MotionVector mvP1 = mviP.mv[1]; if (!mviP.predFlag[1]) { mvP1.x=mvP1.y=0; }
-              MotionVector mvQ0 = mviQ.mv[0]; if (!mviQ.predFlag[0]) { mvQ0.x=mvQ0.y=0; }
-              MotionVector mvQ1 = mviQ.mv[1]; if (!mviQ.predFlag[1]) { mvQ1.x=mvQ1.y=0; }
-
-              int numMV_P = mviP.predFlag[0] + mviP.predFlag[1];
-              int numMV_Q = mviQ.predFlag[0] + mviQ.predFlag[1];
-
-              if (numMV_P!=numMV_Q) {
-                img->decctx->add_warning(DE265_WARNING_NUMMVP_NOT_EQUAL_TO_NUMMVQ, false);
-                img->integrity = INTEGRITY_DECODING_ERRORS;
-              }
-
-              // two different reference pictures or only one reference picture
-              if (refPicP0 != refPicP1) {
-
-                if (refPicP0 == refPicQ0) {
-                  if (abs_value(mvP0.x-mvQ0.x) >= 4 ||
-                      abs_value(mvP0.y-mvQ0.y) >= 4 ||
-                      abs_value(mvP1.x-mvQ1.x) >= 4 ||
-                      abs_value(mvP1.y-mvQ1.y) >= 4) {
-                    bS = 1;
-                  }
-                }
-                else {
-                  if (abs_value(mvP0.x-mvQ1.x) >= 4 ||
-                      abs_value(mvP0.y-mvQ1.y) >= 4 ||
-                      abs_value(mvP1.x-mvQ0.x) >= 4 ||
-                      abs_value(mvP1.y-mvQ0.y) >= 4) {
-                    bS = 1;
-                  }
-                }
-              }
-              else {
-                assert(refPicQ0==refPicQ1);
-
-                if ((abs_value(mvP0.x-mvQ0.x) >= 4 ||
-                     abs_value(mvP0.y-mvQ0.y) >= 4 ||
-                     abs_value(mvP1.x-mvQ1.x) >= 4 ||
-                     abs_value(mvP1.y-mvQ1.y) >= 4)
-                    &&
-                    (abs_value(mvP0.x-mvQ1.x) >= 4 ||
-                     abs_value(mvP0.y-mvQ1.y) >= 4 ||
-                     abs_value(mvP1.x-mvQ0.x) >= 4 ||
-                     abs_value(mvP1.y-mvQ0.y) >= 4)) {
-                  bS = 1;
-                }
-              }
-            }
+	    if (shdrP && shdrQ) {
+	      int refPicP0 = mviP.predFlag[0] ? shdrP->RefPicList[0][ mviP.refIdx[0] ] : -1;
+	      int refPicP1 = mviP.predFlag[1] ? shdrP->RefPicList[1][ mviP.refIdx[1] ] : -1;
+	      int refPicQ0 = mviQ.predFlag[0] ? shdrQ->RefPicList[0][ mviQ.refIdx[0] ] : -1;
+	      int refPicQ1 = mviQ.predFlag[1] ? shdrQ->RefPicList[1][ mviQ.refIdx[1] ] : -1;
+
+	      bool samePics = ((refPicP0==refPicQ0 && refPicP1==refPicQ1) ||
+			       (refPicP0==refPicQ1 && refPicP1==refPicQ0));
+
+	      if (!samePics) {
+		bS = 1;
+	      }
+	      else {
+		MotionVector mvP0 = mviP.mv[0]; if (!mviP.predFlag[0]) { mvP0.x=mvP0.y=0; }
+		MotionVector mvP1 = mviP.mv[1]; if (!mviP.predFlag[1]) { mvP1.x=mvP1.y=0; }
+		MotionVector mvQ0 = mviQ.mv[0]; if (!mviQ.predFlag[0]) { mvQ0.x=mvQ0.y=0; }
+		MotionVector mvQ1 = mviQ.mv[1]; if (!mviQ.predFlag[1]) { mvQ1.x=mvQ1.y=0; }
+
+		int numMV_P = mviP.predFlag[0] + mviP.predFlag[1];
+		int numMV_Q = mviQ.predFlag[0] + mviQ.predFlag[1];
+
+		if (numMV_P!=numMV_Q) {
+		  img->decctx->add_warning(DE265_WARNING_NUMMVP_NOT_EQUAL_TO_NUMMVQ, false);
+		  img->integrity = INTEGRITY_DECODING_ERRORS;
+		}
+
+		// two different reference pictures or only one reference picture
+		if (refPicP0 != refPicP1) {
+
+		  if (refPicP0 == refPicQ0) {
+		    if (abs_value(mvP0.x-mvQ0.x) >= 4 ||
+			abs_value(mvP0.y-mvQ0.y) >= 4 ||
+			abs_value(mvP1.x-mvQ1.x) >= 4 ||
+			abs_value(mvP1.y-mvQ1.y) >= 4) {
+		      bS = 1;
+		    }
+		  }
+		  else {
+		    if (abs_value(mvP0.x-mvQ1.x) >= 4 ||
+			abs_value(mvP0.y-mvQ1.y) >= 4 ||
+			abs_value(mvP1.x-mvQ0.x) >= 4 ||
+			abs_value(mvP1.y-mvQ0.y) >= 4) {
+		      bS = 1;
+		    }
+		  }
+		}
+		else {
+		  assert(refPicQ0==refPicQ1);
+
+		  if ((abs_value(mvP0.x-mvQ0.x) >= 4 ||
+		       abs_value(mvP0.y-mvQ0.y) >= 4 ||
+		       abs_value(mvP1.x-mvQ1.x) >= 4 ||
+		       abs_value(mvP1.y-mvQ1.y) >= 4)
+		      &&
+		      (abs_value(mvP0.x-mvQ1.x) >= 4 ||
+		       abs_value(mvP0.y-mvQ1.y) >= 4 ||
+		       abs_value(mvP1.x-mvQ0.x) >= 4 ||
+		       abs_value(mvP1.y-mvQ0.y) >= 4)) {
+		    bS = 1;
+		  }
+		}
+	      }
+	    }
+	    else {
+	      bS = 0; // if shdrP==NULL or shdrQ==NULL
+	    }
 
             /*
               printf("unimplemented deblocking code for CU at %d;%d\n",xDi,yDi);
diff --git a/libde265/sao.cc b/libde265/sao.cc
index f93fc02a2..ed8676ea2 100644
--- a/libde265/sao.cc
+++ b/libde265/sao.cc
@@ -353,7 +353,10 @@ void apply_sample_adaptive_offset_sequential(de265_image* img)
       for (int xCtb=0; xCtb<sps.PicWidthInCtbsY; xCtb++)
         {
           const slice_segment_header* shdr = img->get_SliceHeaderCtb(xCtb,yCtb);
-          if (shdr==NULL) { return; }
+          if (shdr==NULL) {
+	    delete[] inputCopy;
+	    return;
+	  }
 
           if (cIdx==0 && shdr->slice_sao_luma_flag) {
             apply_sao(img, xCtb,yCtb, shdr, 0, 1<<sps.Log2CtbSizeY, 1<<sps.Log2CtbSizeY,
