Fossil SCM
Preserve taint across TH1 commands: foreach, lappend, lindex, string index, string range, and string trim. Add test cases for taint.
Commit
5291edac072416b1a9fda05d6fc73e20e99cb0076676d6627d1cb4530495b351
Parent
6a2fee8fd470160…
2 files changed
+19
-4
+84
+19
-4
| --- src/th_lang.c | ||
| +++ src/th_lang.c | ||
| @@ -180,20 +180,24 @@ | ||
| 180 | 180 | int nVar; |
| 181 | 181 | char **azValue = 0; |
| 182 | 182 | int *anValue; |
| 183 | 183 | int nValue; |
| 184 | 184 | int ii, jj; |
| 185 | + int bTaint = 0; | |
| 185 | 186 | |
| 186 | 187 | if( argc!=4 ){ |
| 187 | 188 | return Th_WrongNumArgs(interp, "foreach varlist list script"); |
| 188 | 189 | } |
| 189 | 190 | rc = Th_SplitList(interp, argv[1], argl[1], &azVar, &anVar, &nVar); |
| 190 | 191 | if( rc ) return rc; |
| 192 | + TH1_XFER_TAINT(bTaint, argl[2]); | |
| 191 | 193 | rc = Th_SplitList(interp, argv[2], argl[2], &azValue, &anValue, &nValue); |
| 192 | 194 | for(ii=0; rc==TH_OK && ii<=nValue-nVar; ii+=nVar){ |
| 193 | 195 | for(jj=0; jj<nVar; jj++){ |
| 194 | - Th_SetVar(interp, azVar[jj], anVar[jj], azValue[ii+jj], anValue[ii+jj]); | |
| 196 | + int x = anValue[ii+jj]; | |
| 197 | + TH1_XFER_TAINT(x, bTaint); | |
| 198 | + Th_SetVar(interp, azVar[jj], anVar[jj], azValue[ii+jj], x); | |
| 195 | 199 | } |
| 196 | 200 | rc = eval_loopbody(interp, argv[3], argl[3]); |
| 197 | 201 | } |
| 198 | 202 | if( rc==TH_BREAK ) rc = TH_OK; |
| 199 | 203 | Th_Free(interp, azVar); |
| @@ -257,10 +261,11 @@ | ||
| 257 | 261 | rc = Th_GetVar(interp, argv[1], argl[1]); |
| 258 | 262 | if( rc==TH_OK ){ |
| 259 | 263 | zList = Th_TakeResult(interp, &nList); |
| 260 | 264 | } |
| 261 | 265 | |
| 266 | + TH1_XFER_TAINT(bTaint, nList); | |
| 262 | 267 | for(i=2; i<argc; i++){ |
| 263 | 268 | TH1_XFER_TAINT(bTaint, argl[i]); |
| 264 | 269 | Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]); |
| 265 | 270 | } |
| 266 | 271 | |
| @@ -289,23 +294,27 @@ | ||
| 289 | 294 | int rc; |
| 290 | 295 | |
| 291 | 296 | char **azElem; |
| 292 | 297 | int *anElem; |
| 293 | 298 | int nCount; |
| 299 | + int bTaint = 0; | |
| 294 | 300 | |
| 295 | 301 | if( argc!=3 ){ |
| 296 | 302 | return Th_WrongNumArgs(interp, "lindex list index"); |
| 297 | 303 | } |
| 298 | 304 | |
| 299 | 305 | if( TH_OK!=Th_ToInt(interp, argv[2], argl[2], &iElem) ){ |
| 300 | 306 | return TH_ERROR; |
| 301 | 307 | } |
| 302 | 308 | |
| 309 | + TH1_XFER_TAINT(bTaint, argl[1]); | |
| 303 | 310 | rc = Th_SplitList(interp, argv[1], argl[1], &azElem, &anElem, &nCount); |
| 304 | 311 | if( rc==TH_OK ){ |
| 305 | 312 | if( iElem<nCount && iElem>=0 ){ |
| 306 | - Th_SetResult(interp, azElem[iElem], anElem[iElem]); | |
| 313 | + int sz = anElem[iElem]; | |
| 314 | + TH1_XFER_TAINT(sz, bTaint); | |
| 315 | + Th_SetResult(interp, azElem[iElem], sz); | |
| 307 | 316 | }else{ |
| 308 | 317 | Th_SetResult(interp, 0, 0); |
| 309 | 318 | } |
| 310 | 319 | Th_Free(interp, azElem); |
| 311 | 320 | } |
| @@ -832,11 +841,13 @@ | ||
| 832 | 841 | interp, "Expected \"end\" or integer, got:", argv[3], argl[3]); |
| 833 | 842 | return TH_ERROR; |
| 834 | 843 | } |
| 835 | 844 | |
| 836 | 845 | if( iIndex>=0 && iIndex<TH1_LEN(argl[2]) ){ |
| 837 | - return Th_SetResult(interp, &argv[2][iIndex], 1); | |
| 846 | + int sz = 1; | |
| 847 | + TH1_XFER_TAINT(sz, argl[2]); | |
| 848 | + return Th_SetResult(interp, &argv[2][iIndex], sz); | |
| 838 | 849 | }else{ |
| 839 | 850 | return Th_SetResult(interp, 0, 0); |
| 840 | 851 | } |
| 841 | 852 | } |
| 842 | 853 | |
| @@ -970,10 +981,11 @@ | ||
| 970 | 981 | static int string_range_command( |
| 971 | 982 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 972 | 983 | ){ |
| 973 | 984 | int iStart; |
| 974 | 985 | int iEnd; |
| 986 | + int sz; | |
| 975 | 987 | |
| 976 | 988 | if( argc!=5 ){ |
| 977 | 989 | return Th_WrongNumArgs(interp, "string range string first last"); |
| 978 | 990 | } |
| 979 | 991 | |
| @@ -989,12 +1001,14 @@ | ||
| 989 | 1001 | } |
| 990 | 1002 | |
| 991 | 1003 | if( iStart<0 ) iStart = 0; |
| 992 | 1004 | if( iEnd>=TH1_LEN(argl[2]) ) iEnd = TH1_LEN(argl[2])-1; |
| 993 | 1005 | if( iStart>iEnd ) iEnd = iStart-1; |
| 1006 | + sz = iEnd - iStart + 1; | |
| 1007 | + TH1_XFER_TAINT(sz, argl[2]); | |
| 994 | 1008 | |
| 995 | - return Th_SetResult(interp, &argv[2][iStart], iEnd-iStart+1); | |
| 1009 | + return Th_SetResult(interp, &argv[2][iStart], sz); | |
| 996 | 1010 | } |
| 997 | 1011 | |
| 998 | 1012 | /* |
| 999 | 1013 | ** TH Syntax: |
| 1000 | 1014 | ** |
| @@ -1054,10 +1068,11 @@ | ||
| 1054 | 1068 | while( n && th_isspace(z[0]) ){ z++; n--; } |
| 1055 | 1069 | } |
| 1056 | 1070 | if( TH1_LEN(argl[1])<5 || argv[1][4]=='r' ){ |
| 1057 | 1071 | while( n && th_isspace(z[n-1]) ){ n--; } |
| 1058 | 1072 | } |
| 1073 | + TH1_XFER_TAINT(n, argl[2]); | |
| 1059 | 1074 | Th_SetResult(interp, z, n); |
| 1060 | 1075 | return TH_OK; |
| 1061 | 1076 | } |
| 1062 | 1077 | |
| 1063 | 1078 | /* |
| 1064 | 1079 | |
| 1065 | 1080 | ADDED test/th1-taint.test |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -180,20 +180,24 @@ | |
| 180 | int nVar; |
| 181 | char **azValue = 0; |
| 182 | int *anValue; |
| 183 | int nValue; |
| 184 | int ii, jj; |
| 185 | |
| 186 | if( argc!=4 ){ |
| 187 | return Th_WrongNumArgs(interp, "foreach varlist list script"); |
| 188 | } |
| 189 | rc = Th_SplitList(interp, argv[1], argl[1], &azVar, &anVar, &nVar); |
| 190 | if( rc ) return rc; |
| 191 | rc = Th_SplitList(interp, argv[2], argl[2], &azValue, &anValue, &nValue); |
| 192 | for(ii=0; rc==TH_OK && ii<=nValue-nVar; ii+=nVar){ |
| 193 | for(jj=0; jj<nVar; jj++){ |
| 194 | Th_SetVar(interp, azVar[jj], anVar[jj], azValue[ii+jj], anValue[ii+jj]); |
| 195 | } |
| 196 | rc = eval_loopbody(interp, argv[3], argl[3]); |
| 197 | } |
| 198 | if( rc==TH_BREAK ) rc = TH_OK; |
| 199 | Th_Free(interp, azVar); |
| @@ -257,10 +261,11 @@ | |
| 257 | rc = Th_GetVar(interp, argv[1], argl[1]); |
| 258 | if( rc==TH_OK ){ |
| 259 | zList = Th_TakeResult(interp, &nList); |
| 260 | } |
| 261 | |
| 262 | for(i=2; i<argc; i++){ |
| 263 | TH1_XFER_TAINT(bTaint, argl[i]); |
| 264 | Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]); |
| 265 | } |
| 266 | |
| @@ -289,23 +294,27 @@ | |
| 289 | int rc; |
| 290 | |
| 291 | char **azElem; |
| 292 | int *anElem; |
| 293 | int nCount; |
| 294 | |
| 295 | if( argc!=3 ){ |
| 296 | return Th_WrongNumArgs(interp, "lindex list index"); |
| 297 | } |
| 298 | |
| 299 | if( TH_OK!=Th_ToInt(interp, argv[2], argl[2], &iElem) ){ |
| 300 | return TH_ERROR; |
| 301 | } |
| 302 | |
| 303 | rc = Th_SplitList(interp, argv[1], argl[1], &azElem, &anElem, &nCount); |
| 304 | if( rc==TH_OK ){ |
| 305 | if( iElem<nCount && iElem>=0 ){ |
| 306 | Th_SetResult(interp, azElem[iElem], anElem[iElem]); |
| 307 | }else{ |
| 308 | Th_SetResult(interp, 0, 0); |
| 309 | } |
| 310 | Th_Free(interp, azElem); |
| 311 | } |
| @@ -832,11 +841,13 @@ | |
| 832 | interp, "Expected \"end\" or integer, got:", argv[3], argl[3]); |
| 833 | return TH_ERROR; |
| 834 | } |
| 835 | |
| 836 | if( iIndex>=0 && iIndex<TH1_LEN(argl[2]) ){ |
| 837 | return Th_SetResult(interp, &argv[2][iIndex], 1); |
| 838 | }else{ |
| 839 | return Th_SetResult(interp, 0, 0); |
| 840 | } |
| 841 | } |
| 842 | |
| @@ -970,10 +981,11 @@ | |
| 970 | static int string_range_command( |
| 971 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 972 | ){ |
| 973 | int iStart; |
| 974 | int iEnd; |
| 975 | |
| 976 | if( argc!=5 ){ |
| 977 | return Th_WrongNumArgs(interp, "string range string first last"); |
| 978 | } |
| 979 | |
| @@ -989,12 +1001,14 @@ | |
| 989 | } |
| 990 | |
| 991 | if( iStart<0 ) iStart = 0; |
| 992 | if( iEnd>=TH1_LEN(argl[2]) ) iEnd = TH1_LEN(argl[2])-1; |
| 993 | if( iStart>iEnd ) iEnd = iStart-1; |
| 994 | |
| 995 | return Th_SetResult(interp, &argv[2][iStart], iEnd-iStart+1); |
| 996 | } |
| 997 | |
| 998 | /* |
| 999 | ** TH Syntax: |
| 1000 | ** |
| @@ -1054,10 +1068,11 @@ | |
| 1054 | while( n && th_isspace(z[0]) ){ z++; n--; } |
| 1055 | } |
| 1056 | if( TH1_LEN(argl[1])<5 || argv[1][4]=='r' ){ |
| 1057 | while( n && th_isspace(z[n-1]) ){ n--; } |
| 1058 | } |
| 1059 | Th_SetResult(interp, z, n); |
| 1060 | return TH_OK; |
| 1061 | } |
| 1062 | |
| 1063 | /* |
| 1064 | |
| 1065 | DDED test/th1-taint.test |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -180,20 +180,24 @@ | |
| 180 | int nVar; |
| 181 | char **azValue = 0; |
| 182 | int *anValue; |
| 183 | int nValue; |
| 184 | int ii, jj; |
| 185 | int bTaint = 0; |
| 186 | |
| 187 | if( argc!=4 ){ |
| 188 | return Th_WrongNumArgs(interp, "foreach varlist list script"); |
| 189 | } |
| 190 | rc = Th_SplitList(interp, argv[1], argl[1], &azVar, &anVar, &nVar); |
| 191 | if( rc ) return rc; |
| 192 | TH1_XFER_TAINT(bTaint, argl[2]); |
| 193 | rc = Th_SplitList(interp, argv[2], argl[2], &azValue, &anValue, &nValue); |
| 194 | for(ii=0; rc==TH_OK && ii<=nValue-nVar; ii+=nVar){ |
| 195 | for(jj=0; jj<nVar; jj++){ |
| 196 | int x = anValue[ii+jj]; |
| 197 | TH1_XFER_TAINT(x, bTaint); |
| 198 | Th_SetVar(interp, azVar[jj], anVar[jj], azValue[ii+jj], x); |
| 199 | } |
| 200 | rc = eval_loopbody(interp, argv[3], argl[3]); |
| 201 | } |
| 202 | if( rc==TH_BREAK ) rc = TH_OK; |
| 203 | Th_Free(interp, azVar); |
| @@ -257,10 +261,11 @@ | |
| 261 | rc = Th_GetVar(interp, argv[1], argl[1]); |
| 262 | if( rc==TH_OK ){ |
| 263 | zList = Th_TakeResult(interp, &nList); |
| 264 | } |
| 265 | |
| 266 | TH1_XFER_TAINT(bTaint, nList); |
| 267 | for(i=2; i<argc; i++){ |
| 268 | TH1_XFER_TAINT(bTaint, argl[i]); |
| 269 | Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]); |
| 270 | } |
| 271 | |
| @@ -289,23 +294,27 @@ | |
| 294 | int rc; |
| 295 | |
| 296 | char **azElem; |
| 297 | int *anElem; |
| 298 | int nCount; |
| 299 | int bTaint = 0; |
| 300 | |
| 301 | if( argc!=3 ){ |
| 302 | return Th_WrongNumArgs(interp, "lindex list index"); |
| 303 | } |
| 304 | |
| 305 | if( TH_OK!=Th_ToInt(interp, argv[2], argl[2], &iElem) ){ |
| 306 | return TH_ERROR; |
| 307 | } |
| 308 | |
| 309 | TH1_XFER_TAINT(bTaint, argl[1]); |
| 310 | rc = Th_SplitList(interp, argv[1], argl[1], &azElem, &anElem, &nCount); |
| 311 | if( rc==TH_OK ){ |
| 312 | if( iElem<nCount && iElem>=0 ){ |
| 313 | int sz = anElem[iElem]; |
| 314 | TH1_XFER_TAINT(sz, bTaint); |
| 315 | Th_SetResult(interp, azElem[iElem], sz); |
| 316 | }else{ |
| 317 | Th_SetResult(interp, 0, 0); |
| 318 | } |
| 319 | Th_Free(interp, azElem); |
| 320 | } |
| @@ -832,11 +841,13 @@ | |
| 841 | interp, "Expected \"end\" or integer, got:", argv[3], argl[3]); |
| 842 | return TH_ERROR; |
| 843 | } |
| 844 | |
| 845 | if( iIndex>=0 && iIndex<TH1_LEN(argl[2]) ){ |
| 846 | int sz = 1; |
| 847 | TH1_XFER_TAINT(sz, argl[2]); |
| 848 | return Th_SetResult(interp, &argv[2][iIndex], sz); |
| 849 | }else{ |
| 850 | return Th_SetResult(interp, 0, 0); |
| 851 | } |
| 852 | } |
| 853 | |
| @@ -970,10 +981,11 @@ | |
| 981 | static int string_range_command( |
| 982 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 983 | ){ |
| 984 | int iStart; |
| 985 | int iEnd; |
| 986 | int sz; |
| 987 | |
| 988 | if( argc!=5 ){ |
| 989 | return Th_WrongNumArgs(interp, "string range string first last"); |
| 990 | } |
| 991 | |
| @@ -989,12 +1001,14 @@ | |
| 1001 | } |
| 1002 | |
| 1003 | if( iStart<0 ) iStart = 0; |
| 1004 | if( iEnd>=TH1_LEN(argl[2]) ) iEnd = TH1_LEN(argl[2])-1; |
| 1005 | if( iStart>iEnd ) iEnd = iStart-1; |
| 1006 | sz = iEnd - iStart + 1; |
| 1007 | TH1_XFER_TAINT(sz, argl[2]); |
| 1008 | |
| 1009 | return Th_SetResult(interp, &argv[2][iStart], sz); |
| 1010 | } |
| 1011 | |
| 1012 | /* |
| 1013 | ** TH Syntax: |
| 1014 | ** |
| @@ -1054,10 +1068,11 @@ | |
| 1068 | while( n && th_isspace(z[0]) ){ z++; n--; } |
| 1069 | } |
| 1070 | if( TH1_LEN(argl[1])<5 || argv[1][4]=='r' ){ |
| 1071 | while( n && th_isspace(z[n-1]) ){ n--; } |
| 1072 | } |
| 1073 | TH1_XFER_TAINT(n, argl[2]); |
| 1074 | Th_SetResult(interp, z, n); |
| 1075 | return TH_OK; |
| 1076 | } |
| 1077 | |
| 1078 | /* |
| 1079 | |
| 1080 | DDED test/th1-taint.test |
+84
| --- a/test/th1-taint.test | ||
| +++ b/test/th1-taint.test | ||
| @@ -0,0 +1,84 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2025 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# TH1 Commands | |
| 19 | +# | |
| 20 | + | |
| 21 | +set path [file dirname [info script]]; test_setup | |
| 22 | + | |
| 23 | +proc taint-test {testnum th1script expected} { | |
| 24 | + global fossilexe | |
| 25 | + set rc [catch {exec $fossilexe test-th-eval $th1script} got] | |
| 26 | + if {$rc} { | |
| 27 | + test th1-taint-$testnum 0 | |
| 28 | + puts $got | |
| 29 | + return | |
| 30 | + } | |
| 31 | + if {$got ne $expected} { | |
| 32 | + test th1-taint-$testnum 0 | |
| 33 | + puts " Expected: $expected" | |
| 34 | + puts " Got: $got" | |
| 35 | + } else { | |
| 36 | + test th1-taint-$testnum 1 | |
| 37 | + } | |
| 38 | +} | |
| 39 | + | |
| 40 | +taint-test 10 {string is tainted abcd} 0 | |
| 41 | +taint-test 20 {string is tainted [taint abcd]} 1 | |
| 42 | +taint-test 30 {string is tainted [untaint [taint abcd]]} 0 | |
| 43 | +taint-test 40 {string is tainted [untaint abcde]} 0 | |
| 44 | +taint-test 50 {string is tainted "abc[taint def]ghi"} 1 | |
| 45 | +taint-test 60 {set t1 [taint abc]; string is tainted "123 $t1 456"} 1 | |
| 46 | + | |
| 47 | +taint-test 100 {set t1 [taint abc]; lappend t1 def; string is tainted $t1} 1 | |
| 48 | +taint-test 110 {set t1 abc; lappend t1 [taint def]; string is tainted $t1} 1 | |
| 49 | + | |
| 50 | +taint-test 200 {string is tainted [list abc def ghi]} 0 | |
| 51 | +taint-test 210 {string is tainted [list [taint abc] def ghi]} 1 | |
| 52 | +taint-test 220 {string is tainted [list abc [taint def] ghi]} 1 | |
| 53 | +taint-test 230 {string is tainted [list abc def [taint ghi]]} 1 | |
| 54 | + | |
| 55 | +taint-test 300 { | |
| 56 | + set res {} | |
| 57 | + foreach x [list abc [taint def] ghi] { | |
| 58 | + lappend res [string is tainted $x] | |
| 59 | + } | |
| 60 | + set res | |
| 61 | +} {1 1 1} | |
| 62 | +taint-test 310 { | |
| 63 | + set res {} | |
| 64 | + foreach {x y} [list abc [taint def] ghi jkl] { | |
| 65 | + lappend res [string is tainted $x] [string is tainted $y] | |
| 66 | + } | |
| 67 | + set res | |
| 68 | +} {1 1 1 1} | |
| 69 | + | |
| 70 | +taint-test 400 {string is tainted [lindex "abc [taint def] ghi" 0]} 1 | |
| 71 | +taint-test 410 {string is tainted [lindex "abc [taint def] ghi" 1]} 1 | |
| 72 | +taint-test 420 {string is tainted [lindex "abc [taint def] ghi" 2]} 1 | |
| 73 | +taint-test 430 {string is tainted [lindex "abc [taint def] ghi" 3]} 0 | |
| 74 | + | |
| 75 | +taint-test 500 {string is tainted [string index [taint abcdefg] 3]} 1 | |
| 76 | + | |
| 77 | +taint-test 600 {string is tainted [string range [taint abcdefg] 3 5]} 1 | |
| 78 | + | |
| 79 | +taint-test 700 {string is tainted [string trim [taint " abcdefg "]]} 1 | |
| 80 | +taint-test 710 {string is tainted [string trimright [taint " abcdefg "]]} 1 | |
| 81 | +taint-test 720 {string is tainted [string trimleft [taint " abcdefg "]]} 1 | |
| 82 | + | |
| 83 | + | |
| 84 | +test_cleanup |
| --- a/test/th1-taint.test | |
| +++ b/test/th1-taint.test | |
| @@ -0,0 +1,84 @@ | |
| --- a/test/th1-taint.test | |
| +++ b/test/th1-taint.test | |
| @@ -0,0 +1,84 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2025 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # TH1 Commands |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]]; test_setup |
| 22 | |
| 23 | proc taint-test {testnum th1script expected} { |
| 24 | global fossilexe |
| 25 | set rc [catch {exec $fossilexe test-th-eval $th1script} got] |
| 26 | if {$rc} { |
| 27 | test th1-taint-$testnum 0 |
| 28 | puts $got |
| 29 | return |
| 30 | } |
| 31 | if {$got ne $expected} { |
| 32 | test th1-taint-$testnum 0 |
| 33 | puts " Expected: $expected" |
| 34 | puts " Got: $got" |
| 35 | } else { |
| 36 | test th1-taint-$testnum 1 |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | taint-test 10 {string is tainted abcd} 0 |
| 41 | taint-test 20 {string is tainted [taint abcd]} 1 |
| 42 | taint-test 30 {string is tainted [untaint [taint abcd]]} 0 |
| 43 | taint-test 40 {string is tainted [untaint abcde]} 0 |
| 44 | taint-test 50 {string is tainted "abc[taint def]ghi"} 1 |
| 45 | taint-test 60 {set t1 [taint abc]; string is tainted "123 $t1 456"} 1 |
| 46 | |
| 47 | taint-test 100 {set t1 [taint abc]; lappend t1 def; string is tainted $t1} 1 |
| 48 | taint-test 110 {set t1 abc; lappend t1 [taint def]; string is tainted $t1} 1 |
| 49 | |
| 50 | taint-test 200 {string is tainted [list abc def ghi]} 0 |
| 51 | taint-test 210 {string is tainted [list [taint abc] def ghi]} 1 |
| 52 | taint-test 220 {string is tainted [list abc [taint def] ghi]} 1 |
| 53 | taint-test 230 {string is tainted [list abc def [taint ghi]]} 1 |
| 54 | |
| 55 | taint-test 300 { |
| 56 | set res {} |
| 57 | foreach x [list abc [taint def] ghi] { |
| 58 | lappend res [string is tainted $x] |
| 59 | } |
| 60 | set res |
| 61 | } {1 1 1} |
| 62 | taint-test 310 { |
| 63 | set res {} |
| 64 | foreach {x y} [list abc [taint def] ghi jkl] { |
| 65 | lappend res [string is tainted $x] [string is tainted $y] |
| 66 | } |
| 67 | set res |
| 68 | } {1 1 1 1} |
| 69 | |
| 70 | taint-test 400 {string is tainted [lindex "abc [taint def] ghi" 0]} 1 |
| 71 | taint-test 410 {string is tainted [lindex "abc [taint def] ghi" 1]} 1 |
| 72 | taint-test 420 {string is tainted [lindex "abc [taint def] ghi" 2]} 1 |
| 73 | taint-test 430 {string is tainted [lindex "abc [taint def] ghi" 3]} 0 |
| 74 | |
| 75 | taint-test 500 {string is tainted [string index [taint abcdefg] 3]} 1 |
| 76 | |
| 77 | taint-test 600 {string is tainted [string range [taint abcdefg] 3 5]} 1 |
| 78 | |
| 79 | taint-test 700 {string is tainted [string trim [taint " abcdefg "]]} 1 |
| 80 | taint-test 710 {string is tainted [string trimright [taint " abcdefg "]]} 1 |
| 81 | taint-test 720 {string is tainted [string trimleft [taint " abcdefg "]]} 1 |
| 82 | |
| 83 | |
| 84 | test_cleanup |