"I work on a team maintaining a large and enterprisey PHP system," writes Amber, "and as such, my job mostly involves doing enhancements and fixing bugs."
"It sounds normal enough, if not for the fact that almost all variables are globals and each of them might or might not be initialized in the same way, or the same place, as seen in this screenshot."
"That's tolerable, but the real problem arises when I need to reuse a function in a different location. I've added line breaks and formatting to make some sense of things..."
global $dbCon; $dbCon->InitOpen($cf_db, 'db1'); .... snip a few hundred lines .... function getRanking () { global $dbCon, $dbCon_test, $dbCon2, $cf_db; include '../rtuser/rtutil.php'; $dbCon_test-> InitOpen($cf_db, 'db2'); ..... snip .... /* rt_rank() requires $dbCon as db connection to testdb * in this context, $dbCon currently points to Db1 thus * temporarily pointing $dbCon to testdb is necessary (fred) */ $tempdbConDb1 = $dbCon; //assign $dbCon_test to $dbCon to have testdb connection $dbCon = $dbCon_test; $memcacheKey = 'hof_ranking_' . $cntr . ':' . $offset; //call rtutil.php's getrtRank() // cache db r in memcache for 5 minutes $r = unserialize(getMemCache($dbCon2, $memcacheKey, '5 minute', 'getrtRank', $args)); //swap back $dbCon so that the code relying on $dbCon pointing to Db1 won't be affected $dbCon = $tempdbConDb1; include '../rateuser/rateutil.php'; ... snip ... /* rate_rank() requires $sql as db connection to testdb * in this context, $sql currently points to gm thus * temporarily pointing $sql to testdb is necessary (fred) */ $tempSqlGm = $sql; //assign $sql_test to $sql to have testdb connection $sql = $sql_test; $memcacheKey = 'hof_ranking_' . $cntr . ':' . $offset; //call rateutil.php's getRateRank() $result = unserialize(getCacheInfo($sql2, $memcacheKey, '5 minute', 'getRateRank', $args)); list($uidlist, $nicks, $votes, $imageIds, $genders) = $result; //swap back $sql so that the code relying on $sql pointing to gm won't be affected $sql = $tempSqlGm; //.... }
Amber continues, "what happened here was that, in file A, a global database link identifier pointed to database 1 but in the include file B, the same variable was supposed to point to database 2. What I did was to swap out the link identifier whenever a function in file B was involved, then swap back whenever a function in file A was involved. Injection was not an option as the Globals were so deeply and variably coupled that decoupling them needs to be done on a case-by-case basis. And that was just one place...