From 3e3f2b135495753cad09a1f4bcaec5e460557e6f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 11 Mar 2019 20:30:28 +0000 Subject: Improve parsing of -xchar option for serial channels: Allow full 8-bit range (correct UTF-8 handling), and let UNIX/win32 produce the same error-message in case of char > 0xFF --- unix/tclUnixChan.c | 30 +++++++++++++++++++----------- win/tclWinSerial.c | 16 ++++++++-------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 435579a..673e4cd 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -654,17 +654,15 @@ TtySetOptionProc( */ if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) { - Tcl_DString ds; - if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } else if (argc != 2) { + badXchar: if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -xchar: should be a list of" - " two elements", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE", - "VALUE", NULL); + " two elements with each a single 8-bit character", -1)); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", NULL); } ckfree(argv); return TCL_ERROR; @@ -672,13 +670,23 @@ TtySetOptionProc( tcgetattr(fsPtr->fd, &iostate); - Tcl_UtfToExternalDString(NULL, argv[0], -1, &ds); - iostate.c_cc[VSTART] = *(const cc_t *) Tcl_DStringValue(&ds); - TclDStringClear(&ds); + iostate.c_cc[VSTART] = argv[0][0]; + iostate.c_cc[VSTOP] = argv[1][0]; + if (argv[0][0] & 0x80 || argv[1][0] & 0x80) { + Tcl_UniChar character = 0; + int charLen; - Tcl_UtfToExternalDString(NULL, argv[1], -1, &ds); - iostate.c_cc[VSTOP] = *(const cc_t *) Tcl_DStringValue(&ds); - Tcl_DStringFree(&ds); + charLen = Tcl_UtfToUniChar(argv[0], &character); + if ((character > 0xFF) || argv[0][charLen]) { + goto badXchar; + } + iostate.c_cc[VSTART] = character; + charLen = Tcl_UtfToUniChar(argv[1], &character); + if ((character > 0xFF) || argv[1][charLen]) { + goto badXchar; + } + iostate.c_cc[VSTOP] = character; + } ckfree(argv); tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c index 8ee426b..2a2c445 100644 --- a/win/tclWinSerial.c +++ b/win/tclWinSerial.c @@ -1368,7 +1368,7 @@ SerialWriterThread( HANDLE TclWinSerialOpen( HANDLE handle, - const TCHAR *name, + const WCHAR *name, DWORD access) { SerialInit(); @@ -1595,7 +1595,7 @@ SerialSetOptionProc( BOOL result, flag; size_t len, vlen; Tcl_DString ds; - const TCHAR *native; + const WCHAR *native; int argc; const char **argv; @@ -1718,7 +1718,7 @@ SerialSetOptionProc( if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -xchar: should be a list of" - " two elements with each a single character", -1)); + " two elements with each a single 8-bit character", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", NULL); } ckfree(argv); @@ -1742,12 +1742,12 @@ SerialSetOptionProc( int charLen; charLen = Tcl_UtfToUniChar(argv[0], &character); - if (argv[0][charLen]) { + if ((character > 0xFF) || argv[0][charLen]) { goto badXchar; } dcb.XonChar = (char) character; charLen = Tcl_UtfToUniChar(argv[1], &character); - if (argv[1][charLen]) { + if ((character > 0xFF) || argv[1][charLen]) { goto badXchar; } dcb.XoffChar = (char) character; @@ -2077,7 +2077,7 @@ SerialGetOptionProc( Tcl_DStringStartSublist(dsPtr); } if (len==0 || (len>1 && strncmp(optionName, "-xchar", len) == 0)) { - char buf[4]; + char buf[TCL_UTF_MAX]; valid = 1; if (!GetCommState(infoPtr->handle, &dcb)) { @@ -2088,9 +2088,9 @@ SerialGetOptionProc( } return TCL_ERROR; } - sprintf(buf, "%c", dcb.XonChar); + buf[Tcl_UniCharToUtf(UCHAR(dcb.XonChar), buf)] = '\0'; Tcl_DStringAppendElement(dsPtr, buf); - sprintf(buf, "%c", dcb.XoffChar); + buf[Tcl_UniCharToUtf(UCHAR(dcb.XoffChar), buf)] = '\0'; Tcl_DStringAppendElement(dsPtr, buf); } if (len == 0) { -- cgit v0.12