| | @@ -382,25 +382,26 @@ |
| 382 | 382 | ** g.th1Flags has the TH_INIT_NO_ENCODE flag. |
| 383 | 383 | ** |
| 384 | 384 | ** If pOut is NULL and the global pThOut is not then that blob |
| 385 | 385 | ** is used for output. |
| 386 | 386 | */ |
| 387 | | -static void sendText(Blob * pOut, const char *z, int n, int encode){ |
| 387 | +static void sendText(Blob *pOut, const char *z, int n, int encode){ |
| 388 | 388 | if(0==pOut && pThOut!=0){ |
| 389 | 389 | pOut = pThOut; |
| 390 | 390 | } |
| 391 | 391 | if(TH_INIT_NO_ENCODE & g.th1Flags){ |
| 392 | 392 | encode = 0; |
| 393 | | - if( TH1_TAINTED(n) && Th_ReportTaint(0, "output string", z, n) ){ |
| 393 | + } |
| 394 | + if( encode==0 && n>0 && TH1_TAINTED(n) ){ |
| 395 | + if( Th_ReportTaint(0, "output string", z, n) ){ |
| 394 | 396 | return; |
| 395 | 397 | } |
| 398 | + n = TH1_LEN(n); |
| 396 | 399 | } |
| 397 | 400 | if( enableOutput && n ){ |
| 398 | 401 | if( n<0 ){ |
| 399 | 402 | n = strlen(z); |
| 400 | | - }else{ |
| 401 | | - n = TH1_LEN(n); |
| 402 | 403 | } |
| 403 | 404 | if( encode ){ |
| 404 | 405 | z = htmlize(z, n); |
| 405 | 406 | n = strlen(z); |
| 406 | 407 | } |
| | @@ -1865,10 +1866,47 @@ |
| 1865 | 1866 | sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x); |
| 1866 | 1867 | Th_SetResult(interp, zUTime, -1); |
| 1867 | 1868 | return TH_OK; |
| 1868 | 1869 | } |
| 1869 | 1870 | |
| 1871 | +/* |
| 1872 | +** TH1 command: taint STRING |
| 1873 | +** |
| 1874 | +** Return a copy of STRING that is marked as tainted. |
| 1875 | +*/ |
| 1876 | +static int taintCmd( |
| 1877 | + Th_Interp *interp, |
| 1878 | + void *p, |
| 1879 | + int argc, |
| 1880 | + const char **argv, |
| 1881 | + int *argl |
| 1882 | +){ |
| 1883 | + if( argc!=2 ){ |
| 1884 | + return Th_WrongNumArgs(interp, "STRING"); |
| 1885 | + } |
| 1886 | + Th_SetResult(interp, argv[1], TH1_ADD_TAINT(argl[1])); |
| 1887 | + return TH_OK; |
| 1888 | +} |
| 1889 | + |
| 1890 | +/* |
| 1891 | +** TH1 command: untaint STRING |
| 1892 | +** |
| 1893 | +** Return a copy of STRING that is marked as untainted. |
| 1894 | +*/ |
| 1895 | +static int untaintCmd( |
| 1896 | + Th_Interp *interp, |
| 1897 | + void *p, |
| 1898 | + int argc, |
| 1899 | + const char **argv, |
| 1900 | + int *argl |
| 1901 | +){ |
| 1902 | + if( argc!=2 ){ |
| 1903 | + return Th_WrongNumArgs(interp, "STRING"); |
| 1904 | + } |
| 1905 | + Th_SetResult(interp, argv[1], TH1_LEN(argl[1])); |
| 1906 | + return TH_OK; |
| 1907 | +} |
| 1870 | 1908 | |
| 1871 | 1909 | /* |
| 1872 | 1910 | ** TH1 command: randhex N |
| 1873 | 1911 | ** |
| 1874 | 1912 | ** Return N*2 random hexadecimal digits with N<50. If N is omitted, |
| | @@ -1940,11 +1978,13 @@ |
| 1940 | 1978 | int res = TH_OK; |
| 1941 | 1979 | int nVar; |
| 1942 | 1980 | char *zErr = 0; |
| 1943 | 1981 | int noComplain = 0; |
| 1944 | 1982 | |
| 1945 | | - if( argc>3 && argl[1]==11 && strncmp(argv[1], "-nocomplain", 11)==0 ){ |
| 1983 | + if( argc>3 && TH1_LEN(argl[1])==11 |
| 1984 | + && strncmp(argv[1], "-nocomplain", 11)==0 |
| 1985 | + ){ |
| 1946 | 1986 | argc--; |
| 1947 | 1987 | argv++; |
| 1948 | 1988 | argl++; |
| 1949 | 1989 | noComplain = 1; |
| 1950 | 1990 | } |
| | @@ -1956,12 +1996,15 @@ |
| 1956 | 1996 | Th_ErrorMessage(interp, "database is not open", 0, 0); |
| 1957 | 1997 | return TH_ERROR; |
| 1958 | 1998 | } |
| 1959 | 1999 | zSql = argv[1]; |
| 1960 | 2000 | nSql = argl[1]; |
| 1961 | | - if( TH1_TAINTED(nSql) && Th_ReportTaint(interp,"query SQL",zSql,nSql) ){ |
| 1962 | | - return TH_ERROR; |
| 2001 | + if( TH1_TAINTED(nSql) ){ |
| 2002 | + if( Th_ReportTaint(interp,"query SQL",zSql,nSql) ){ |
| 2003 | + return TH_ERROR; |
| 2004 | + } |
| 2005 | + nSql = TH1_LEN(nSql); |
| 1963 | 2006 | } |
| 1964 | 2007 | |
| 1965 | 2008 | while( res==TH_OK && nSql>0 ){ |
| 1966 | 2009 | zErr = 0; |
| 1967 | 2010 | report_restrict_sql(&zErr); |
| | @@ -2408,13 +2451,15 @@ |
| 2408 | 2451 | {"setting", settingCmd, 0}, |
| 2409 | 2452 | {"styleFooter", styleFooterCmd, 0}, |
| 2410 | 2453 | {"styleHeader", styleHeaderCmd, 0}, |
| 2411 | 2454 | {"styleScript", styleScriptCmd, 0}, |
| 2412 | 2455 | {"submenu", submenuCmd, 0}, |
| 2456 | + {"taint", taintCmd, 0}, |
| 2413 | 2457 | {"tclReady", tclReadyCmd, 0}, |
| 2414 | 2458 | {"trace", traceCmd, 0}, |
| 2415 | 2459 | {"stime", stimeCmd, 0}, |
| 2460 | + {"untaint", untaintCmd, 0}, |
| 2416 | 2461 | {"unversioned", unversionedCmd, 0}, |
| 2417 | 2462 | {"utime", utimeCmd, 0}, |
| 2418 | 2463 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 2419 | 2464 | {"verifyLogin", verifyLoginCmd, 0}, |
| 2420 | 2465 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| | @@ -3013,10 +3058,11 @@ |
| 3013 | 3058 | if( find_option("set-user-caps", 0, 0)!=0 ){ |
| 3014 | 3059 | const char *zCap = fossil_getenv("TH1_TEST_USER_CAPS"); |
| 3015 | 3060 | login_set_capabilities(zCap ? zCap : "sx", 0); |
| 3016 | 3061 | g.useLocalauth = 1; |
| 3017 | 3062 | } |
| 3063 | + db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); |
| 3018 | 3064 | verify_all_options(); |
| 3019 | 3065 | if( g.argc<3 ){ |
| 3020 | 3066 | usage("FILE"); |
| 3021 | 3067 | } |
| 3022 | 3068 | blob_zero(&in); |
| | @@ -3065,10 +3111,11 @@ |
| 3065 | 3111 | if( find_option("set-user-caps", 0, 0)!=0 ){ |
| 3066 | 3112 | const char *zCap = fossil_getenv("TH1_TEST_USER_CAPS"); |
| 3067 | 3113 | login_set_capabilities(zCap ? zCap : "sx", 0); |
| 3068 | 3114 | g.useLocalauth = 1; |
| 3069 | 3115 | } |
| 3116 | + db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); |
| 3070 | 3117 | verify_all_options(); |
| 3071 | 3118 | if( g.argc!=3 ){ |
| 3072 | 3119 | usage("script"); |
| 3073 | 3120 | } |
| 3074 | 3121 | if(file_isfile(g.argv[2], ExtFILE)){ |
| 3075 | 3122 | |