diff --git a/src/test/tainting/print_r_01.php b/src/test/tainting/core/array.php similarity index 57% rename from src/test/tainting/print_r_01.php rename to src/test/tainting/core/array.php index 86573b4f668aa..5591bf692020e 100644 --- a/src/test/tainting/print_r_01.php +++ b/src/test/tainting/core/array.php @@ -14,22 +14,36 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ -require_once('setup.inc'); +require_once('../setup.inc'); -$a = "good\n"; -$b = print_r($a, true); +/** + * Sanity checks for tainting array entries. + */ -if(fb_get_taint($b) & TAINT_HTML_MASK){ - echo "b is tainted\n"; -} else { - echo "b is not tainted\n"; -} +$arrg1 = array($good1); +$arrb1 = array($bad1); +echo "Testing array() on strings:\n"; +assert_not_tainted($arrg1[0]); +assert_tainted($arrb1[0]); -$b = array($a); -$c = print_r($b, true); +$arr = array( + 'good1' => $good1, + 'bad1' => $bad1, + 42 => array( + 'good2' => $good2, + 'bad2' => $bad2, + ), +); +echo "\n"; +echo "Testing array containing mixed taints:\n"; +assert_not_tainted($arr); +assert_tainted(print_r($arr, true)); -if(fb_get_taint($c) & TAINT_HTML_MASK){ - echo "c is tainted\n"; -} else { - echo "c is not tainted\n"; -} +echo "\n"; +echo "Testing taint independence among array entries:\n"; +assert_not_tainted($arr['good1']); +assert_tainted($arr['bad1']); +assert_not_tainted($arr[42]); +assert_tainted(print_r($arr[42], true)); +assert_not_tainted($arr[42]['good2']); +assert_tainted($arr[42]['bad2']); diff --git a/src/test/tainting/concatenations.php b/src/test/tainting/core/concatenations.php similarity index 78% rename from src/test/tainting/concatenations.php rename to src/test/tainting/core/concatenations.php index df934fda9a958..78c61cd296823 100644 --- a/src/test/tainting/concatenations.php +++ b/src/test/tainting/core/concatenations.php @@ -14,28 +14,29 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ -require_once('setup.inc'); +require_once('../setup.inc'); /** - * Check that various forms of concatenations output the right taint information + * Check that various forms of concatenations output the right general taint + * information. Concatenation tests for staticity can be found in ./static/ */ $a = $good1 . $good2; -not_tainted($a); +assert_not_tainted($a); $a = $good1 . $bad1; -tainted($a); +assert_tainted($a); $a = $good1; $a .= $good2; -not_tainted($a); +assert_not_tainted($a); $a = $good1; $a .= $bad1; -tainted($a); +assert_tainted($a); $a = "$good1 $good2"; -not_tainted($a); +assert_not_tainted($a); $a = "$good1 $bad1"; -tainted($a); +assert_tainted($a); diff --git a/src/test/tainting/output.php b/src/test/tainting/core/output.php similarity index 69% rename from src/test/tainting/output.php rename to src/test/tainting/core/output.php index d6e47dc33fdbc..3d70cccd1d49b 100644 --- a/src/test/tainting/output.php +++ b/src/test/tainting/core/output.php @@ -14,21 +14,21 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ -require_once('setup.inc'); +require_once('../setup.inc'); /** * Taint tests for functions defined in output.idl.php */ -echo "testing ob_start\n"; +echo "Testing ob_start:\n"; ob_start(); ob_start(); echo $good1; $a = ob_get_clean(); echo $a; $b = ob_get_clean(); -not_tainted($a); -not_tainted($b); +assert_html_safe($a); +assert_html_safe($b); ob_start(); ob_start(); @@ -36,44 +36,44 @@ $a = ob_get_clean(); echo $a; $b = ob_get_clean(); -tainted($a); -tainted($b); +assert_html_unsafe($a); +assert_html_unsafe($b); -echo "\n\n"; -echo "testing ob_clean\n"; +echo "\n"; +echo "Testing ob_clean:\n"; ob_start(); echo $good1; ob_clean(); echo $good2; -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); echo $bad1; ob_clean(); echo $good1; -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); echo $good1; ob_clean(); echo $bad1; -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); ob_start(); echo $bad1; ob_clean(); echo $bad2; -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); -echo "\n\n"; -echo "testing ob_flush\n"; +echo "\n"; +echo "Testing ob_flush:\n"; ob_start(); ob_start(); echo $good1; ob_flush(); ob_end_clean(); $a = ob_get_clean(); -not_tainted($a); +assert_html_safe($a); ob_start(); ob_start(); @@ -81,86 +81,86 @@ ob_flush(); ob_end_clean(); $a = ob_get_clean(); -tainted($a); +assert_html_unsafe($a); -echo "\n\n"; -echo "testing ob_end_clean\n"; +echo "\n"; +echo "Testing ob_end_clean:\n"; ob_start(); ob_start(); echo $good1; ob_end_clean(); echo $good2; -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); ob_start(); echo $bad1; ob_end_clean(); echo $good1; -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); ob_start(); echo $good1; ob_end_clean(); echo $bad1; -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); ob_start(); ob_start(); echo $bad1; ob_end_clean(); echo $bad2; -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); -echo "\n\n"; -echo "testing ob_end_flush\n"; +echo "\n"; +echo "Testing ob_end_flush:\n"; ob_start(); ob_start(); echo $good1; ob_end_flush(); -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); ob_start(); echo $bad1; ob_end_flush(); -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); -echo "\n\n"; -echo "testing ob_get_clean\n"; +echo "\n"; +echo "Testing ob_get_clean:\n"; ob_start(); echo $good1; -not_tainted(ob_get_clean()); +assert_html_safe(ob_get_clean()); ob_start(); echo $bad1; -tainted(ob_get_clean()); +assert_html_unsafe(ob_get_clean()); -echo "\n\n"; -echo "testing ob_get_contents\n"; +echo "\n"; +echo "Testing ob_get_contents:\n"; ob_start(); echo $good1; $a = ob_get_contents(); ob_end_clean(); -not_tainted($a); +assert_html_safe($a); ob_start(); echo $bad1; $a = ob_get_contents(); ob_end_clean(); -tainted($a); +assert_html_unsafe($a); -echo "\n\n"; -echo "testing ob_get_flush\n"; +echo "\n"; +echo "Testing ob_get_flush:\n"; ob_start(); ob_start(); echo $good1; $a = ob_get_flush(); ob_end_clean(); $b = ob_get_clean(); -not_tainted($a); -not_tainted($b); +assert_html_safe($a); +assert_html_safe($b); ob_start(); ob_start(); @@ -168,7 +168,7 @@ $a = ob_get_flush(); ob_end_clean(); $b = ob_get_clean(); -tainted($a); -tainted($b); +assert_html_unsafe($a); +assert_html_unsafe($b); diff --git a/src/test/tainting/references.php b/src/test/tainting/core/references.php similarity index 86% rename from src/test/tainting/references.php rename to src/test/tainting/core/references.php index 7247a9a2ba892..41d3badf0e3a1 100644 --- a/src/test/tainting/references.php +++ b/src/test/tainting/core/references.php @@ -14,18 +14,18 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ -require_once('setup.inc'); +require_once('../setup.inc'); /** - * Check that the reference operator doesn't cause us to loose any taint - * information + * Check that the reference operator doesn't cause us to lose any taint + * information. */ $a = $good1; $b = &$a; $a .= $good2; -not_tainted($b); +assert_not_tainted($b); $a .= $bad1; -tainted($b); +assert_tainted($b); diff --git a/src/test/tainting/core/strings.php b/src/test/tainting/core/strings.php new file mode 100644 index 0000000000000..4bc1d580a4893 --- /dev/null +++ b/src/test/tainting/core/strings.php @@ -0,0 +1,253 @@ + $good1, 'bad1' => $bad1, ); extract($arr, EXTR_PREFIX_ALL, 'extract'); -not_tainted($extract_good1); -tainted($extract_bad1); +assert_html_safe($extract_good1); +assert_html_unsafe($extract_bad1); diff --git a/src/test/tainting/print_r_01.php.exp b/src/test/tainting/print_r_01.php.exp deleted file mode 100644 index 8c9a94b2bd516..0000000000000 --- a/src/test/tainting/print_r_01.php.exp +++ /dev/null @@ -1,4 +0,0 @@ - -b is not tainted - -c is not tainted diff --git a/src/test/tainting/print_r_02.php b/src/test/tainting/print_r_02.php deleted file mode 100644 index 2cc7463db43a0..0000000000000 --- a/src/test/tainting/print_r_02.php +++ /dev/null @@ -1,37 +0,0 @@ - good - - - -) diff --git a/src/test/tainting/print_r_06.php b/src/test/tainting/print_r_06.php index 9f755fdd09ff4..5915389cefa47 100644 --- a/src/test/tainting/print_r_06.php +++ b/src/test/tainting/print_r_06.php @@ -17,7 +17,7 @@ require_once('setup.inc'); $a = "bad\n"; -fb_set_taint($a, TAINT_HTML_MASK); +fb_set_taint($a, TAINT_ALL_MASK); print_r($a); diff --git a/src/test/tainting/setup.inc b/src/test/tainting/setup.inc index 05902211466eb..8fb5c9c3e7312 100644 --- a/src/test/tainting/setup.inc +++ b/src/test/tainting/setup.inc @@ -15,52 +15,78 @@ +----------------------------------------------------------------------+ */ -define('TAINT_HTML_MASK', 0x1); +define('TAINT_HTML', 0x1); +define('TAINT_SQL', 0x2); +define('TAINT_MUTATED', 0x4); +define('TAINT_ALL', 0x7); $good1 = "heLlO\nwoRld\ntoto\ntiti\ntata"; $good2 = "world"; $good3 = "toto"; - $serialized_good = 's:5:"hello";'; $bad1 = "eViL\nsTring\nare\tfun\narent\tthey?"; $bad2 = "some\nthing\ntoto\nbad!"; - $serialized_bad = 's:11:"evil string";'; -fb_set_taint($bad1, TAINT_HTML_MASK); -fb_set_taint($bad2, TAINT_HTML_MASK); -fb_set_taint($serialized_bad, TAINT_HTML_MASK); -function not_tainted($v) { +fb_set_taint($bad1, TAINT_ALL); +fb_set_taint($bad2, TAINT_ALL); +fb_set_taint($serialized_bad, TAINT_ALL); + +function assert_positive($v, $taint) { if (ob_get_level()) { - die("HEY YOU CAN'T CALL not_tainted INSIDE ob_start()"); + die("Error: may not call assert_negative() inside ob_start()\n"); } - $r = fb_get_taint($v); - if ($r) { - echo chr(27)."[0;31m"; - echo "FAIL (tainted something which shouldn't be tainted)\n"; + if (!fb_get_taint($v, $taint)) { + echo chr(27)."[0;32m"; + echo "OK\n"; echo chr(27)."[0m"; } else { - echo chr(27)."[0;32m"; - echo "Ok\n"; + echo chr(27)."[0;31m"; + echo "FAIL\n"; echo chr(27)."[0m"; } } -function tainted($v) { +function assert_negative($v, $taint) { if (ob_get_level()) { - die("HEY YOU CAN'T CALL tainted INSIDE ob_start()"); + die("Error: may not call assert_positive() inside ob_start()\n"); } - $r = fb_get_taint($v); - if (!$r) { - echo chr(27)."[0;31m"; - echo "FAIL (did not taint something which should have been)\n"; + if (fb_get_taint($v, $taint)) { + echo chr(27)."[0;32m"; + echo "OK\n"; echo chr(27)."[0m"; } else { - echo chr(27)."[0;32m"; - echo "Ok\n"; + echo chr(27)."[0;31m"; + echo "FAIL\n"; echo chr(27)."[0m"; } } + +function assert_not_tainted($v) { + return assert_positive($v, TAINT_ALL); +} +function assert_html_safe($v) { + return assert_positive($v, TAINT_HTML); +} +function assert_sql_safe($v) { + return assert_positive($v, TAINT_SQL); +} +function assert_static($v) { + return assert_positive($v, TAINT_MUTATED); +} + +function assert_tainted($v) { + return assert_negative($v, TAINT_ALL); +} +function assert_html_unsafe($v) { + return assert_negative($v, TAINT_HTML); +} +function assert_sql_unsafe($v) { + return assert_negative($v, TAINT_SQL); +} +function assert_not_static($v) { + return assert_negative($v, TAINT_MUTATED); +} diff --git a/src/test/tainting/static/static_concat.php b/src/test/tainting/static/static_concat.php new file mode 100644 index 0000000000000..1d1165de4bddb --- /dev/null +++ b/src/test/tainting/static/static_concat.php @@ -0,0 +1,144 @@ +sc_prop = "property"; + } + + public function concatWithConstant($str) { + return $str . self::SC_CONST; + } + + public function concatWithProperty($str) { + return $str . $this->sc_prop; + } +} +echo "\n"; +echo "Testing class-wrapped concat:\n"; +assert_static($good1 . StaticConcat::SC_CONST); +$sc = new StaticConcat(); +assert_static($sc->concatWithConstant($good1)); +assert_static($good1 . $sc->sc_prop); +assert_static($sc->concatWithProperty($good1)); + +echo "\n"; +echo "Testing concat with other types:\n"; +assert_static($good1 . NULL); +assert_static($good1 . true); +assert_static($good1 . false); +assert_not_static($good1 . 42); +assert_not_static($good1 . 3.1415926535897); diff --git a/src/test/tainting/static/static_typecast.php b/src/test/tainting/static/static_typecast.php new file mode 100644 index 0000000000000..35d169dd3e829 --- /dev/null +++ b/src/test/tainting/static/static_typecast.php @@ -0,0 +1,96 @@ + 42, + 42 => 'str', + 1 => true, +); +echo "Testing array...\n"; +echo " int value: "; +assert_not_static($array['str']); +echo " string value: "; +assert_static($array[42]); +echo " bool value: "; +assert_not_static($array[1]); +echo " typecast as string: "; +assert_static($array); + +class ObjToStringLiteral { + function __toString() { return "obj"; } +} +class ObjToStringNonliteral { + function __toString() { + global $bad1; + return "obj" . $bad1; + } +} +echo "Testing object...\n"; +$obj1 = new ObjToStringLiteral(); +echo " cast as literal: "; +assert_static($obj1); +$obj2 = new ObjToStringNonliteral(); +echo " cast as nonliteral: "; +assert_not_static($obj2); diff --git a/src/test/tainting/strings.php b/src/test/tainting/strings.php deleted file mode 100644 index c708516eb925c..0000000000000 --- a/src/test/tainting/strings.php +++ /dev/null @@ -1,266 +0,0 @@ - - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint02.php:9] - the echoed string is : 'bad -' - -[end of the echoed string] - - -bad diff --git a/src/test/tainting/taint03.php b/src/test/tainting/taint03.php deleted file mode 100644 index 9f33c292e1c42..0000000000000 --- a/src/test/tainting/taint03.php +++ /dev/null @@ -1,5 +0,0 @@ - - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint05.php:8] - the echoed string is : 'great' - -[end of the echoed string] - - -greatHipHop Warning: Echoing a tainted string: - the originally tainted string was : 'great' - it was tainted at : - #0 fb_set_taint(), called at [/data/users/jjeannin/hphp/src/test/tainting/taint05.php:4] - it was successively modified at: - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint05.php:5] - --- - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint05.php:9] - the echoed string is : 'worse great' - -[end of the echoed string] - - -worse great \ No newline at end of file diff --git a/src/test/tainting/taint06.php b/src/test/tainting/taint06.php deleted file mode 100644 index 4bf59a94920aa..0000000000000 --- a/src/test/tainting/taint06.php +++ /dev/null @@ -1,8 +0,0 @@ - - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint06.php:7] - the echoed string is : 'great' - -[end of the echoed string] - - -greatworse great \ No newline at end of file diff --git a/src/test/tainting/taint07.php b/src/test/tainting/taint07.php deleted file mode 100644 index 577e7a3be9836..0000000000000 --- a/src/test/tainting/taint07.php +++ /dev/null @@ -1,7 +0,0 @@ - - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint10_aux.php:5] - #1 foo(), called at [/data/users/jjeannin/hphp/src/test/tainting/taint10.php:3] - the echoed string is : 'a weird string' - -[end of the echoed string] - - -a weird stringHipHop Warning: Echoing a tainted string: - the originally tainted string was : 'a weird string' - it was tainted at : - #0 fb_set_taint(), called at [/data/users/jjeannin/hphp/src/test/tainting/taint10_aux.php:4] - #1 foo(), called at [/data/users/jjeannin/hphp/src/test/tainting/taint10.php:3] - it was successively modified at: - - it was echoed at : - #0 at [/data/users/jjeannin/hphp/src/test/tainting/taint10.php:4] - the echoed string is : 'a weird string' - -[end of the echoed string] - - -a weird string \ No newline at end of file diff --git a/src/test/tainting/taint10_aux.php b/src/test/tainting/taint10_aux.php deleted file mode 100644 index 7b8e36639dc79..0000000000000 --- a/src/test/tainting/taint10_aux.php +++ /dev/null @@ -1,7 +0,0 @@ -