]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Handle empty rects from the server
authorPierre Ossman <ossman@cendio.se>
Fri, 4 Sep 2020 14:16:44 +0000 (16:16 +0200)
committerPierre Ossman <ossman@cendio.se>
Fri, 4 Sep 2020 14:16:44 +0000 (16:16 +0200)
These are very pointless for the server to send, but not a violation of
the protocol so we need to be able to handle them. We've seen this
happen in real world scenarios a few times.

core/decoders/copyrect.js
core/decoders/tight.js
tests/test.copyrect.js
tests/test.hextile.js
tests/test.raw.js
tests/test.rre.js
tests/test.tight.js

index 0e0536a6ac77b0a28d782c5c48f4531972dc6664..9e6391a1733216da3ad8d2a9970634bb59dc5fdd 100644 (file)
@@ -15,6 +15,11 @@ export default class CopyRectDecoder {
 
         let deltaX = sock.rQshift16();
         let deltaY = sock.rQshift16();
+
+        if ((width === 0) || (height === 0)) {
+            return true;
+        }
+
         display.copyImage(deltaX, deltaY, x, y, width, height);
 
         return true;
index 8bc97d10d7525e53f19e7527d1570040b38ef842..7952707c5e6b48c8daea2d7c25cfca39be261550 100644 (file)
@@ -148,6 +148,10 @@ export default class TightDecoder {
         const uncompressedSize = width * height * 3;
         let data;
 
+        if (uncompressedSize === 0) {
+            return true;
+        }
+
         if (uncompressedSize < 12) {
             if (sock.rQwait("TIGHT", uncompressedSize)) {
                 return false;
@@ -203,6 +207,10 @@ export default class TightDecoder {
 
         let data;
 
+        if (uncompressedSize === 0) {
+            return true;
+        }
+
         if (uncompressedSize < 12) {
             if (sock.rQwait("TIGHT", uncompressedSize)) {
                 return false;
index e2277cb5b25e5ca95f13b8135818c1573221e8d2..c67caeb5e69126438a7f7d7efd45c20d623bd570 100644 (file)
@@ -57,4 +57,21 @@ describe('CopyRect Decoder', function () {
 
         expect(display).to.have.displayed(targetData);
     });
+
+    it('should handle empty rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [0x00, 0x00, 0x00, 0x00], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
 });
index 052c82e114cdb11d15d697b9622b15709035e124..a703100f69985029cdcf9b46f0bdced05828ed39 100644 (file)
@@ -206,4 +206,21 @@ describe('Hextile Decoder', function () {
         let data = [45];  // an invalid subencoding
         expect(() => testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24)).to.throw();
     });
+
+    it('should handle empty rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
 });
index 95a33af99ae06cde9f89594d756dce2ef9dbe6d8..13b3502c83835b811cc173b807c9e69349041dad 100644 (file)
@@ -86,4 +86,38 @@ describe('Raw Decoder', function () {
 
         expect(display).to.have.displayed(targetData);
     });
+
+    it('should handle empty rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
+
+    it('should handle empty rects in low colour mode', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [], display, 8);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
 });
index fff1c945faeb1dee4c993452ed0492495338dd0e..15760520378e7cf83a99eec082ef35fe8fcea401 100644 (file)
@@ -81,4 +81,21 @@ describe('RRE Decoder', function () {
 
         expect(display).to.have.displayed(targetData);
     });
+
+    it('should handle empty rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [ 0x00, 0xff, 0xff, 0xff, 0xff ], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
 });
index 10ef971ce9c6a87e8d04f98d8ca24f5e47b6f79b..d89cf57e2d84f28761adf9ffe6ef5768db9cbf64 100644 (file)
@@ -210,6 +210,61 @@ describe('Tight Decoder', function () {
         // Not implemented yet
     });
 
+    it('should handle empty copy rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0, [ 0x00 ], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
+
+    it('should handle empty palette rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0,
+                       [ 0x40, 0x01, 0x01,
+                         0xff, 0xff, 0xff,
+                         0xff, 0xff, 0xff ], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
+
+    it('should handle empty fill rects', function () {
+        display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
+        display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
+        display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
+
+        testDecodeRect(decoder, 1, 2, 0, 0,
+                       [ 0x80, 0xff, 0xff, 0xff ], display, 24);
+
+        let targetData = new Uint8Array([
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
+            0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
+        ]);
+
+        expect(display).to.have.displayed(targetData);
+    });
+
     it('should handle JPEG rects', function (done) {
         let data = [
             // Control bytes