From fe943395873c6cbfdfa0eadb8a5d13f2c95e8614 Mon Sep 17 00:00:00 2001 From: Bert van Hall Date: Wed, 8 Feb 2017 17:53:58 +0100 Subject: drop autotools Since autotools officially is no longer supported (see various github issues), drop the related infrastructure to stop tempting people to use it for building. Signed-off-by: Bert van Hall --- test/Makefile.am | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 test/Makefile.am (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am deleted file mode 100644 index f07fc82..0000000 --- a/test/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -check_PROGRAMS = - -if HAVE_LIBJPEG -# TurboJPEG wrapper tests -check_PROGRAMS += tjunittest tjbench -tjunittest_SOURCES=tjunittest.c ../common/turbojpeg.c ../common/turbojpeg.h \ - tjutil.c tjutil.h -tjbench_SOURCES=tjbench.c ../common/turbojpeg.c ../common/turbojpeg.h \ - tjutil.c tjutil.h bmp.c bmp.h -tjbench_LDADD=$(LDADD) -lm -endif - -AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/common -LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@ - -if HAVE_LIBPTHREAD -BACKGROUND_TEST=blooptest -ENCODINGS_TEST=encodingstest -endif - -copyrecttest_LDADD=$(LDADD) -lm - -check_PROGRAMS += $(ENCODINGS_TEST) cargstest copyrecttest $(BACKGROUND_TEST) \ - cursortest - -test: encodingstest$(EXEEXT) cargstest$(EXEEXT) copyrecttest$(EXEEXT) - ./encodingstest && ./cargstest - -- cgit v1.2.3 From 90220264f5ca9a6a7852cd133cc4621abb45fcee Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 21 Feb 2017 17:42:26 +0100 Subject: test: tell MSVC to use math defines --- test/copyrecttest.c | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/copyrecttest.c b/test/copyrecttest.c index cd2a504..b3d3ada 100644 --- a/test/copyrecttest.c +++ b/test/copyrecttest.c @@ -2,6 +2,7 @@ #define _BSD_SOURCE #endif #include +#define _USE_MATH_DEFINES #include static void initBackground(rfbScreenInfoPtr server) -- cgit v1.2.3 From f19d6ee225ff35eb54ca06927a921c98ff721adc Mon Sep 17 00:00:00 2001 From: Andreas Weigel Date: Mon, 20 Feb 2017 11:24:18 +0100 Subject: add ws_decode tests modify automake to include ws_decode test add python frame generator for decode tests modify configure to only include ws_decode test if preconditions are fulfilled --- .gitignore | 3 + libvncserver/websockets.c | 22 +----- libvncserver/ws_decode.c | 56 ++++++++----- libvncserver/ws_decode.h | 4 +- test/wsmaketestframe.py | 121 ++++++++++++++++++++++++++++ test/wstest.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 360 insertions(+), 41 deletions(-) create mode 100755 test/wsmaketestframe.py create mode 100644 test/wstest.c (limited to 'test') diff --git a/.gitignore b/.gitignore index fccd7af..a24f81a 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,9 @@ test/cargstest test/copyrecttest test/cursortest test/encodingstest +test/wstest +test/wsmaketestframe.py +test/wstestdata.in /test/tjbench /test/tjunittest vncterm/LinuxVNC diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index 364225b..ab9cabb 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -100,8 +100,7 @@ void webSocketsGenMd5(char * target, char *key1, char *key2, char *key3); static int webSocketsEncodeHybi(rfbClientPtr cl, const char *src, int len, char **dst); -static int ws_read(void *cl, char *buf, int len); -static int ws_peek(void *cl, char *buf, int len); +static int ws_read(void *cl, char *buf, size_t len); static int @@ -345,7 +344,6 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) wsctx->encode = webSocketsEncodeHybi; wsctx->decode = webSocketsDecodeHybi; wsctx->ctxInfo.readFunc = ws_read; - wsctx->ctxInfo.peekFunc = ws_peek; wsctx->base64 = base64; hybiDecodeCleanup(wsctx); cl->wsctx = (wsCtx *)wsctx; @@ -403,7 +401,7 @@ webSocketsGenMd5(char * target, char *key1, char *key2, char *key3) } static int -ws_read(void *ctxPtr, char *buf, int len) +ws_read(void *ctxPtr, char *buf, size_t len) { int n; rfbClientPtr cl = ctxPtr; @@ -415,22 +413,6 @@ ws_read(void *ctxPtr, char *buf, int len) return n; } -static int -ws_peek(void *ctxPtr, char *buf, int len) -{ - int n; - rfbClientPtr cl = ctxPtr; - if (cl->sslctx) { - n = rfbssl_peek(cl, buf, len); - } else { - while (-1 == (n = recv(cl->sock, buf, len, MSG_PEEK))) { - if (errno != EAGAIN) - break; - } - } - return n; -} - static int webSocketsEncodeHybi(rfbClientPtr cl, const char *src, int len, char **dst) { diff --git a/libvncserver/ws_decode.c b/libvncserver/ws_decode.c index e74a33c..3bd17f4 100644 --- a/libvncserver/ws_decode.c +++ b/libvncserver/ws_decode.c @@ -1,11 +1,12 @@ #include "ws_decode.h" -#include #include #include #define WS_HYBI_MASK_LEN 4 - +#define WS_HYBI_HEADER_LEN_SHORT 2 + WS_HYBI_MASK_LEN +#define WS_HYBI_HEADER_LEN_EXTENDED 4 + WS_HYBI_MASK_LEN +#define WS_HYBI_HEADER_LEN_LONG 10 + WS_HYBI_MASK_LEN static int hybiRemaining(ws_ctx_t *wsctx) @@ -66,8 +67,12 @@ hybiReturnData(char *dst, int len, ws_ctx_t *wsctx, int *nWritten) } } rfbLog("after copy: readPos=%p, readLen=%d\n", wsctx->readPos, wsctx->readlen); - } else if (wsctx->hybiDecodeState == WS_HYBI_STATE_CLOSE_REASON_PENDING) { - nextState = WS_HYBI_STATE_CLOSE_REASON_PENDING; + } else { + /* it may happen that we read some bytes but could not decode them, + * in that case, set errno to EAGAIN and return -1 */ + nextState = wsctx->hybiDecodeState; + errno = EAGAIN; + *nWritten = -1; } return nextState; } @@ -98,7 +103,7 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet) if (-1 == ret) { /* save errno because rfbErr() will tamper it */ int olderrno = errno; - rfbErr("%s: peek; %m\n", __func__); + rfbErr("%s: read; %s\n", __func__, strerror(errno)); errno = olderrno; *sockRet = -1; } else { @@ -131,22 +136,22 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet) * close the connection upon receiving a frame with the MASK bit set to 0. **/ if (!(wsctx->header.data->b1 & 0x80)) { - rfbErr("%s: got frame without mask ret=%d\n", __func__, ret); - syslog(LOG_ERR, "%s: got frame without mask; ret=%d\n", __func__, ret); - errno = EIO; + rfbErr("%s: got frame without mask; ret=%d\n", __func__, ret); + errno = EPROTO; *sockRet = -1; return WS_HYBI_STATE_ERR; } + if (wsctx->header.payloadLen < 126 && wsctx->nReadRaw >= 6) { - wsctx->header.headerLen = 2 + WS_HYBI_MASK_LEN; + wsctx->header.headerLen = WS_HYBI_HEADER_LEN_SHORT; wsctx->header.mask = wsctx->header.data->u.m; } else if (wsctx->header.payloadLen == 126 && 8 <= wsctx->nReadRaw) { - wsctx->header.headerLen = 4 + WS_HYBI_MASK_LEN; + wsctx->header.headerLen = WS_HYBI_HEADER_LEN_EXTENDED; wsctx->header.payloadLen = WS_NTOH16(wsctx->header.data->u.s16.l16); wsctx->header.mask = wsctx->header.data->u.s16.m16; } else if (wsctx->header.payloadLen == 127 && 14 <= wsctx->nReadRaw) { - wsctx->header.headerLen = 10 + WS_HYBI_MASK_LEN; + wsctx->header.headerLen = WS_HYBI_HEADER_LEN_LONG; wsctx->header.payloadLen = WS_NTOH64(wsctx->header.data->u.s64.l64); wsctx->header.mask = wsctx->header.data->u.s64.m64; } else { @@ -157,6 +162,19 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet) return WS_HYBI_STATE_HEADER_PENDING; } + /* while RFC 6455 mandates that lengths MUST be encoded with the minimum + * number of bytes, it does not specify for the server how to react on + * 'wrongly' encoded frames --- this implementation rejects them*/ + if ((wsctx->header.headerLen > WS_HYBI_HEADER_LEN_SHORT + && wsctx->header.payloadLen < 126) + || (wsctx->header.headerLen > WS_HYBI_HEADER_LEN_EXTENDED + && wsctx->header.payloadLen < 65536)) { + rfbErr("%s: invalid length field; headerLen=%d payloadLen=%llu\n", __func__, wsctx->header.headerLen, wsctx->header.payloadLen); + errno = EPROTO; + *sockRet = -1; + return WS_HYBI_STATE_ERR; + } + /* absolute length of frame */ wsctx->nToRead = wsctx->header.headerLen + wsctx->header.payloadLen; @@ -238,7 +256,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) //if (-1 == (n = ws_read(cl, wsctx->writePos, nextRead))) { if (-1 == (n = wsctx->ctxInfo.readFunc(wsctx->ctxInfo.ctxPtr, wsctx->writePos, nextRead))) { int olderrno = errno; - rfbErr("%s: read; %m", __func__); + rfbErr("%s: read; %s", __func__, strerror(errno)); errno = olderrno; *sockRet = -1; return WS_HYBI_STATE_ERR; @@ -260,6 +278,8 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) errno=EIO; *sockRet = -1; return WS_HYBI_STATE_ERR; + } else { + wsctx->hybiDecodeState = WS_HYBI_STATE_FRAME_COMPLETE; } } @@ -294,7 +314,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) /* carry over remaining, non-multiple-of-four bytes */ wsctx->carrylen = toDecode - (i * 4); if (wsctx->carrylen < 0 || wsctx->carrylen > ARRAYSIZE(wsctx->carryBuf)) { - syslog(LOG_ERR, "%s: internal error, invalid carry over size: carrylen=%d, toDecode=%d, i=%d", __func__, wsctx->carrylen, toDecode, i); + rfbErr("%s: internal error, invalid carry over size: carrylen=%d, toDecode=%d, i=%d", __func__, wsctx->carrylen, toDecode, i); *sockRet = -1; errno = EIO; return WS_HYBI_STATE_ERR; @@ -310,7 +330,6 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) /* this data is not returned as payload data */ if (hybiWsFrameComplete(wsctx)) { - rfbLog("got closure, reason %d\n", WS_NTOH16(((uint16_t *)data)[0])); rfbLog("got close cmd, reason %d\n", WS_NTOH16(((uint16_t *)data)[0])); errno = ECONNRESET; *sockRet = -1; @@ -326,8 +345,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) data[toReturn] = '\0'; rfbLog("Initiate Base64 decoding in %p with max size %d and '\\0' at %p\n", data, bufsize, data + toReturn); if (-1 == (wsctx->readlen = b64_pton((char *)data, data, bufsize))) { - syslog(LOG_ERR, "Base64 decode error in %s; data=%p bufsize=%d", __func__, data, bufsize); - rfbErr("%s: Base64 decode error; %m\n", __func__); + rfbErr("%s: Base64 decode error; %s\n", __func__, strerror(errno)); } wsctx->writePos = hybiPayloadStart(wsctx); break; @@ -437,12 +455,14 @@ spor: "writePos=%p " "state=%d toRead=%d remaining=%d " "nRead=%d carrylen=%d carryBuf=%p " - "result=%d\n", + "result=%d " + "errno=%d\n", __func__, len, wsctx->readlen, wsctx->readPos, wsctx->writePos, wsctx->hybiDecodeState, wsctx->nToRead, hybiRemaining(wsctx), wsctx->nReadRaw, wsctx->carrylen, wsctx->carryBuf, - result); + result, + errno); return result; } diff --git a/libvncserver/ws_decode.h b/libvncserver/ws_decode.h index e75c4d1..fac3c68 100644 --- a/libvncserver/ws_decode.h +++ b/libvncserver/ws_decode.h @@ -50,13 +50,11 @@ typedef struct ws_ctx_s ws_ctx_t; typedef int (*wsEncodeFunc)(rfbClientPtr cl, const char *src, int len, char **dst); typedef int (*wsDecodeFunc)(ws_ctx_t *wsctx, char *dst, int len); -typedef int (*wsReadFunc)(void *ctx, char *dst, int len); -typedef int (*wsPeekFunc)(void *ctx, char *dst, int len); +typedef int (*wsReadFunc)(void *ctx, char *dst, size_t len); typedef struct ctxInfo_s{ void *ctxPtr; wsReadFunc readFunc; - wsPeekFunc peekFunc; } ctxInfo_t; enum { diff --git a/test/wsmaketestframe.py b/test/wsmaketestframe.py new file mode 100755 index 0000000..d0053a2 --- /dev/null +++ b/test/wsmaketestframe.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# Copyright (C)2017 Andreas Weigel. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import websockets +import base64 +import errno + +def add_field(s, name, value, first=False): + deli = ",\n\t\t" + if first: + deli = "\t\t" + s += "{2}.{0}={1}".format(name, value, deli) + return s + + +class Testframe(): + def __init__(self, frame, descr, retbytes=[], modify_bytes={}, experrno=0, mask=True): + self.frame = frame + self.descr = descr + self.retbytes = retbytes + self.modify_bytes = modify_bytes + self.experrno = experrno + self.b64 = True if frame.opcode == 1 else False + self.mask = mask + + def to_carray_initializer(self, buf): + values = [] + for i in range(len(buf)): + values.append("0X{0:02X}".format(buf[i])) + + if self.modify_bytes != {}: + for k in self.modify_bytes: + values[k] = "0X{0:02X}".format(self.modify_bytes[k]) + + return "{{{0}}}".format(", ".join(values)) + + + def set_frame_buf(self, buf): + self.frame_carray = self.to_carray_initializer(buf) + self.framelen = len(buf) + + def __str__(self): + #print("processing frame: {0}".format(self.descr)) + the_frame = self.frame + if self.b64: + olddata = self.frame.data + newdata = base64.b64encode(self.frame.data) + #print("converting\n{0}\nto{1}\n".format(olddata, newdata)) + the_frame = websockets.framing.Frame(self.frame.fin, self.frame.opcode, base64.b64encode(olddata)) + + websockets.framing.write_frame(the_frame, self.set_frame_buf, self.mask) + s = "\t{\n" + s = add_field(s, "frame", "{0}".format(self.frame_carray), True) + s = add_field(s, "expectedDecodeBuf", self.to_carray_initializer(self.frame.data)) + s = add_field(s, "frame_len", self.framelen) + s = add_field(s, "raw_payload_len", len(self.frame.data)) + s = add_field(s, "expected_errno", self.experrno) + s = add_field(s, "descr", "\"{0}\"".format(self.descr)) + s = add_field(s, "ret_bytes", "{{{0}}}".format(", ".join(self.retbytes))) + s = add_field(s, "ret_bytes_len", len(self.retbytes)) + s = add_field(s, "i", "0") + s = add_field(s, "simulate_sock_malfunction_at", "0") + s = add_field(s, "errno_val", "0") + s = add_field(s, "close_sock_at", "0") + s += "\n\t}" + return s + +### create test frames +flist = [] +### standard text frames with different lengths +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Short valid text frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Frame2 does contain much more text and even goes beyond the 126 byte len field. Frame2 does contain much more text and even goes beyond the 126 byte len field.", encoding="utf-8")), + "Mid-long valid text frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray([(x % 26) + 65 for x in range(100000)])), "100k text frame (ABC..YZABC..)", {})) + +### standard binary frames with different lengths +flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Testit", encoding="utf-8")), "Short valid binary frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Frame2 does contain much more text and even goes beyond the 126 byte len field. Frame2 does contain much more text and even goes beyond the 126 byte len field.", encoding="utf-8")), + "Mid-long valid binary frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray([(x % 26) + 65 for x in range(100000)])), "100k binary frame (ABC..YZABC..)", {})) + +### some conn reset frames, one with no close message, one with close message (the latter should cause an error) +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB]))), "Close frame (Reason 1003)", {}, experrno=errno.ECONNRESET)) +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB])) + bytearray("I'm a close reason", encoding="utf-8")), "Close frame (Reason 1003) and msg", {}, experrno=errno.EIO)) + +### invalid header values +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", {}, experrno=errno.EPROTO, mask=False)) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", {}, experrno=errno.EPROTO, modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", {}, experrno=errno.EPROTO, modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) + +s = "struct ws_frame_test tests[] = {\n" +for i in range(len(flist)): + s += flist[i].__str__() + if (i + 1 < len(flist)): + s += "," + s += "\n" +s += "};\n" + +with open("wstestdata.in", "w") as cdatafile: + cdatafile.write(s) diff --git a/test/wstest.c b/test/wstest.c new file mode 100644 index 0000000..30324cb --- /dev/null +++ b/test/wstest.c @@ -0,0 +1,195 @@ +/* + * Copyright (C)2017 Andreas Weigel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 + +#define TEST_BUF_SIZE B64LEN(131072) + WSHLENMAX +#define RND_SEED 100 +#define WS_TMP_LOG "ws_tmp.log" + +enum { + OK, + FAIL_DATA, + FAIL_ERRNO, + FAIL_CLOSED, +}; + +const char *result_descr[] = { + "", + "Data buffers do not match", + "Wrong errno", + "Wrongly reported closed socket", + "Internal test error" +}; + +struct ws_frame_test { + char frame[TEST_BUF_SIZE]; + char *pos; + char expectedDecodeBuf[TEST_BUF_SIZE]; + uint64_t frame_len; + uint64_t raw_payload_len; + int expected_errno; + const char *descr; + int ret_bytes[16]; + int ret_bytes_len; + int i; + int simulate_sock_malfunction_at; + int errno_val; + int close_sock_at; +}; + +char el_log[1000000]; +char *el_pos; + +static void logtest(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + size_t left = el_log + sizeof(el_log) - el_pos; + size_t off = vsnprintf(el_pos, left, fmt, args); + el_pos += off; + va_end(args); +} + +static int emu_read(void *ctx, char *dst, size_t len); + +static int emu_read(void *ctx, char *dst, size_t len) +{ + struct ws_frame_test *ft = (struct ws_frame_test *)ctx; + ssize_t nret; + int r; + ssize_t modu; + + rfbLog("emu_read called with dst=%p and len=%lu\n", dst, len); + if (ft->simulate_sock_malfunction_at > 0 && ft->simulate_sock_malfunction_at == ft->i) { + rfbLog("simulating IO error with errno=%d\n", ft->errno_val); + errno = ft->errno_val; + return -1; + } + + /* return something */ + r = rand(); + modu = (ft->frame + ft->frame_len) - ft->pos; + rfbLog("r=%d modu=%ld frame=%p pos=%p\n", r, modu, ft->frame, ft->pos); + nret = (r % modu) + 1; + nret = nret > len ? len : nret; + + rfbLog("copy and return %ld bytes\n", nret); + memcpy(dst, ft->pos, nret); + ft->pos += nret; + rfbLog("leaving %s; pos=%p framebuf=%p nret=%ld\n", __func__, ft->pos, ft->frame, nret); + return nret; +} + +static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx) +{ + uint64_t nleft = ft->raw_payload_len; + char dstbuf[ft->raw_payload_len]; + char *dst = dstbuf; + ssize_t n; + + ft->pos = ft->frame; + + ctx->ctxInfo.ctxPtr = (void *)ft; + + while (nleft > 0) { + rfbLog("calling ws_decode with dst=%p, len=%lu\n", dst, nleft); + n = ctx->decode(ctx, dst, nleft); + rfbLog("read n=%ld\n", n); + if (n == 0) { + if (ft->close_sock_at > 0) { + return OK; + } else { + return FAIL_CLOSED; + } + } else if (n < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* ok, just call again */ + } else { + if (ft->expected_errno == errno) { + rfbLog("errno=%d as expected\n", errno); + return OK; + } else { + rfbLog("errno=%d != expected(%d)\n", errno, ft->expected_errno); + return FAIL_ERRNO; + } + } + } else { + nleft -= n; + dst += n; + rfbLog("read n=%ld from decode; dst=%p, nleft=%lu\n", n, dst, nleft); + } + } + + if (memcmp(ft->expectedDecodeBuf, dstbuf, ft->raw_payload_len) != 0) { + ft->expectedDecodeBuf[ft->raw_payload_len] = '\0'; + dstbuf[ft->raw_payload_len] = '\0'; + rfbLog("decoded result not equal:\nexpected:\n%s\ngot\n%s\n\n", ft->expectedDecodeBuf, dstbuf); + return FAIL_DATA; + } + + return OK; +} + +#include "wstestdata.in" + +int main() +{ + ws_ctx_t ctx; + int retall= 0; + srand(RND_SEED); + + for (int i = 0; i < ARRAYSIZE(tests); i++) { + int ret; + + el_pos = el_log; + rfbLog = logtest; + rfbErr = logtest; + + hybiDecodeCleanup(&ctx); + ctx.decode = webSocketsDecodeHybi; + ctx.version = WEBSOCKETS_VERSION_HYBI; + + ctx.ctxInfo.readFunc = emu_read; + + ret = run_test(&tests[i], &ctx); + printf("%s: \"%s\"\n", ret == 0 ? "PASS" : "FAIL", tests[i].descr); + if (ret != 0) { + *el_pos = '\0'; + printf("%s", el_log); + retall = -1; + } + } + return retall; +} + +#endif -- cgit v1.2.3 From 826e0f9e39a49ae3598f8709218180f835af269b Mon Sep 17 00:00:00 2001 From: Andreas Weigel Date: Mon, 20 Feb 2017 15:13:03 +0100 Subject: add generation wstest to cmake add wstestdata.c, because the python data generation script has too many dependencies remove some redundance from jpeg test creation add support for decoding close messages --- .gitignore | 2 - CMakeLists.txt | 41 +++++++++++++----- libvncserver/ws_decode.c | 44 +++++++++++-------- libvncserver/ws_decode.h | 7 --- test/wsmaketestframe.py | 44 ++++++++++--------- test/wstest.c | 23 +++++++--- test/wstestdata.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 207 insertions(+), 64 deletions(-) create mode 100644 test/wstestdata.c (limited to 'test') diff --git a/.gitignore b/.gitignore index a24f81a..03bdf0f 100644 --- a/.gitignore +++ b/.gitignore @@ -67,8 +67,6 @@ test/copyrecttest test/cursortest test/encodingstest test/wstest -test/wsmaketestframe.py -test/wstestdata.in /test/tjbench /test/tjunittest vncterm/LinuxVNC diff --git a/CMakeLists.txt b/CMakeLists.txt index cf6017d..8c6da06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ option(WITH_IPv6 "Enable IPv6 Support" ON) option(WITH_WEBSOCKETS "Build with websockets support" ON) - if(WITH_ZLIB) find_package(ZLIB) endif(WITH_ZLIB) @@ -387,6 +386,7 @@ if(LIBVNCSERVER_WITH_WEBSOCKETS) set(LIBVNCSERVER_SOURCES ${LIBVNCSERVER_SOURCES} ${LIBVNCSERVER_DIR}/websockets.c + ${LIBVNCSERVER_DIR}/ws_decode.c ${WSSRCS} ) endif(LIBVNCSERVER_WITH_WEBSOCKETS) @@ -500,11 +500,9 @@ foreach(e ${LIBVNCCLIENT_EXAMPLES}) target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL_LIBRARY} ${FFMPEG_LIBRARIES}) endforeach(e ${LIBVNCCLIENT_EXAMPLES}) - # # them tests # - if(UNIX) set(ADDITIONAL_TEST_LIBS m) endif(UNIX) @@ -512,18 +510,41 @@ endif(UNIX) set(SIMPLETESTS cargstest copyrecttest + wstest ) -if(CMAKE_USE_PTHREADS_INIT) - set(SIMPLETESTS - ${SIMPLETESTS} - encodingstest +add_test(NAME cargs COMMAND test_cargstest) +add_test(NAME websockets_decode COMMAND test_wstest) + +if(CMAKE_USE_PTHREADS_INI) + list(APPEND SIMPLETESTS encodingstest) +endif(CMAKE_USE_PTHREADS_INI) + +if(FOUND_LIBJPEG_TURBO) + list(APPEND SIMPLETESTS tjunittest tjbench) + set(tjunittest_add_src + ${TESTS_DIR}/tjutil.c + ${TESTS_DIR}/tjutil.h + ${COMMON_DIR}/turbojpeg.c + ${COMMON_DIR}/turbojpeg.h ) -endif(CMAKE_USE_PTHREADS_INIT) + + set(tjbench_add_src + ${TESTS_DIR}/tjbench.c + ${TESTS_DIR}/tjutil.c + ${TESTS_DIR}/tjutil.h + ${TESTS_DIR}/bmp.c + ${TESTS_DIR}/bmp.h + ${COMMON_DIR}/turbojpeg.c + ${COMMON_DIR}/turbojpeg.h + ) + + add_test(NAME turbojpeg COMMAND test_tjunittest) +endif(FOUND_LIBJPEG_TURBO) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test) foreach(t ${SIMPLETESTS}) - add_executable(test_${t} ${TESTS_DIR}/${t}.c) + add_executable(test_${t} ${TESTS_DIR}/${t}.c ${${t}_add_src}) set_target_properties(test_${t} PROPERTIES OUTPUT_NAME ${t}) set_target_properties(test_${t} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test) target_link_libraries(test_${t} vncserver vncclient ${ADDITIONAL_TEST_LIBS}) @@ -561,8 +582,6 @@ if(FOUND_LIBJPEG_TURBO) add_test(NAME turbojpeg COMMAND test_tjunittest) endif(FOUND_LIBJPEG_TURBO) - - # # this gets the libraries needed by TARGET in "-libx -liby ..." form # diff --git a/libvncserver/ws_decode.c b/libvncserver/ws_decode.c index 3bd17f4..472a44a 100644 --- a/libvncserver/ws_decode.c +++ b/libvncserver/ws_decode.c @@ -85,11 +85,12 @@ hybiReturnData(char *dst, int len, ws_ctx_t *wsctx, int *nWritten) * * @param[in] cl client ptr with ptr to raw socket and ws_ctx_t ptr * @param[out] sockRet emulated recv return value + * @param[out] nPayload number of payload bytes already read * @return next hybi decoding state; WS_HYBI_STATE_HEADER_PENDING indicates * that the header was not received completely. */ static int -hybiReadHeader(ws_ctx_t *wsctx, int *sockRet) +hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) { int ret; char *headerDst = wsctx->codeBufDecode + wsctx->nReadRaw; @@ -184,7 +185,8 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet) /* set payload pointer just after header */ wsctx->readPos = (unsigned char *)(wsctx->codeBufDecode + wsctx->header.headerLen); - rfbLog("header complete: state=%d flen=%d writeTo=%p\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos); + *nPayload = wsctx->nReadRaw - wsctx->header.headerLen; + rfbLog("header complete: state=%d flen=%d writeTo=%p nPayload=%d\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos, *nPayload); return WS_HYBI_STATE_DATA_NEEDED; } @@ -217,21 +219,24 @@ hybiPayloadStart(ws_ctx_t *wsctx) * - execute return data routine * * Sets errno corresponding to what it gets from the underlying - * socket or EIO if some internal sanity check fails. + * socket or EPROTO if some invalid data is in the received frame + * or ECONNRESET if a close reason + message is received. EIO is used if + * an internal sanity check fails. * * @param[in] cl client ptr with raw socket reference * @param[out] dst destination buffer * @param[in] len size of destination buffer * @param[out] sockRet emulated recv return value + * @param[in] nInBuf number of undecoded bytes before writePos from header read * @return next hybi decode state */ static int -hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) +hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet, int nInBuf) { int n; int i; - int toReturn; - int toDecode; + int toReturn; /* number of data bytes to return */ + int toDecode; /* number of bytes to decode starting at wsctx->writePos */ int bufsize; int nextRead; unsigned char *data; @@ -253,7 +258,6 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) if (wsctx->nReadRaw < wsctx->nToRead) { /* decode more data */ - //if (-1 == (n = ws_read(cl, wsctx->writePos, nextRead))) { if (-1 == (n = wsctx->ctxInfo.readFunc(wsctx->ctxInfo.ctxPtr, wsctx->writePos, nextRead))) { int olderrno = errno; rfbErr("%s: read; %s", __func__, strerror(errno)); @@ -283,7 +287,9 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) } } - toDecode = wsctx->writePos - hybiPayloadStart(wsctx); + /* number of not yet unmasked payload bytes: what we read here + what was + * carried over + what was read with the header */ + toDecode = n + wsctx->carrylen + nInBuf; rfbLog("toDecode=%d from n=%d carrylen=%d headerLen=%d\n", toDecode, n, wsctx->carrylen, wsctx->header.headerLen); if (toDecode < 0) { rfbErr("%s: internal error; negative number of bytes to decode: %d", __func__, toDecode); @@ -294,7 +300,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) /* for a possible base64 decoding, we decode multiples of 4 bytes until * the whole frame is received and carry over any remaining bytes in the carry buf*/ - data = (unsigned char *)hybiPayloadStart(wsctx); + data = (unsigned char *)(wsctx->writePos - toDecode); data32= (uint32_t *)data; for (i = 0; i < (toDecode >> 2); i++) { @@ -321,24 +327,25 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet) } rfbLog("carrying over %d bytes from %p to %p\n", wsctx->carrylen, wsctx->writePos + (i * 4), wsctx->carryBuf); memcpy(wsctx->carryBuf, data + (i * 4), wsctx->carrylen); + wsctx->writePos -= wsctx->carrylen; } toReturn = toDecode - wsctx->carrylen; switch (wsctx->header.opcode) { case WS_OPCODE_CLOSE: - /* this data is not returned as payload data */ if (hybiWsFrameComplete(wsctx)) { - rfbLog("got close cmd, reason %d\n", WS_NTOH16(((uint16_t *)data)[0])); + *(wsctx->writePos) = '\0'; + rfbLog("got close cmd %d, reason %d: %s\n", (int)(wsctx->writePos - hybiPayloadStart(wsctx)), WS_NTOH16(((uint16_t *)hybiPayloadStart(wsctx))[0]), &hybiPayloadStart(wsctx)[2]); errno = ECONNRESET; *sockRet = -1; return WS_HYBI_STATE_FRAME_COMPLETE; } else { - rfbErr("%s: close reason with long frame not supported", __func__); - errno = EIO; + rfbLog("got close cmd; waiting for %d more bytes to arrive\n", hybiRemaining(wsctx)); *sockRet = -1; - return WS_HYBI_STATE_ERR; + errno = EAGAIN; + return WS_HYBI_STATE_CLOSE_REASON_PENDING; } break; case WS_OPCODE_TEXT_FRAME: @@ -412,25 +419,26 @@ webSocketsDecodeHybi(ws_ctx_t *wsctx, char *dst, int len) wsctx->nReadRaw, wsctx->carrylen, wsctx->carryBuf); switch (wsctx->hybiDecodeState){ + int nInBuf; case WS_HYBI_STATE_HEADER_PENDING: - wsctx->hybiDecodeState = hybiReadHeader(wsctx, &result); + wsctx->hybiDecodeState = hybiReadHeader(wsctx, &result, &nInBuf); if (wsctx->hybiDecodeState == WS_HYBI_STATE_ERR) { goto spor; } if (wsctx->hybiDecodeState != WS_HYBI_STATE_HEADER_PENDING) { /* when header is complete, try to read some more data */ - wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result); + wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result, nInBuf); } break; case WS_HYBI_STATE_DATA_AVAILABLE: wsctx->hybiDecodeState = hybiReturnData(dst, len, wsctx, &result); break; case WS_HYBI_STATE_DATA_NEEDED: - wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result); + wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result, 0); break; case WS_HYBI_STATE_CLOSE_REASON_PENDING: - wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result); + wsctx->hybiDecodeState = hybiReadAndDecode(wsctx, dst, len, &result, 0); break; default: /* invalid state */ diff --git a/libvncserver/ws_decode.h b/libvncserver/ws_decode.h index fac3c68..0dcbc83 100644 --- a/libvncserver/ws_decode.h +++ b/libvncserver/ws_decode.h @@ -7,13 +7,6 @@ #include /* __b64_ntop */ #endif - - -enum { - WEBSOCKETS_VERSION_HIXIE, - WEBSOCKETS_VERSION_HYBI -}; - #if defined(__APPLE__) #include diff --git a/test/wsmaketestframe.py b/test/wsmaketestframe.py index d0053a2..3412754 100755 --- a/test/wsmaketestframe.py +++ b/test/wsmaketestframe.py @@ -26,6 +26,14 @@ import websockets import base64 import errno +''' + Create websocket frames for the wstest websocket decoding unit test. + + Generates c ws_frame_test structure definitions + included by wstest.c. +''' + + def add_field(s, name, value, first=False): deli = ",\n\t\t" if first: @@ -35,10 +43,9 @@ def add_field(s, name, value, first=False): class Testframe(): - def __init__(self, frame, descr, retbytes=[], modify_bytes={}, experrno=0, mask=True): + def __init__(self, frame, descr, modify_bytes={}, experrno=0, mask=True): self.frame = frame self.descr = descr - self.retbytes = retbytes self.modify_bytes = modify_bytes self.experrno = experrno self.b64 = True if frame.opcode == 1 else False @@ -53,7 +60,7 @@ class Testframe(): for k in self.modify_bytes: values[k] = "0X{0:02X}".format(self.modify_bytes[k]) - return "{{{0}}}".format(", ".join(values)) + return "{{{0}}}".format(",".join(values)) def set_frame_buf(self, buf): @@ -61,14 +68,13 @@ class Testframe(): self.framelen = len(buf) def __str__(self): - #print("processing frame: {0}".format(self.descr)) + print("processing frame: {0}".format(self.descr)) the_frame = self.frame if self.b64: olddata = self.frame.data newdata = base64.b64encode(self.frame.data) #print("converting\n{0}\nto{1}\n".format(olddata, newdata)) the_frame = websockets.framing.Frame(self.frame.fin, self.frame.opcode, base64.b64encode(olddata)) - websockets.framing.write_frame(the_frame, self.set_frame_buf, self.mask) s = "\t{\n" s = add_field(s, "frame", "{0}".format(self.frame_carray), True) @@ -77,8 +83,6 @@ class Testframe(): s = add_field(s, "raw_payload_len", len(self.frame.data)) s = add_field(s, "expected_errno", self.experrno) s = add_field(s, "descr", "\"{0}\"".format(self.descr)) - s = add_field(s, "ret_bytes", "{{{0}}}".format(", ".join(self.retbytes))) - s = add_field(s, "ret_bytes_len", len(self.retbytes)) s = add_field(s, "i", "0") s = add_field(s, "simulate_sock_malfunction_at", "0") s = add_field(s, "errno_val", "0") @@ -89,25 +93,25 @@ class Testframe(): ### create test frames flist = [] ### standard text frames with different lengths -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Short valid text frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Short valid text frame")) flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Frame2 does contain much more text and even goes beyond the 126 byte len field. Frame2 does contain much more text and even goes beyond the 126 byte len field.", encoding="utf-8")), - "Mid-long valid text frame", {})) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray([(x % 26) + 65 for x in range(100000)])), "100k text frame (ABC..YZABC..)", {})) + "Mid-long valid text frame")) +#flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray([(x % 26) + 65 for x in range(100000)])), "100k text frame (ABC..YZABC..)")) ### standard binary frames with different lengths -flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Testit", encoding="utf-8")), "Short valid binary frame", {})) +flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Testit", encoding="utf-8")), "Short valid binary frame")) flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Frame2 does contain much more text and even goes beyond the 126 byte len field. Frame2 does contain much more text and even goes beyond the 126 byte len field.", encoding="utf-8")), - "Mid-long valid binary frame", {})) -flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray([(x % 26) + 65 for x in range(100000)])), "100k binary frame (ABC..YZABC..)", {})) + "Mid-long valid binary frame")) +#flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray([(x % 26) + 65 for x in range(100000)])), "100k binary frame (ABC..YZABC..)")) -### some conn reset frames, one with no close message, one with close message (the latter should cause an error) -flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB]))), "Close frame (Reason 1003)", {}, experrno=errno.ECONNRESET)) -flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB])) + bytearray("I'm a close reason", encoding="utf-8")), "Close frame (Reason 1003) and msg", {}, experrno=errno.EIO)) +### some conn reset frames, one with no close message, one with close message +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB]))), "Close frame (Reason 1003)", experrno=errno.ECONNRESET)) +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB])) + bytearray("I'm a close reason and much more than that!", encoding="utf-8")), "Close frame (Reason 1003) and msg", experrno=errno.ECONNRESET)) ### invalid header values -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", {}, experrno=errno.EPROTO, mask=False)) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", {}, experrno=errno.EPROTO, modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", {}, experrno=errno.EPROTO, modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", experrno=errno.EPROTO, mask=False)) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", experrno=errno.EPROTO, modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno=errno.EPROTO, modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) s = "struct ws_frame_test tests[] = {\n" for i in range(len(flist)): @@ -117,5 +121,5 @@ for i in range(len(flist)): s += "\n" s += "};\n" -with open("wstestdata.in", "w") as cdatafile: +with open("wstestdata.c", "w") as cdatafile: cdatafile.write(s) diff --git a/test/wstest.c b/test/wstest.c index 30324cb..4a5ba91 100644 --- a/test/wstest.c +++ b/test/wstest.c @@ -23,6 +23,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef _WIN32 + #include #include #include @@ -30,11 +32,11 @@ #include #include -#ifndef _WIN32 - +/* incoming data frames should not be larger than that */ #define TEST_BUF_SIZE B64LEN(131072) + WSHLENMAX + +/* seed is fixed deliberately to get reproducible test cases */ #define RND_SEED 100 -#define WS_TMP_LOG "ws_tmp.log" enum { OK, @@ -55,6 +57,7 @@ struct ws_frame_test { char frame[TEST_BUF_SIZE]; char *pos; char expectedDecodeBuf[TEST_BUF_SIZE]; + uint64_t n_compare; uint64_t frame_len; uint64_t raw_payload_len; int expected_errno; @@ -67,6 +70,8 @@ struct ws_frame_test { int close_sock_at; }; +#include "wstestdata.c" + char el_log[1000000]; char *el_pos; @@ -160,15 +165,15 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx) return OK; } -#include "wstestdata.in" int main() { ws_ctx_t ctx; - int retall= 0; + int retall= 0; + int i; srand(RND_SEED); - for (int i = 0; i < ARRAYSIZE(tests); i++) { + for (i = 0; i < ARRAYSIZE(tests); i++) { int ret; el_pos = el_log; @@ -192,4 +197,10 @@ int main() return retall; } +#else + +int main() { + return 0; +} + #endif diff --git a/test/wstestdata.c b/test/wstestdata.c new file mode 100644 index 0000000..628bdb1 --- /dev/null +++ b/test/wstestdata.c @@ -0,0 +1,110 @@ +struct ws_frame_test tests[] = { + { + .frame={0X81,0X88,0XB7,0XDB,0X16,0X16,0XE1,0X9C,0X40,0X6C,0XD3,0X9C,0X7A,0X26}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=14, + .raw_payload_len=6, + .expected_errno=0, + .descr="Short valid text frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFE,0X00,0XD4,0X67,0XFE,0X8A,0X31,0X35,0X90,0XC0,0X59,0X05,0XA9,0XDF,0X48,0X2E,0XB9,0XD8,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0XCC,0XB3,0X44,0X03,0XB9,0XCC,0X41,0X05,0X97,0XC8,0X45,0X03,0XA9,0XC4,0X5E,0X2E,0XB9,0XBB,0X47,0X04,0X93,0XDF,0X56,0X03,0XB9,0XDC,0X05,0X03,0XBD,0XC8,0X59,0X05,0X93,0XDB,0X56,0X3D,0XA6,0XD0,0X5D,0X05,0X97,0XC8,0X5F,0X05,0XCC,0XDC,0X4B,0X2E,0XB9,0XC0,0X5D,0X02,0XA9,0XB3,0X44,0X3D,0XBD,0XC8,0X01,0X06,0XB9,0XDF,0X56,0X2A,0XAA,0XC3,0X03,0X2E,0XB9,0XC0,0X04,0X03,0XB9,0XDF,0X56,0X05,0XB9,0XDC,0X44,0X2E,0XB9,0XD0,0X41,0X3D,0XA9,0XF2,0X5A,0X2B,0X97,0XC8,0X76,0X04,0X93,0XCC,0X45,0X3D,0XAA,0XC3,0X56,0X3D,0XB9,0XB3,0X5D,0X04,0X87,0XC8,0X5B,0X05,0XCC,0XBF,0X01,0X3E,0XA9,0XE6,0X44,0X2E,0XB9,0XBB,0X00,0X3E,0XCC,0XED,0X56,0X05,0XA9,0XB3,0X48,0X3D,0XAD,0XC8,0X01,0X3D,0XA6,0XE2,0X01,0X2E,0XB9,0XCC,0X44,0X3D,0XBD,0XC8,0X5D,0X03,0X93,0XDC,0X44,0X2E,0XB9,0XEE,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0X93,0XDC,0X04,0X05,0XCC,0XBF,0X5A,0X2E,0XB6,0XD8,0X5E,0X3D,0XAD,0XCB,0X49,0X2A,0X94,0XD3,0X56,0X3E,0X90,0XE6,0X01,0X3D,0XAD,0XC8,0X42,0X3D,0XA9,0XBE,0X56,0X3D,0X93,0XE6,0X5D,0X05,0XB9,0XDB,0X44}, + .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, + .frame_len=220, + .raw_payload_len=159, + .expected_errno=0, + .descr="Mid-long valid text frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X82,0X86,0X90,0X5E,0X2B,0X8E,0XC4,0X3B,0X58,0XFA,0XF9,0X2A}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=12, + .raw_payload_len=6, + .expected_errno=0, + .descr="Short valid binary frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X82,0XFE,0X00,0X9F,0X7D,0X97,0X6B,0XA2,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45,0X82,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45}, + .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, + .frame_len=167, + .raw_payload_len=159, + .expected_errno=0, + .descr="Mid-long valid binary frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X88,0X82,0X71,0X1D,0X00,0XFE,0X72,0XF6}, + .expectedDecodeBuf={0X03,0XEB}, + .frame_len=8, + .raw_payload_len=2, + .expected_errno=104, + .descr="Close frame (Reason 1003)", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X88,0XAD,0XD0,0X8D,0X26,0XD8,0XD3,0X66,0X6F,0XFF,0XBD,0XAD,0X47,0XF8,0XB3,0XE1,0X49,0XAB,0XB5,0XAD,0X54,0XBD,0XB1,0XFE,0X49,0XB6,0XF0,0XEC,0X48,0XBC,0XF0,0XE0,0X53,0XBB,0XB8,0XAD,0X4B,0XB7,0XA2,0XE8,0X06,0XAC,0XB8,0XEC,0X48,0XF8,0XA4,0XE5,0X47,0XAC,0XF1}, + .expectedDecodeBuf={0X03,0XEB,0X49,0X27,0X6D,0X20,0X61,0X20,0X63,0X6C,0X6F,0X73,0X65,0X20,0X72,0X65,0X61,0X73,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X68,0X61,0X6E,0X20,0X74,0X68,0X61,0X74,0X21}, + .frame_len=51, + .raw_payload_len=45, + .expected_errno=104, + .descr="Close frame (Reason 1003) and msg", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0X08,0X56,0X47,0X56,0X7A,0X64,0X47,0X6C,0X30}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=10, + .raw_payload_len=6, + .expected_errno=71, + .descr="Invalid frame: Wrong masking", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFE,0X00,0X0F,0X24,0X22,0X8D,0X9C,0X11,0X6F,0XA3,0XC6,0X6E,0X4E,0X88,0XB0,0X48,0X55,0XA2,0XC6,0X72,0X56}, + .expectedDecodeBuf={0X2E,0XFE,0X00,0X0F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, + .frame_len=22, + .raw_payload_len=12, + .expected_errno=71, + .descr="Invalid frame: Length of < 126 with add. 16 bit len field", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X7D,0XBB,0X03,0X56,0X7D,0XBB,0X03,0X56,0X7C,0X83,0X2D,0X0C,0X03,0XA2,0X06,0X7A,0X25,0XB9,0X2C,0X0C,0X1F,0XBA}, + .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X4C,0X6F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, + .frame_len=30, + .raw_payload_len=18, + .expected_errno=71, + .descr="Invalid frame: Length of < 126 with add. 64 bit len field", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + } +}; -- cgit v1.2.3 From 8fefdcde2750340c8c4062548e51acc34ae61496 Mon Sep 17 00:00:00 2001 From: Andreas Weigel Date: Thu, 23 Feb 2017 11:55:49 +0100 Subject: fix problems in test and requests for cmake build add missing stdarg header fix hardcoded errno integer values in tests add dependency to wstestdata and rename to prevent building it as c source --- CMakeLists.txt | 47 ++++++++------------- test/wsmaketestframe.py | 11 +++-- test/wstest.c | 3 +- test/wstestdata.c | 110 ------------------------------------------------ test/wstestdata.inc | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 146 deletions(-) delete mode 100644 test/wstestdata.c create mode 100644 test/wstestdata.inc (limited to 'test') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c6da06..de696bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ option(WITH_IPv6 "Enable IPv6 Support" ON) option(WITH_WEBSOCKETS "Build with websockets support" ON) + if(WITH_ZLIB) find_package(ZLIB) endif(WITH_ZLIB) @@ -500,9 +501,11 @@ foreach(e ${LIBVNCCLIENT_EXAMPLES}) target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL_LIBRARY} ${FFMPEG_LIBRARIES}) endforeach(e ${LIBVNCCLIENT_EXAMPLES}) + # # them tests # + if(UNIX) set(ADDITIONAL_TEST_LIBS m) endif(UNIX) @@ -510,41 +513,18 @@ endif(UNIX) set(SIMPLETESTS cargstest copyrecttest - wstest ) -add_test(NAME cargs COMMAND test_cargstest) -add_test(NAME websockets_decode COMMAND test_wstest) - -if(CMAKE_USE_PTHREADS_INI) - list(APPEND SIMPLETESTS encodingstest) -endif(CMAKE_USE_PTHREADS_INI) - -if(FOUND_LIBJPEG_TURBO) - list(APPEND SIMPLETESTS tjunittest tjbench) - set(tjunittest_add_src - ${TESTS_DIR}/tjutil.c - ${TESTS_DIR}/tjutil.h - ${COMMON_DIR}/turbojpeg.c - ${COMMON_DIR}/turbojpeg.h +if(CMAKE_USE_PTHREADS_INIT) + set(SIMPLETESTS + ${SIMPLETESTS} + encodingstest ) - - set(tjbench_add_src - ${TESTS_DIR}/tjbench.c - ${TESTS_DIR}/tjutil.c - ${TESTS_DIR}/tjutil.h - ${TESTS_DIR}/bmp.c - ${TESTS_DIR}/bmp.h - ${COMMON_DIR}/turbojpeg.c - ${COMMON_DIR}/turbojpeg.h - ) - - add_test(NAME turbojpeg COMMAND test_tjunittest) -endif(FOUND_LIBJPEG_TURBO) +endif(CMAKE_USE_PTHREADS_INIT) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test) foreach(t ${SIMPLETESTS}) - add_executable(test_${t} ${TESTS_DIR}/${t}.c ${${t}_add_src}) + add_executable(test_${t} ${TESTS_DIR}/${t}.c) set_target_properties(test_${t} PROPERTIES OUTPUT_NAME ${t}) set_target_properties(test_${t} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test) target_link_libraries(test_${t} vncserver vncclient ${ADDITIONAL_TEST_LIBS}) @@ -577,10 +557,19 @@ if(WITH_JPEG AND FOUND_LIBJPEG_TURBO) endif(WITH_JPEG AND FOUND_LIBJPEG_TURBO) +add_executable(test_wstest + ${TESTS_DIR}/wstest.c + ${TESTS_DIR}/wstestdata.inc + ) +set_target_properties(test_wstest PROPERTIES OUTPUT_NAME wstest) +set_target_properties(test_wstest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test) +target_link_libraries(test_wstest vncserver vncclient ${ADDITIONAL_TEST_LIBS}) + add_test(NAME cargs COMMAND test_cargstest) if(FOUND_LIBJPEG_TURBO) add_test(NAME turbojpeg COMMAND test_tjunittest) endif(FOUND_LIBJPEG_TURBO) +add_test(NAME wstest COMMAND test_wstest) # # this gets the libraries needed by TARGET in "-libx -liby ..." form diff --git a/test/wsmaketestframe.py b/test/wsmaketestframe.py index 3412754..1d4d24d 100755 --- a/test/wsmaketestframe.py +++ b/test/wsmaketestframe.py @@ -24,7 +24,6 @@ import websockets import base64 -import errno ''' Create websocket frames for the wstest websocket decoding unit test. @@ -105,13 +104,13 @@ flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray("Frame2 does con #flist.append(Testframe(websockets.framing.Frame(1, 2, bytearray([(x % 26) + 65 for x in range(100000)])), "100k binary frame (ABC..YZABC..)")) ### some conn reset frames, one with no close message, one with close message -flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB]))), "Close frame (Reason 1003)", experrno=errno.ECONNRESET)) -flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB])) + bytearray("I'm a close reason and much more than that!", encoding="utf-8")), "Close frame (Reason 1003) and msg", experrno=errno.ECONNRESET)) +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB]))), "Close frame (Reason 1003)", experrno="ECONNRESET")) +flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB])) + bytearray("I'm a close reason and much more than that!", encoding="utf-8")), "Close frame (Reason 1003) and msg", experrno="ECONNRESET")) ### invalid header values -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", experrno=errno.EPROTO, mask=False)) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", experrno=errno.EPROTO, modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno=errno.EPROTO, modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", experrno="EPROTO", mask=False)) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) s = "struct ws_frame_test tests[] = {\n" for i in range(len(flist)): diff --git a/test/wstest.c b/test/wstest.c index 4a5ba91..69cd174 100644 --- a/test/wstest.c +++ b/test/wstest.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,7 @@ struct ws_frame_test { int close_sock_at; }; -#include "wstestdata.c" +#include "wstestdata.inc" char el_log[1000000]; char *el_pos; diff --git a/test/wstestdata.c b/test/wstestdata.c deleted file mode 100644 index 628bdb1..0000000 --- a/test/wstestdata.c +++ /dev/null @@ -1,110 +0,0 @@ -struct ws_frame_test tests[] = { - { - .frame={0X81,0X88,0XB7,0XDB,0X16,0X16,0XE1,0X9C,0X40,0X6C,0XD3,0X9C,0X7A,0X26}, - .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, - .frame_len=14, - .raw_payload_len=6, - .expected_errno=0, - .descr="Short valid text frame", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X81,0XFE,0X00,0XD4,0X67,0XFE,0X8A,0X31,0X35,0X90,0XC0,0X59,0X05,0XA9,0XDF,0X48,0X2E,0XB9,0XD8,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0XCC,0XB3,0X44,0X03,0XB9,0XCC,0X41,0X05,0X97,0XC8,0X45,0X03,0XA9,0XC4,0X5E,0X2E,0XB9,0XBB,0X47,0X04,0X93,0XDF,0X56,0X03,0XB9,0XDC,0X05,0X03,0XBD,0XC8,0X59,0X05,0X93,0XDB,0X56,0X3D,0XA6,0XD0,0X5D,0X05,0X97,0XC8,0X5F,0X05,0XCC,0XDC,0X4B,0X2E,0XB9,0XC0,0X5D,0X02,0XA9,0XB3,0X44,0X3D,0XBD,0XC8,0X01,0X06,0XB9,0XDF,0X56,0X2A,0XAA,0XC3,0X03,0X2E,0XB9,0XC0,0X04,0X03,0XB9,0XDF,0X56,0X05,0XB9,0XDC,0X44,0X2E,0XB9,0XD0,0X41,0X3D,0XA9,0XF2,0X5A,0X2B,0X97,0XC8,0X76,0X04,0X93,0XCC,0X45,0X3D,0XAA,0XC3,0X56,0X3D,0XB9,0XB3,0X5D,0X04,0X87,0XC8,0X5B,0X05,0XCC,0XBF,0X01,0X3E,0XA9,0XE6,0X44,0X2E,0XB9,0XBB,0X00,0X3E,0XCC,0XED,0X56,0X05,0XA9,0XB3,0X48,0X3D,0XAD,0XC8,0X01,0X3D,0XA6,0XE2,0X01,0X2E,0XB9,0XCC,0X44,0X3D,0XBD,0XC8,0X5D,0X03,0X93,0XDC,0X44,0X2E,0XB9,0XEE,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0X93,0XDC,0X04,0X05,0XCC,0XBF,0X5A,0X2E,0XB6,0XD8,0X5E,0X3D,0XAD,0XCB,0X49,0X2A,0X94,0XD3,0X56,0X3E,0X90,0XE6,0X01,0X3D,0XAD,0XC8,0X42,0X3D,0XA9,0XBE,0X56,0X3D,0X93,0XE6,0X5D,0X05,0XB9,0XDB,0X44}, - .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, - .frame_len=220, - .raw_payload_len=159, - .expected_errno=0, - .descr="Mid-long valid text frame", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X82,0X86,0X90,0X5E,0X2B,0X8E,0XC4,0X3B,0X58,0XFA,0XF9,0X2A}, - .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, - .frame_len=12, - .raw_payload_len=6, - .expected_errno=0, - .descr="Short valid binary frame", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X82,0XFE,0X00,0X9F,0X7D,0X97,0X6B,0XA2,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45,0X82,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45}, - .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, - .frame_len=167, - .raw_payload_len=159, - .expected_errno=0, - .descr="Mid-long valid binary frame", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X88,0X82,0X71,0X1D,0X00,0XFE,0X72,0XF6}, - .expectedDecodeBuf={0X03,0XEB}, - .frame_len=8, - .raw_payload_len=2, - .expected_errno=104, - .descr="Close frame (Reason 1003)", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X88,0XAD,0XD0,0X8D,0X26,0XD8,0XD3,0X66,0X6F,0XFF,0XBD,0XAD,0X47,0XF8,0XB3,0XE1,0X49,0XAB,0XB5,0XAD,0X54,0XBD,0XB1,0XFE,0X49,0XB6,0XF0,0XEC,0X48,0XBC,0XF0,0XE0,0X53,0XBB,0XB8,0XAD,0X4B,0XB7,0XA2,0XE8,0X06,0XAC,0XB8,0XEC,0X48,0XF8,0XA4,0XE5,0X47,0XAC,0XF1}, - .expectedDecodeBuf={0X03,0XEB,0X49,0X27,0X6D,0X20,0X61,0X20,0X63,0X6C,0X6F,0X73,0X65,0X20,0X72,0X65,0X61,0X73,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X68,0X61,0X6E,0X20,0X74,0X68,0X61,0X74,0X21}, - .frame_len=51, - .raw_payload_len=45, - .expected_errno=104, - .descr="Close frame (Reason 1003) and msg", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X81,0X08,0X56,0X47,0X56,0X7A,0X64,0X47,0X6C,0X30}, - .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, - .frame_len=10, - .raw_payload_len=6, - .expected_errno=71, - .descr="Invalid frame: Wrong masking", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X81,0XFE,0X00,0X0F,0X24,0X22,0X8D,0X9C,0X11,0X6F,0XA3,0XC6,0X6E,0X4E,0X88,0XB0,0X48,0X55,0XA2,0XC6,0X72,0X56}, - .expectedDecodeBuf={0X2E,0XFE,0X00,0X0F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, - .frame_len=22, - .raw_payload_len=12, - .expected_errno=71, - .descr="Invalid frame: Length of < 126 with add. 16 bit len field", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - }, - { - .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X7D,0XBB,0X03,0X56,0X7D,0XBB,0X03,0X56,0X7C,0X83,0X2D,0X0C,0X03,0XA2,0X06,0X7A,0X25,0XB9,0X2C,0X0C,0X1F,0XBA}, - .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X4C,0X6F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, - .frame_len=30, - .raw_payload_len=18, - .expected_errno=71, - .descr="Invalid frame: Length of < 126 with add. 64 bit len field", - .i=0, - .simulate_sock_malfunction_at=0, - .errno_val=0, - .close_sock_at=0 - } -}; diff --git a/test/wstestdata.inc b/test/wstestdata.inc new file mode 100644 index 0000000..9dc919e --- /dev/null +++ b/test/wstestdata.inc @@ -0,0 +1,110 @@ +struct ws_frame_test tests[] = { + { + .frame={0X81,0X88,0XB7,0XDB,0X16,0X16,0XE1,0X9C,0X40,0X6C,0XD3,0X9C,0X7A,0X26}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=14, + .raw_payload_len=6, + .expected_errno=0, + .descr="Short valid text frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFE,0X00,0XD4,0X67,0XFE,0X8A,0X31,0X35,0X90,0XC0,0X59,0X05,0XA9,0XDF,0X48,0X2E,0XB9,0XD8,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0XCC,0XB3,0X44,0X03,0XB9,0XCC,0X41,0X05,0X97,0XC8,0X45,0X03,0XA9,0XC4,0X5E,0X2E,0XB9,0XBB,0X47,0X04,0X93,0XDF,0X56,0X03,0XB9,0XDC,0X05,0X03,0XBD,0XC8,0X59,0X05,0X93,0XDB,0X56,0X3D,0XA6,0XD0,0X5D,0X05,0X97,0XC8,0X5F,0X05,0XCC,0XDC,0X4B,0X2E,0XB9,0XC0,0X5D,0X02,0XA9,0XB3,0X44,0X3D,0XBD,0XC8,0X01,0X06,0XB9,0XDF,0X56,0X2A,0XAA,0XC3,0X03,0X2E,0XB9,0XC0,0X04,0X03,0XB9,0XDF,0X56,0X05,0XB9,0XDC,0X44,0X2E,0XB9,0XD0,0X41,0X3D,0XA9,0XF2,0X5A,0X2B,0X97,0XC8,0X76,0X04,0X93,0XCC,0X45,0X3D,0XAA,0XC3,0X56,0X3D,0XB9,0XB3,0X5D,0X04,0X87,0XC8,0X5B,0X05,0XCC,0XBF,0X01,0X3E,0XA9,0XE6,0X44,0X2E,0XB9,0XBB,0X00,0X3E,0XCC,0XED,0X56,0X05,0XA9,0XB3,0X48,0X3D,0XAD,0XC8,0X01,0X3D,0XA6,0XE2,0X01,0X2E,0XB9,0XCC,0X44,0X3D,0XBD,0XC8,0X5D,0X03,0X93,0XDC,0X44,0X2E,0XB9,0XEE,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0X93,0XDC,0X04,0X05,0XCC,0XBF,0X5A,0X2E,0XB6,0XD8,0X5E,0X3D,0XAD,0XCB,0X49,0X2A,0X94,0XD3,0X56,0X3E,0X90,0XE6,0X01,0X3D,0XAD,0XC8,0X42,0X3D,0XA9,0XBE,0X56,0X3D,0X93,0XE6,0X5D,0X05,0XB9,0XDB,0X44}, + .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, + .frame_len=220, + .raw_payload_len=159, + .expected_errno=0, + .descr="Mid-long valid text frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X82,0X86,0X90,0X5E,0X2B,0X8E,0XC4,0X3B,0X58,0XFA,0XF9,0X2A}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=12, + .raw_payload_len=6, + .expected_errno=0, + .descr="Short valid binary frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X82,0XFE,0X00,0X9F,0X7D,0X97,0X6B,0XA2,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45,0X82,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45}, + .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, + .frame_len=167, + .raw_payload_len=159, + .expected_errno=0, + .descr="Mid-long valid binary frame", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X88,0X82,0X71,0X1D,0X00,0XFE,0X72,0XF6}, + .expectedDecodeBuf={0X03,0XEB}, + .frame_len=8, + .raw_payload_len=2, + .expected_errno=ECONNRESET, + .descr="Close frame (Reason 1003)", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X88,0XAD,0XD0,0X8D,0X26,0XD8,0XD3,0X66,0X6F,0XFF,0XBD,0XAD,0X47,0XF8,0XB3,0XE1,0X49,0XAB,0XB5,0XAD,0X54,0XBD,0XB1,0XFE,0X49,0XB6,0XF0,0XEC,0X48,0XBC,0XF0,0XE0,0X53,0XBB,0XB8,0XAD,0X4B,0XB7,0XA2,0XE8,0X06,0XAC,0XB8,0XEC,0X48,0XF8,0XA4,0XE5,0X47,0XAC,0XF1}, + .expectedDecodeBuf={0X03,0XEB,0X49,0X27,0X6D,0X20,0X61,0X20,0X63,0X6C,0X6F,0X73,0X65,0X20,0X72,0X65,0X61,0X73,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X68,0X61,0X6E,0X20,0X74,0X68,0X61,0X74,0X21}, + .frame_len=51, + .raw_payload_len=45, + .expected_errno=ECONNRESET, + .descr="Close frame (Reason 1003) and msg", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0X08,0X56,0X47,0X56,0X7A,0X64,0X47,0X6C,0X30}, + .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, + .frame_len=10, + .raw_payload_len=6, + .expected_errno=EPROTO, + .descr="Invalid frame: Wrong masking", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFE,0X00,0X0F,0X24,0X22,0X8D,0X9C,0X11,0X6F,0XA3,0XC6,0X6E,0X4E,0X88,0XB0,0X48,0X55,0XA2,0XC6,0X72,0X56}, + .expectedDecodeBuf={0X2E,0XFE,0X00,0X0F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, + .frame_len=22, + .raw_payload_len=12, + .expected_errno=EPROTO, + .descr="Invalid frame: Length of < 126 with add. 16 bit len field", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X7D,0XBB,0X03,0X56,0X7D,0XBB,0X03,0X56,0X7C,0X83,0X2D,0X0C,0X03,0XA2,0X06,0X7A,0X25,0XB9,0X2C,0X0C,0X1F,0XBA}, + .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X4C,0X6F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, + .frame_len=30, + .raw_payload_len=18, + .expected_errno=EPROTO, + .descr="Invalid frame: Length of < 126 with add. 64 bit len field", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + } +}; -- cgit v1.2.3 From 5d9d6a87124a5439d3432c37a67f9b2babe04407 Mon Sep 17 00:00:00 2001 From: Andreas Weigel Date: Mon, 27 Feb 2017 08:45:32 +0100 Subject: add decode support for continuation frames use FIN bit and implement opcode 0x00 make consistent use of uint64_t for big frame sizes --- libvncserver/websockets.c | 3 +- libvncserver/ws_decode.c | 137 +++++++++++++++++++++++++++++++++++++--------- libvncserver/ws_decode.h | 32 +++++------ test/wsmaketestframe.py | 15 +++-- test/wstest.c | 29 +++++----- test/wstestdata.inc | 54 +++++++++++++++--- 6 files changed, 196 insertions(+), 74 deletions(-) (limited to 'test') diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index 73ad81c..921015d 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -339,12 +339,11 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) free(buf); wsctx = calloc(1, sizeof(ws_ctx_t)); - wsctx->version = WEBSOCKETS_VERSION_HYBI; wsctx->encode = webSocketsEncodeHybi; wsctx->decode = webSocketsDecodeHybi; wsctx->ctxInfo.readFunc = ws_read; wsctx->base64 = base64; - hybiDecodeCleanup(wsctx); + hybiDecodeCleanupComplete(wsctx); cl->wsctx = (wsCtx *)wsctx; return TRUE; } diff --git a/libvncserver/ws_decode.c b/libvncserver/ws_decode.c index 472a44a..485478d 100644 --- a/libvncserver/ws_decode.c +++ b/libvncserver/ws_decode.c @@ -8,17 +8,27 @@ #define WS_HYBI_HEADER_LEN_EXTENDED 4 + WS_HYBI_MASK_LEN #define WS_HYBI_HEADER_LEN_LONG 10 + WS_HYBI_MASK_LEN -static int +static inline int +isControlFrame(ws_ctx_t *wsctx) +{ + return 0 != (wsctx->header.opcode & 0x08); +} + +static uint64_t hybiRemaining(ws_ctx_t *wsctx) { return wsctx->nToRead - wsctx->nReadRaw; } -void -hybiDecodeCleanup(ws_ctx_t *wsctx) +static void +hybiDecodeCleanupBasics(ws_ctx_t *wsctx) { + /* keep opcode, cleanup rest */ + wsctx->header.opcode = WS_OPCODE_INVALID; wsctx->header.payloadLen = 0; wsctx->header.mask.u = 0; + wsctx->header.headerLen = 0; + wsctx->header.data = NULL; wsctx->nReadRaw = 0; wsctx->nToRead= 0; wsctx->carrylen = 0; @@ -26,9 +36,24 @@ hybiDecodeCleanup(ws_ctx_t *wsctx) wsctx->readlen = 0; wsctx->hybiDecodeState = WS_HYBI_STATE_HEADER_PENDING; wsctx->writePos = NULL; - rfbLog("cleaned up wsctx\n"); } +static void +hybiDecodeCleanupForContinuation(ws_ctx_t *wsctx) +{ + hybiDecodeCleanupBasics(wsctx); + rfbLog("clean up frame, but expect continuation with opcode %d\n", wsctx->continuation_opcode); +} + +void +hybiDecodeCleanupComplete(ws_ctx_t *wsctx) +{ + hybiDecodeCleanupBasics(wsctx); + wsctx->continuation_opcode = WS_OPCODE_INVALID; + rfbLog("cleaned up wsctx completely\n"); +} + + /** * Return payload data that has been decoded/unmasked from * a websocket frame. @@ -94,10 +119,9 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) { int ret; char *headerDst = wsctx->codeBufDecode + wsctx->nReadRaw; - int n = WSHLENMAX - wsctx->nReadRaw; + int n = ((uint64_t)WSHLENMAX) - wsctx->nReadRaw; rfbLog("header_read to %p with len=%d\n", headerDst, n); - //ret = ws_read(cl, headerDst, n); ret = wsctx->ctxInfo.readFunc(wsctx->ctxInfo.ctxPtr, headerDst, n); rfbLog("read %d bytes from socket\n", ret); if (ret <= 0) { @@ -106,29 +130,65 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) int olderrno = errno; rfbErr("%s: read; %s\n", __func__, strerror(errno)); errno = olderrno; - *sockRet = -1; + goto err_cleanup_state; } else { *sockRet = 0; + goto err_cleanup_state_sock_closed; } - return WS_HYBI_STATE_ERR; } wsctx->nReadRaw += ret; if (wsctx->nReadRaw < 2) { /* cannot decode header with less than two bytes */ - errno = EAGAIN; - *sockRet = -1; - return WS_HYBI_STATE_HEADER_PENDING; + goto ret_header_pending; } /* first two header bytes received; interpret header data and get rest */ wsctx->header.data = (ws_header_t *)wsctx->codeBufDecode; wsctx->header.opcode = wsctx->header.data->b0 & 0x0f; + wsctx->header.fin = (wsctx->header.data->b0 & 0x80) >> 7; + if (isControlFrame(wsctx)) { + rfbLog("is control frame\n"); + /* is a control frame, leave remembered continuation opcode unchanged; + * just check if there is a wrong fragmentation */ + if (wsctx->header.fin == 0) { + + /* we only accept text/binary continuation frames; RFC6455: + * Control frames (see Section 5.5) MAY be injected in the middle of + * a fragmented message. Control frames themselves MUST NOT be + * fragmented. */ + rfbErr("control frame with FIN bit cleared received, aborting\n"); + errno = EPROTO; + goto err_cleanup_state; + } + } else { + rfbLog("not a control frame\n"); + /* not a control frame, check for continuation opcode */ + if (wsctx->header.opcode == WS_OPCODE_CONTINUATION) { + rfbLog("cont_frame\n"); + /* do we have state (i.e., opcode) for continuation frame? */ + if (wsctx->continuation_opcode == WS_OPCODE_INVALID) { + rfbErr("no continuation state\n"); + errno = EPROTO; + goto err_cleanup_state; + } - /* fin = (header->b0 & 0x80) >> 7; */ /* not used atm */ - wsctx->header.payloadLen = wsctx->header.data->b1 & 0x7f; - rfbLog("first header bytes received; opcode=%d lenbyte=%d\n", wsctx->header.opcode, wsctx->header.payloadLen); + /* otherwise, set opcode = continuation_opcode */ + wsctx->header.opcode = wsctx->continuation_opcode; + rfbLog("set opcode to continuation_opcode: %d\n", wsctx->header.opcode); + } else { + if (wsctx->header.fin == 0) { + wsctx->continuation_opcode = wsctx->header.opcode; + } else { + wsctx->continuation_opcode = WS_OPCODE_INVALID; + } + rfbLog("set continuation_opcode to %d\n", wsctx->continuation_opcode); + } + } + + wsctx->header.payloadLen = (uint64_t)(wsctx->header.data->b1 & 0x7f); + rfbLog("first header bytes received; opcode=%d lenbyte=%d fin=%d\n", wsctx->header.opcode, wsctx->header.payloadLen, wsctx->header.fin); /* * 4.3. Client-to-Server Masking @@ -139,8 +199,7 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) if (!(wsctx->header.data->b1 & 0x80)) { rfbErr("%s: got frame without mask; ret=%d\n", __func__, ret); errno = EPROTO; - *sockRet = -1; - return WS_HYBI_STATE_ERR; + goto err_cleanup_state; } @@ -158,22 +217,27 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) } else { /* Incomplete frame header, try again */ rfbErr("%s: incomplete frame header; ret=%d\n", __func__, ret); - errno = EAGAIN; - *sockRet = -1; - return WS_HYBI_STATE_HEADER_PENDING; + goto ret_header_pending; } + char *h = wsctx->codeBufDecode; + int i; + rfbLog("Header:\n"); + for (i=0; i <10; i++) { + rfbLog("0x%02X\n", (unsigned char)h[i]); + } + rfbLog("\n"); + /* while RFC 6455 mandates that lengths MUST be encoded with the minimum * number of bytes, it does not specify for the server how to react on * 'wrongly' encoded frames --- this implementation rejects them*/ if ((wsctx->header.headerLen > WS_HYBI_HEADER_LEN_SHORT - && wsctx->header.payloadLen < 126) + && wsctx->header.payloadLen < (uint64_t)126) || (wsctx->header.headerLen > WS_HYBI_HEADER_LEN_EXTENDED - && wsctx->header.payloadLen < 65536)) { + && wsctx->header.payloadLen < (uint64_t)65536)) { rfbErr("%s: invalid length field; headerLen=%d payloadLen=%llu\n", __func__, wsctx->header.headerLen, wsctx->header.payloadLen); errno = EPROTO; - *sockRet = -1; - return WS_HYBI_STATE_ERR; + goto err_cleanup_state; } /* absolute length of frame */ @@ -186,9 +250,20 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload) wsctx->readPos = (unsigned char *)(wsctx->codeBufDecode + wsctx->header.headerLen); *nPayload = wsctx->nReadRaw - wsctx->header.headerLen; - rfbLog("header complete: state=%d flen=%d writeTo=%p nPayload=%d\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos, *nPayload); + rfbLog("header complete: state=%d flen=%llu writeTo=%p nPayload=%d\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos, *nPayload); return WS_HYBI_STATE_DATA_NEEDED; + +ret_header_pending: + errno = EAGAIN; + *sockRet = -1; + return WS_HYBI_STATE_HEADER_PENDING; + +err_cleanup_state: + *sockRet = -1; +err_cleanup_state_sock_closed: + hybiDecodeCleanupComplete(wsctx); + return WS_HYBI_STATE_ERR; } static int @@ -248,6 +323,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet, int nInBuf) /* -1 accounts for potential '\0' terminator for base64 decoding */ bufsize = wsctx->codeBufDecode + ARRAYSIZE(wsctx->codeBufDecode) - wsctx->writePos - 1; + rfbLog("bufsize=%d\n", bufsize); if (hybiRemaining(wsctx) > bufsize) { nextRead = bufsize; } else { @@ -453,11 +529,18 @@ spor: /* rfbLog("%s: ret: %d/%d\n", __func__, result, len); */ if (wsctx->hybiDecodeState == WS_HYBI_STATE_FRAME_COMPLETE) { rfbLog("frame received successfully, cleaning up: read=%d hlen=%d plen=%d\n", wsctx->header.nRead, wsctx->header.headerLen, wsctx->header.payloadLen); - /* frame finished, cleanup state */ - hybiDecodeCleanup(wsctx); + if (wsctx->header.fin && !isControlFrame(wsctx)) { + /* frame finished, cleanup state */ + hybiDecodeCleanupComplete(wsctx); + } else { + /* always retain continuation opcode for unfinished data frames + * or control frames, which may interleave with data frames */ + hybiDecodeCleanupForContinuation(wsctx); + } } else if (wsctx->hybiDecodeState == WS_HYBI_STATE_ERR) { - hybiDecodeCleanup(wsctx); + hybiDecodeCleanupComplete(wsctx); } + rfbLog("%s_exit: len=%d; " "CTX: readlen=%d readPos=%p " "writePos=%p " diff --git a/libvncserver/ws_decode.h b/libvncserver/ws_decode.h index 0dcbc83..07d37bd 100644 --- a/libvncserver/ws_decode.h +++ b/libvncserver/ws_decode.h @@ -27,16 +27,11 @@ #endif #define B64LEN(__x) (((__x + 2) / 3) * 12 / 3) -#define WSHLENMAX 14 /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */ +#define WSHLENMAX 14LL /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */ #define WS_HYBI_MASK_LEN 4 #define ARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))) / (size_t)(!(sizeof(a) % sizeof((a[0]))))) -enum { - WEBSOCKETS_VERSION_HIXIE, - WEBSOCKETS_VERSION_HYBI -}; - struct ws_ctx_s; typedef struct ws_ctx_s ws_ctx_t; @@ -111,9 +106,11 @@ typedef struct ws_header_data_s { /** length of frame header including payload len, but without mask */ int headerLen; /** length of the payload data */ - int payloadLen; + uint64_t payloadLen; /** opcode */ unsigned char opcode; + /** fin bit */ + unsigned char fin; } ws_header_data_t; typedef struct ws_ctx_s { @@ -125,11 +122,11 @@ typedef struct ws_ctx_s { int hybiDecodeState; char carryBuf[3]; /* For base64 carry-over */ int carrylen; - int version; int base64; ws_header_data_t header; - int nReadRaw; - int nToRead; + uint64_t nReadRaw; + uint64_t nToRead; + unsigned char continuation_opcode; wsEncodeFunc encode; wsDecodeFunc decode; ctxInfo_t ctxInfo; @@ -137,15 +134,16 @@ typedef struct ws_ctx_s { enum { - WS_OPCODE_CONTINUATION = 0x0, - WS_OPCODE_TEXT_FRAME, - WS_OPCODE_BINARY_FRAME, - WS_OPCODE_CLOSE = 0x8, - WS_OPCODE_PING, - WS_OPCODE_PONG + WS_OPCODE_CONTINUATION = 0x00, + WS_OPCODE_TEXT_FRAME = 0x01, + WS_OPCODE_BINARY_FRAME = 0x02, + WS_OPCODE_CLOSE = 0x08, + WS_OPCODE_PING = 0x09, + WS_OPCODE_PONG = 0x0A, + WS_OPCODE_INVALID = 0xFF }; int webSocketsDecodeHybi(ws_ctx_t *wsctx, char *dst, int len); -void hybiDecodeCleanup(ws_ctx_t *wsctx); +void hybiDecodeCleanupComplete(ws_ctx_t *wsctx); #endif diff --git a/test/wsmaketestframe.py b/test/wsmaketestframe.py index 1d4d24d..fc03e39 100755 --- a/test/wsmaketestframe.py +++ b/test/wsmaketestframe.py @@ -42,12 +42,12 @@ def add_field(s, name, value, first=False): class Testframe(): - def __init__(self, frame, descr, modify_bytes={}, experrno=0, mask=True): + def __init__(self, frame, descr, modify_bytes={}, experrno=0, mask=True, opcode_overwrite=False): self.frame = frame self.descr = descr self.modify_bytes = modify_bytes self.experrno = experrno - self.b64 = True if frame.opcode == 1 else False + self.b64 = True if frame.opcode == 1 or opcode_overwrite == 1 else False self.mask = mask def to_carray_initializer(self, buf): @@ -110,7 +110,14 @@ flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB ### invalid header values flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", experrno="EPROTO", mask=False)) flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F})) -flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40})) +flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x00, 7: 0x00, 8: 0x80, 9: 0x40})) + +frag1 = websockets.framing.Frame(0, 1, bytearray("This is a fragmented websocket...", encoding="utf-8")) +frag2 = websockets.framing.Frame(0, 0, bytearray("... and it goes on...", encoding="utf-8")) +frag3 = websockets.framing.Frame(1, 0, bytearray("and on and stop", encoding="utf-8")) +flist.append(Testframe(frag1, "Continuation test frag1")) +flist.append(Testframe(frag2, "Continuation test frag2", opcode_overwrite=1)) +flist.append(Testframe(frag3, "Continuation test frag3", opcode_overwrite=1)) s = "struct ws_frame_test tests[] = {\n" for i in range(len(flist)): @@ -120,5 +127,5 @@ for i in range(len(flist)): s += "\n" s += "};\n" -with open("wstestdata.c", "w") as cdatafile: +with open("wstestdata.inc", "w") as cdatafile: cdatafile.write(s) diff --git a/test/wstest.c b/test/wstest.c index 69cd174..042b75b 100644 --- a/test/wstest.c +++ b/test/wstest.c @@ -98,10 +98,10 @@ static int emu_read(void *ctx, char *dst, size_t len) rfbLog("emu_read called with dst=%p and len=%lu\n", dst, len); if (ft->simulate_sock_malfunction_at > 0 && ft->simulate_sock_malfunction_at == ft->i) { rfbLog("simulating IO error with errno=%d\n", ft->errno_val); - errno = ft->errno_val; + errno = ft->errno_val; return -1; } - + /* return something */ r = rand(); modu = (ft->frame + ft->frame_len) - ft->pos; @@ -130,7 +130,7 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx) while (nleft > 0) { rfbLog("calling ws_decode with dst=%p, len=%lu\n", dst, nleft); n = ctx->decode(ctx, dst, nleft); - rfbLog("read n=%ld\n", n); + rfbLog("read n=%ld\n", n); if (n == 0) { if (ft->close_sock_at > 0) { return OK; @@ -155,7 +155,7 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx) rfbLog("read n=%ld from decode; dst=%p, nleft=%lu\n", n, dst, nleft); } } - + if (memcmp(ft->expectedDecodeBuf, dstbuf, ft->raw_payload_len) != 0) { ft->expectedDecodeBuf[ft->raw_payload_len] = '\0'; dstbuf[ft->raw_payload_len] = '\0'; @@ -168,24 +168,23 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx) int main() -{ +{ ws_ctx_t ctx; int retall= 0; int i; - srand(RND_SEED); + srand(RND_SEED); + hybiDecodeCleanupComplete(&ctx); + ctx.decode = webSocketsDecodeHybi; + ctx.ctxInfo.readFunc = emu_read; + rfbLog = logtest; + rfbErr = logtest; + for (i = 0; i < ARRAYSIZE(tests); i++) { int ret; + /* reset output log buffer to begin */ el_pos = el_log; - rfbLog = logtest; - rfbErr = logtest; - - hybiDecodeCleanup(&ctx); - ctx.decode = webSocketsDecodeHybi; - ctx.version = WEBSOCKETS_VERSION_HYBI; - - ctx.ctxInfo.readFunc = emu_read; ret = run_test(&tests[i], &ctx); printf("%s: \"%s\"\n", ret == 0 ? "PASS" : "FAIL", tests[i].descr); @@ -198,7 +197,7 @@ int main() return retall; } -#else +#else int main() { return 0; diff --git a/test/wstestdata.inc b/test/wstestdata.inc index 9dc919e..595b891 100644 --- a/test/wstestdata.inc +++ b/test/wstestdata.inc @@ -1,6 +1,6 @@ struct ws_frame_test tests[] = { { - .frame={0X81,0X88,0XB7,0XDB,0X16,0X16,0XE1,0X9C,0X40,0X6C,0XD3,0X9C,0X7A,0X26}, + .frame={0X81,0X88,0X2F,0X2A,0X17,0X41,0X79,0X6D,0X41,0X3B,0X4B,0X6D,0X7B,0X71}, .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, .frame_len=14, .raw_payload_len=6, @@ -12,7 +12,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X81,0XFE,0X00,0XD4,0X67,0XFE,0X8A,0X31,0X35,0X90,0XC0,0X59,0X05,0XA9,0XDF,0X48,0X2E,0XB9,0XD8,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0XCC,0XB3,0X44,0X03,0XB9,0XCC,0X41,0X05,0X97,0XC8,0X45,0X03,0XA9,0XC4,0X5E,0X2E,0XB9,0XBB,0X47,0X04,0X93,0XDF,0X56,0X03,0XB9,0XDC,0X05,0X03,0XBD,0XC8,0X59,0X05,0X93,0XDB,0X56,0X3D,0XA6,0XD0,0X5D,0X05,0X97,0XC8,0X5F,0X05,0XCC,0XDC,0X4B,0X2E,0XB9,0XC0,0X5D,0X02,0XA9,0XB3,0X44,0X3D,0XBD,0XC8,0X01,0X06,0XB9,0XDF,0X56,0X2A,0XAA,0XC3,0X03,0X2E,0XB9,0XC0,0X04,0X03,0XB9,0XDF,0X56,0X05,0XB9,0XDC,0X44,0X2E,0XB9,0XD0,0X41,0X3D,0XA9,0XF2,0X5A,0X2B,0X97,0XC8,0X76,0X04,0X93,0XCC,0X45,0X3D,0XAA,0XC3,0X56,0X3D,0XB9,0XB3,0X5D,0X04,0X87,0XC8,0X5B,0X05,0XCC,0XBF,0X01,0X3E,0XA9,0XE6,0X44,0X2E,0XB9,0XBB,0X00,0X3E,0XCC,0XED,0X56,0X05,0XA9,0XB3,0X48,0X3D,0XAD,0XC8,0X01,0X3D,0XA6,0XE2,0X01,0X2E,0XB9,0XCC,0X44,0X3D,0XBD,0XC8,0X5D,0X03,0X93,0XDC,0X44,0X2E,0XB9,0XEE,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0X93,0XDC,0X04,0X05,0XCC,0XBF,0X5A,0X2E,0XB6,0XD8,0X5E,0X3D,0XAD,0XCB,0X49,0X2A,0X94,0XD3,0X56,0X3E,0X90,0XE6,0X01,0X3D,0XAD,0XC8,0X42,0X3D,0XA9,0XBE,0X56,0X3D,0X93,0XE6,0X5D,0X05,0XB9,0XDB,0X44}, + .frame={0X81,0XFE,0X00,0XD4,0X66,0X27,0XE5,0X24,0X34,0X49,0XAF,0X4C,0X04,0X70,0XB0,0X5D,0X2F,0X60,0XB7,0X52,0X3C,0X7F,0XA8,0X43,0X3F,0X15,0XDC,0X51,0X02,0X60,0XA3,0X54,0X04,0X4E,0XA7,0X50,0X02,0X70,0XAB,0X4B,0X2F,0X60,0XD4,0X52,0X05,0X4A,0XB0,0X43,0X02,0X60,0XB3,0X10,0X02,0X64,0XA7,0X4C,0X04,0X4A,0XB4,0X43,0X3C,0X7F,0XBF,0X48,0X04,0X4E,0XA7,0X4A,0X04,0X15,0XB3,0X5E,0X2F,0X60,0XAF,0X48,0X03,0X70,0XDC,0X51,0X3C,0X64,0XA7,0X14,0X07,0X60,0XB0,0X43,0X2B,0X73,0XAC,0X16,0X2F,0X60,0XAF,0X11,0X02,0X60,0XB0,0X43,0X04,0X60,0XB3,0X51,0X2F,0X60,0XBF,0X54,0X3C,0X70,0X9D,0X4F,0X2A,0X4E,0XA7,0X63,0X05,0X4A,0XA3,0X50,0X3C,0X73,0XAC,0X43,0X3C,0X60,0XDC,0X48,0X05,0X5E,0XA7,0X4E,0X04,0X15,0XD0,0X14,0X3F,0X70,0X89,0X51,0X2F,0X60,0XD4,0X15,0X3F,0X15,0X82,0X43,0X04,0X70,0XDC,0X5D,0X3C,0X74,0XA7,0X14,0X3C,0X7F,0X8D,0X14,0X2F,0X60,0XA3,0X51,0X3C,0X64,0XA7,0X48,0X02,0X4A,0XB3,0X51,0X2F,0X60,0X81,0X52,0X3C,0X7F,0XA8,0X43,0X3F,0X4A,0XB3,0X11,0X04,0X15,0XD0,0X4F,0X2F,0X6F,0XB7,0X4B,0X3C,0X74,0XA4,0X5C,0X2B,0X4D,0XBC,0X43,0X3F,0X49,0X89,0X14,0X3C,0X74,0XA7,0X57,0X3C,0X70,0XD1,0X43,0X3C,0X4A,0X89,0X48,0X04,0X60,0XB4,0X51}, .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, .frame_len=220, .raw_payload_len=159, @@ -24,7 +24,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X82,0X86,0X90,0X5E,0X2B,0X8E,0XC4,0X3B,0X58,0XFA,0XF9,0X2A}, + .frame={0X82,0X86,0XDD,0X9B,0XD8,0X56,0X89,0XFE,0XAB,0X22,0XB4,0XEF}, .expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74}, .frame_len=12, .raw_payload_len=6, @@ -36,7 +36,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X82,0XFE,0X00,0X9F,0X7D,0X97,0X6B,0XA2,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45,0X82,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45}, + .frame={0X82,0XFE,0X00,0X9F,0XB5,0X6E,0X7F,0X4C,0XF3,0X1C,0X1E,0X21,0XD0,0X5C,0X5F,0X28,0XDA,0X0B,0X0C,0X6C,0XD6,0X01,0X11,0X38,0XD4,0X07,0X11,0X6C,0XD8,0X1B,0X1C,0X24,0X95,0X03,0X10,0X3E,0XD0,0X4E,0X0B,0X29,0XCD,0X1A,0X5F,0X2D,0XDB,0X0A,0X5F,0X29,0XC3,0X0B,0X11,0X6C,0XD2,0X01,0X1A,0X3F,0X95,0X0C,0X1A,0X35,0XDA,0X00,0X1B,0X6C,0XC1,0X06,0X1A,0X6C,0X84,0X5C,0X49,0X6C,0XD7,0X17,0X0B,0X29,0X95,0X02,0X1A,0X22,0X95,0X08,0X16,0X29,0XD9,0X0A,0X51,0X6C,0XF3,0X1C,0X1E,0X21,0XD0,0X5C,0X5F,0X28,0XDA,0X0B,0X0C,0X6C,0XD6,0X01,0X11,0X38,0XD4,0X07,0X11,0X6C,0XD8,0X1B,0X1C,0X24,0X95,0X03,0X10,0X3E,0XD0,0X4E,0X0B,0X29,0XCD,0X1A,0X5F,0X2D,0XDB,0X0A,0X5F,0X29,0XC3,0X0B,0X11,0X6C,0XD2,0X01,0X1A,0X3F,0X95,0X0C,0X1A,0X35,0XDA,0X00,0X1B,0X6C,0XC1,0X06,0X1A,0X6C,0X84,0X5C,0X49,0X6C,0XD7,0X17,0X0B,0X29,0X95,0X02,0X1A,0X22,0X95,0X08,0X16,0X29,0XD9,0X0A,0X51}, .expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E}, .frame_len=167, .raw_payload_len=159, @@ -48,7 +48,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X88,0X82,0X71,0X1D,0X00,0XFE,0X72,0XF6}, + .frame={0X88,0X82,0X6B,0X33,0X77,0X94,0X68,0XD8}, .expectedDecodeBuf={0X03,0XEB}, .frame_len=8, .raw_payload_len=2, @@ -60,7 +60,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X88,0XAD,0XD0,0X8D,0X26,0XD8,0XD3,0X66,0X6F,0XFF,0XBD,0XAD,0X47,0XF8,0XB3,0XE1,0X49,0XAB,0XB5,0XAD,0X54,0XBD,0XB1,0XFE,0X49,0XB6,0XF0,0XEC,0X48,0XBC,0XF0,0XE0,0X53,0XBB,0XB8,0XAD,0X4B,0XB7,0XA2,0XE8,0X06,0XAC,0XB8,0XEC,0X48,0XF8,0XA4,0XE5,0X47,0XAC,0XF1}, + .frame={0X88,0XAD,0X4B,0XA1,0XCE,0XE8,0X48,0X4A,0X87,0XCF,0X26,0X81,0XAF,0XC8,0X28,0XCD,0XA1,0X9B,0X2E,0X81,0XBC,0X8D,0X2A,0XD2,0XA1,0X86,0X6B,0XC0,0XA0,0X8C,0X6B,0XCC,0XBB,0X8B,0X23,0X81,0XA3,0X87,0X39,0XC4,0XEE,0X9C,0X23,0XC0,0XA0,0XC8,0X3F,0XC9,0XAF,0X9C,0X6A}, .expectedDecodeBuf={0X03,0XEB,0X49,0X27,0X6D,0X20,0X61,0X20,0X63,0X6C,0X6F,0X73,0X65,0X20,0X72,0X65,0X61,0X73,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X68,0X61,0X6E,0X20,0X74,0X68,0X61,0X74,0X21}, .frame_len=51, .raw_payload_len=45, @@ -84,7 +84,7 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X81,0XFE,0X00,0X0F,0X24,0X22,0X8D,0X9C,0X11,0X6F,0XA3,0XC6,0X6E,0X4E,0X88,0XB0,0X48,0X55,0XA2,0XC6,0X72,0X56}, + .frame={0X81,0XFE,0X00,0X0F,0X71,0XE9,0X29,0X79,0X44,0XA4,0X07,0X23,0X3B,0X85,0X2C,0X55,0X1D,0X9E,0X06,0X23,0X27,0X9D}, .expectedDecodeBuf={0X2E,0XFE,0X00,0X0F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, .frame_len=22, .raw_payload_len=12, @@ -96,8 +96,8 @@ struct ws_frame_test tests[] = { .close_sock_at=0 }, { - .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X7D,0XBB,0X03,0X56,0X7D,0XBB,0X03,0X56,0X7C,0X83,0X2D,0X0C,0X03,0XA2,0X06,0X7A,0X25,0XB9,0X2C,0X0C,0X1F,0XBA}, - .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X4C,0X6F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, + .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X40,0X2F,0X40,0XF3,0X5B,0X2F,0X40,0XF2,0X63,0X01,0X1A,0X8D,0X42,0X2A,0X6C,0XAB,0X59,0X00,0X1A,0X91,0X5A}, + .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X40,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D}, .frame_len=30, .raw_payload_len=18, .expected_errno=EPROTO, @@ -106,5 +106,41 @@ struct ws_frame_test tests[] = { .simulate_sock_malfunction_at=0, .errno_val=0, .close_sock_at=0 + }, + { + .frame={0X01,0XAC,0XC9,0X6E,0XC7,0X6E,0X9F,0X29,0XAF,0X1E,0XAA,0X17,0X85,0X1E,0XAA,0X17,0X85,0X06,0X80,0X29,0X9D,0X17,0X90,0X39,0XA3,0X1A,0X93,0X39,0XF2,0X5E,0X93,0X39,0X96,0X09,0XAD,0X5C,0X91,0X07,0XAA,0X5C,0XFE,0X04,0XA8,0X5C,0X91,0X5E,0X85,0X07,0XF3,0X1B}, + .expectedDecodeBuf={0X54,0X68,0X69,0X73,0X20,0X69,0X73,0X20,0X61,0X20,0X66,0X72,0X61,0X67,0X6D,0X65,0X6E,0X74,0X65,0X64,0X20,0X77,0X65,0X62,0X73,0X6F,0X63,0X6B,0X65,0X74,0X2E,0X2E,0X2E}, + .frame_len=50, + .raw_payload_len=33, + .expected_errno=0, + .descr="Continuation test frag1", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X00,0X9C,0X52,0XBC,0XD5,0X99,0X1E,0XD5,0XE1,0XEC,0X1B,0XFB,0X93,0XEC,0X08,0XFF,0X97,0XE9,0X36,0XFF,0X97,0XF7,0X30,0X8E,0X83,0XE3,0X1B,0XFB,0XEC,0XEC,0X1E,0XD5,0XE1,0XEC}, + .expectedDecodeBuf={0X2E,0X2E,0X2E,0X20,0X61,0X6E,0X64,0X20,0X69,0X74,0X20,0X67,0X6F,0X65,0X73,0X20,0X6F,0X6E,0X2E,0X2E,0X2E}, + .frame_len=34, + .raw_payload_len=21, + .expected_errno=0, + .descr="Continuation test frag2", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 + }, + { + .frame={0X80,0X94,0X3B,0X88,0XA1,0XE9,0X62,0XDF,0X94,0X82,0X72,0XCF,0X98,0X9C,0X72,0XCF,0XE7,0X9C,0X61,0XCB,0XE3,0X93,0X5F,0XCF,0X98,0X9E}, + .expectedDecodeBuf={0X61,0X6E,0X64,0X20,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X73,0X74,0X6F,0X70}, + .frame_len=26, + .raw_payload_len=15, + .expected_errno=0, + .descr="Continuation test frag3", + .i=0, + .simulate_sock_malfunction_at=0, + .errno_val=0, + .close_sock_at=0 } }; -- cgit v1.2.3 From 716bd27235fe6462271e799a758f2682fa4cb1de Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 28 Nov 2018 21:08:15 +0100 Subject: Fix -Wmisleading-indentation warnings --- common/turbojpeg.c | 6 ++++-- common/vncauth.c | 5 +++-- libvncserver/tableinit24.c | 11 ++++++----- libvncserver/websockets.c | 11 +++++++---- test/tjbench.c | 15 +++++++++------ 5 files changed, 29 insertions(+), 19 deletions(-) (limited to 'test') diff --git a/common/turbojpeg.c b/common/turbojpeg.c index 09df173..934e4f1 100644 --- a/common/turbojpeg.c +++ b/common/turbojpeg.c @@ -468,7 +468,8 @@ static tjhandle _tjInitCompress(tjinstance *this) if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - if(this) free(this); return NULL; + if(this) free(this); + return NULL; } jpeg_create_compress(&this->cinfo); @@ -652,7 +653,8 @@ static tjhandle _tjInitDecompress(tjinstance *this) if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - if(this) free(this); return NULL; + if(this) free(this); + return NULL; } jpeg_create_decompress(&this->dinfo); diff --git a/common/vncauth.c b/common/vncauth.c index 2a5d96f..81bb10b 100644 --- a/common/vncauth.c +++ b/common/vncauth.c @@ -207,8 +207,9 @@ rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) { where[i] ^= key[i]; rfbDes(where, where); for (i = 8; i < length; i += 8) { - for (j = 0; j < 8; j++) + for (j = 0; j < 8; j++) { where[i + j] ^= where[i + j - 8]; - rfbDes(where + i, where + i); + } + rfbDes(where + i, where + i); } } diff --git a/libvncserver/tableinit24.c b/libvncserver/tableinit24.c index 39e9920..5c5823c 100644 --- a/libvncserver/tableinit24.c +++ b/libvncserver/tableinit24.c @@ -147,11 +147,12 @@ rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift, for (i = 0; i < nEntries; i++) { outValue = ((i * outMax + inMax / 2) / inMax) << outShift; *(uint32_t *)&table[3*i] = outValue; - if(!rfbEndianTest) + if(!rfbEndianTest) { memmove(table+3*i,table+3*i+1,3); - if (swap) { - c = table[3*i]; table[3*i] = table[3*i+2]; - table[3*i+2] = c; - } + } + if (swap) { + c = table[3*i]; table[3*i] = table[3*i+2]; + table[3*i+2] = c; + } } } diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c index d91c4f2..616c81c 100644 --- a/libvncserver/websockets.c +++ b/libvncserver/websockets.c @@ -198,12 +198,15 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme) if ((n < 0) && (errno == ETIMEDOUT)) { break; } - if (n == 0) + if (n == 0) { rfbLog("webSocketsHandshake: client gone\n"); - else + } + else { rfbLogPerror("webSocketsHandshake: read"); - free(response); - free(buf); + } + + free(response); + free(buf); return FALSE; } diff --git a/test/tjbench.c b/test/tjbench.c index 29aa153..87e1591 100644 --- a/test/tjbench.c +++ b/test/tjbench.c @@ -178,7 +178,8 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, int y=(int)((double)srcbuf[rindex]*0.299 + (double)srcbuf[gindex]*0.587 + (double)srcbuf[bindex]*0.114 + 0.5); - if(y>255) y=255; if(y<0) y=0; + if(y>255) y=255; + if(y<0) y=0; dstbuf[rindex]=abs(dstbuf[rindex]-y); dstbuf[gindex]=abs(dstbuf[gindex]-y); dstbuf[bindex]=abs(dstbuf[bindex]-y); @@ -226,7 +227,8 @@ void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) { - if(tilew>w) tilew=w; if(tileh>h) tileh=h; + if(tilew>w) tilew=w; + if(tileh>h) tileh=h; ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) @@ -323,7 +325,7 @@ void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, for(i=0; iw) tilew=w; if(tileh>h) tileh=h; + if(tilew>w) tilew=w; + if(tileh>h) tileh=h; ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) @@ -455,7 +458,7 @@ void dodecomptest(char *filename) { for(i=0; i