From fc8321956360267fac10630fa1324c28b840dc89 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 14 Apr 2020 09:38:30 +0000 Subject: Backport test-cases from 8.6 --- generic/tclTest.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++---- tests/utf.test | 40 +++++++++++++++++++++++-------- 2 files changed, 95 insertions(+), 15 deletions(-) diff --git a/generic/tclTest.c b/generic/tclTest.c index 506cef9..31d3a7f 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -437,6 +437,12 @@ static Tcl_ObjCmdProc TestUtfPrevCmd; static int TestNumUtfCharsCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +static int TestFindFirstCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int TestFindLastCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static int TestHashSystemHashCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -690,11 +696,15 @@ Tcltest_Init( Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testsetobjerrorcode", - TestsetobjerrorcodeCmd, (ClientData) 0, NULL); + TestsetobjerrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testutfprev", TestUtfPrevCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand(interp, "testnumutfchars", - TestNumUtfCharsCmd, (ClientData) 0, NULL); + TestNumUtfCharsCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "testfindfirst", + TestFindFirstCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "testfindlast", + TestFindLastCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, (ClientData) 0, NULL); Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd, @@ -7157,17 +7167,67 @@ TestNumUtfCharsCmd( Tcl_Obj *const objv[]) { if (objc > 1) { - int len = -1; + int numBytes, len, limit = -1; + const char *bytes = Tcl_GetStringFromObj(objv[1], &numBytes); if (objc > 2) { - (void) Tcl_GetStringFromObj(objv[1], &len); + if (TclGetIntForIndex(interp, objv[2], numBytes, &limit) != TCL_OK) { + return TCL_ERROR; + } + if (limit > numBytes + 1) { + limit = numBytes + 1; + } } - len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len); + len = Tcl_NumUtfChars(bytes, limit); Tcl_SetObjResult(interp, Tcl_NewIntObj(len)); } return TCL_OK; } +/* + * Used to check correct operation of Tcl_UtfFindFirst + */ + +static int +TestFindFirstCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + if (objc > 1) { + int len = -1; + + if (objc > 2) { + (void) Tcl_GetIntFromObj(interp, objv[2], &len); + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindFirst(Tcl_GetString(objv[1]), len), -1)); + } + return TCL_OK; +} + +/* + * Used to check correct operation of Tcl_UtfFindLast + */ + +static int +TestFindLastCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + if (objc > 1) { + int len = -1; + + if (objc > 2) { + (void) Tcl_GetIntFromObj(interp, objv[2], &len); + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1)); + } + return TCL_OK; +} + #if defined(HAVE_CPUID) || defined(__WIN32__) /* *---------------------------------------------------------------------- diff --git a/tests/utf.test b/tests/utf.test index c2191c2..56ca1b9 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -63,6 +63,9 @@ test utf-3.1 {Tcl_UtfCharComplete} { } {} testConstraint testnumutfchars [llength [info commands testnumutfchars]] +testConstraint testfindfirst [llength [info commands testfindfirst]] +testConstraint testfindlast [llength [info commands testfindlast]] + test utf-4.1 {Tcl_NumUtfChars: zero length} testnumutfchars { testnumutfchars "" } {0} @@ -76,20 +79,37 @@ test utf-4.4 {Tcl_NumUtfChars: #u0000} testnumutfchars { testnumutfchars [bytestring "\xC0\x80"] } {1} test utf-4.5 {Tcl_NumUtfChars: zero length, calc len} testnumutfchars { - testnumutfchars "" 1 + testnumutfchars "" 0 } {0} test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} testnumutfchars { testnumutfchars [bytestring "\xC2\xA2"] 1 } {1} test utf-4.7 {Tcl_NumUtfChars: long string, calc len} testnumutfchars { - testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 1 + testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 10 } {7} test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} testnumutfchars { testnumutfchars [bytestring "\xC0\x80"] 1 } {1} +# Bug [2738427]: Tcl_NumUtfChars(...) no overflow check +test utf-4.9 {Tcl_NumUtfChars: #u20AC, calc len, incomplete} testnumutfchars { + testnumutfchars [bytestring "\xE2\x82\xAC"] 2 +} {2} +test utf-4.10 {Tcl_NumUtfChars: #u0000, calc len, overcomplete} testnumutfchars { + testnumutfchars [bytestring "\x00"] 2 +} {2} +test utf-4.11 {Tcl_NumUtfChars: 3 bytes of 4-byte UTF-8 characater} testnumutfchars { + testnumutfchars [bytestring \xf0\x9f\x92\xa9] 3 +} {3} +test utf-4.12 {Tcl_NumUtfChars: #4-byte UTF-8 character} testnumutfchars { + testnumutfchars [bytestring \xf0\x9f\x92\xa9] 4 +} {4} -test utf-5.1 {Tcl_UtfFindFirsts} { -} {} +test utf-5.1 {Tcl_UtfFindFirst} testfindfirst { + testfindfirst [bytestring "abcbc"] 98 +} {bcbc} +test utf-5.2 {Tcl_UtfFindLast} testfindlast { + testfindlast [bytestring "abcbc"] 98 +} {bc} test utf-6.1 {Tcl_UtfNext} { } {} @@ -260,21 +280,21 @@ test utf-8.1 {Tcl_UniCharAtIndex: index = 0} { string index abcd 0 } {a} test utf-8.2 {Tcl_UniCharAtIndex: index = 0} { - string index \u4e4e\u25a 0 -} "\u4e4e" + string index \u4E4E\u25A 0 +} "\u4E4E" test utf-8.3 {Tcl_UniCharAtIndex: index > 0} { string index abcd 2 } {c} test utf-8.4 {Tcl_UniCharAtIndex: index > 0} { - string index \u4e4e\u25a\xff\u543 2 -} "\uff" + string index \u4E4E\u25A\xFF\u543 2 +} "\uFF" test utf-9.1 {Tcl_UtfAtIndex: index = 0} { string range abcd 0 2 } {abc} test utf-9.2 {Tcl_UtfAtIndex: index > 0} { - string range \u4e4e\u25a\xff\u543klmnop 1 5 -} "\u25a\xff\u543kl" + string range \u4E4E\u25A\xFF\u543klmnop 1 5 +} "\u25A\xFF\u543kl" test utf-10.1 {Tcl_UtfBackslash: dst == NULL} { -- cgit v0.12