]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Fix crash with too large clipboard data
authorAlex Tanskanen <aleta@cendio.com>
Thu, 20 Feb 2020 15:12:35 +0000 (16:12 +0100)
committerAlex Tanskanen <aleta@cendio.com>
Fri, 21 Feb 2020 08:39:31 +0000 (09:39 +0100)
If too much text is copied in the session, String.fromCharCode.apply()
would crash in Safari on macOS and Chrome on Linux. This commit fixes
this issue by avoiding apply() altogether. Also added test to cover this
issue.

core/rfb.js
tests/test.rfb.js

index 9e6881fdb367e4948b09043afad87c6d9116a9e2..536ea25cd4460b5454713201e9647cd717e8ca25 100644 (file)
@@ -1504,7 +1504,11 @@ export default class RFB extends EventTargetMixin {
                 streamInflator.setInput(null);
 
                 if (textData !== null) {
-                    textData = String.fromCharCode.apply(null, textData);
+                    let tmpText = "";
+                    for (let i = 0; i < textData.length; i++) {
+                        tmpText += String.fromCharCode(textData[i]);
+                    }
+                    textData = tmpText;
 
                     textData = decodeUTF8(textData);
                     if ((textData.length > 0) && "\0" === textData.charAt(textData.length - 1)) {
index bb690cee4656c7eeeb9e936ccbdaf779d2c704a6..41232aee67e26557a0b37799670896c560b1476a 100644 (file)
@@ -2514,6 +2514,38 @@ describe('Remote Frame Buffer Protocol Client', function () {
                         client.removeEventListener("clipboard", spy);
                     });
 
+                    it('should be able to handle large Provide messages', function () {
+                        // repeat() is not supported in IE so a loop is needed instead
+                        let expectedData = "hello";
+                        for (let i = 1; i <= 100000; i++) {
+                            expectedData += "hello";
+                        }
+
+                        let data = [3, 0, 0, 0];
+                        const flags = [0x10, 0x00, 0x00, 0x01];
+
+                        let text = encodeUTF8(expectedData + "\0");
+
+                        let deflatedText = deflateWithSize(text);
+
+                        // How much data we are sending.
+                        push32(data, toUnsigned32bit(-(4 + deflatedText.length)));
+
+                        data = data.concat(flags);
+
+                        let sendData = new Uint8Array(data.length + deflatedText.length);
+                        sendData.set(data);
+                        sendData.set(deflatedText, data.length);
+
+                        const spy = sinon.spy();
+                        client.addEventListener("clipboard", spy);
+
+                        client._sock._websocket._receive_data(sendData);
+                        expect(spy).to.have.been.calledOnce;
+                        expect(spy.args[0][0].detail.text).to.equal(expectedData);
+                        client.removeEventListener("clipboard", spy);
+                    });
+
                 });
 
                 describe('Handle Notify', function () {