msgpack.js icon indicating copy to clipboard operation
msgpack.js copied to clipboard

DataView read wrong value on msgpack deserialized data

Open dukelec opened this issue 4 years ago • 3 comments

The data was send from Python websocket server (type: bytes), and deserialize by your msgpack (version: e33d6aa).

Screenshot_2021-02-01_22-58-13

dukelec avatar Feb 01 '21 14:02 dukelec

I don't see what you really did and what data you have, or even where you call the msgpack code. I'd think that slice(0) is kind of a no-op. Maybe a browser issue? I have no idea what to do here. I can't debug anything without proper details.

ygoe avatar Feb 01 '21 19:02 ygoe

Firefox and Chrome have the same result.

Here is small test demo for you: dbg_msgpack.zip

Screenshot_2021-02-02_11-27-20

Python code snippet of send one message to web page when websocket connected:

async def serve(ws, path):
    try:
        print(f'ws: connect, path: {path}')
        while True:
            dat = b'\x00\x00\x00\x00\x00'
            print(f'send test dat: {dat}')
            msg = umsgpack.packb(dat)
            print(f'msg: {msg}')
            await ws.send(msg)
            break # only send one pkg
    
    except websockets.exceptions.ConnectionClosed:
        print(f'ws: exception, path: {path}')
    
    print(f'ws: disconnect, path: {path}')

Full javascript code:

async function blob2dat(blob) {
    let ret;
    await new Promise(resolve => {
        new Response(blob).arrayBuffer().then(buf => {
            ret = new Uint8Array(buf);
            resolve();
        });
    });
    return ret;
}


function init_ws() {
    let ws_url = `ws://${window.location.hostname}:8910/`;
    let ws = new WebSocket(ws_url);
    
    ws.onopen = async function(evt) {
        console.log("ws onopen");
    }
    ws.onmessage = async function(evt) {
        let msg = await blob2dat(evt.data);
        var dat = msgpack.deserialize(msg);
        console.log("Received dat", dat);
        
        let dv = new DataView(dat.buffer);

        dat2 = dat.slice(0); // dataview return wrong value without this
        let dv2 = new DataView(dat2.buffer);
        
        console.log('ng', dv.getUint32(0, true), dat.slice(0, 4));
        console.log('ok', dv2.getUint32(0, true), dat2.slice(0, 4));

    }
    ws.onerror = function(evt) {
        console.log("ws onerror: ", evt);
        document.body.style.backgroundColor = "gray";
    }
    ws.onclose = function(evt) {
        console.log('ws disconnected');
        document.body.style.backgroundColor = "gray";
    }
}

init_ws();

The number 1476 of the ng output, in hex is 0x05c4, is exactly the data before deserialize.

dukelec avatar Feb 02 '21 03:02 dukelec

Isn't this a bug in DataView? Sorry, I don't know what to do here. After looking up what DataView.getUint32 does, I believe that there should be no difference between the two calls. Please ask elsewhere, I can't help here.

ygoe avatar Feb 14 '21 11:02 ygoe