toContain("rrdtool_execute('file_exists ' . cacti_escapeshellarg(\$file)"); expect($rrdcheckSource)->not->toContain('rrdtool_execute("file_exists $file"'); }); test('rrdcheck proxy info escapes the RRDfile path', function () use ($rrdcheckSource) { expect($rrdcheckSource)->toContain("rrdtool_execute('info ' . cacti_escapeshellarg(\$file)"); expect($rrdcheckSource)->not->toContain('rrdtool_execute("info $file"'); }); test('rrdcheck proxy fetch escapes the RRDfile path', function () use ($rrdcheckSource) { expect($rrdcheckSource)->toContain("rrdtool_execute('fetch ' . cacti_escapeshellarg(\$file)"); expect($rrdcheckSource)->not->toMatch('/rrdtool_execute\("fetch \$file/'); }); // --- pipe calls hand RRDtool an argument array --- test('rrdcheck pipe info uses the argument array form', function () use ($rrdcheckSource) { expect($rrdcheckSource)->toContain("rrdcheck_rrdtool_execute(['info', \$file], \$pipes)"); expect($rrdcheckSource)->not->toContain('rrdcheck_rrdtool_execute("info $file"'); }); test('rrdcheck pipe fetch uses the argument array form', function () use ($rrdcheckSource) { expect($rrdcheckSource)->toContain("rrdcheck_rrdtool_execute(['fetch', \$file, 'LAST', '-s', \$pstart, '-e', \$pend], \$pipes)"); expect($rrdcheckSource)->not->toMatch('/rrdcheck_rrdtool_execute\("fetch \$file/'); }); // --- no RRDtool command in this file interpolates the path --- test('no rrdcheck RRDtool command interpolates $file', function () use ($rrdcheckSource) { expect(preg_match('/rrd(check_)?(rrd)?tool_execute\(\s*"[^"]*\$file/', $rrdcheckSource))->toBe(0, 'RRDtool commands must not interpolate $file into a double quoted string' ); }); // --- the array form reaches RRDtool with every argument quoted --- test('rrdcheck_rrdtool_execute quotes each argument after the sub-command', function () { /* * Drive the real function with a pair of in-memory streams. The 'OK' * already sitting in the read pipe ends the response loop, so what lands * in the write pipe is the exact command line RRDtool would receive. */ $stdin = fopen('php://temp', 'r+'); $stdout = fopen('php://temp', 'r+'); fwrite($stdout, "OK\n"); rewind($stdout); $pipes = [$stdin, $stdout]; rrdcheck_rrdtool_execute(['fetch', '/rra/x.rrd; touch /tmp/pwned', 'LAST', '-s', 100, '-e', 200], $pipes); rewind($stdin); $written = stream_get_contents($stdin); fclose($stdin); fclose($stdout); expect($written)->toBe("fetch '/rra/x.rrd; touch /tmp/pwned' 'LAST' '-s' '100' '-e' '200'\r\n"); });