2012-08-07 14 views
9

क्या PHP में स्थिर कोड विश्लेषण करने और register_globals पहल पर निर्भरता का पता लगाने का कोई तरीका है? यह फ़ाइल को मैन्युअल रूप से जांचने के लिए अपेक्षाकृत सरल है और उन चरों को ढूंढें जिन्हें प्रारंभ नहीं किया गया है और इससे अनुमान लगाया जा सकता है कि ये इस पर भरोसा कर सकते हैं, लेकिन मुझे कई सैकड़ों स्क्रिप्ट के लिए ऐसा करने की ज़रूरत है, इसलिए मैं एक स्वचालित समाधान की तलाश में हूं ।रजिस्टर ग्लोबल्स का उपयोग करना

मेरा अंतिम उपाय निर्देश के साथ एक देव वातावरण स्थापित कर रहा है और सख्त त्रुटि रिपोर्टिंग और क्यूए को लंबे समय तक खेलना है, फिर त्रुटि लॉग को पकड़ने वाले उदाहरणों को ठीक करें, लेकिन यह 100 को खोजने की गारंटी नहीं है यदि स्वचालित समाधान मौजूद है तो मामलों का%, और निश्चित रूप से संसाधनों का अच्छा उपयोग नहीं है।

+0

यह मुश्किल होगा क्योंकि आपको खाता चर चर और कार्यों जैसे 'निकालने() ' –

+1

पर विचार करना होगा, मैं सोच रहा हूं" नहीं "। चूंकि @ माइकबी सही ढंग से इंगित करता है, 'एक्स्ट्राक्ट()' और वेरिएबल वैरिएबल (और इसके अतिरिक्त '$ ग्लोबल्स 'जैसी चीजें किसी भी प्रकार के कोड विश्लेषण के लिए कार्यों में एक विशाल स्पैनर फेंकती हैं जो वास्तव में कोड निष्पादित नहीं करती है। हां, आप बैच में स्क्रिप्ट चलाने का प्रयास कर सकते हैं और सेट किए गए चर के उपयोग के बारे में शिकायतों की तलाश कर सकते हैं, लेकिन हमेशा यह संभावना है कि कोड अभी भी टूटा हुआ है (हालांकि मुझे लगता है कि इस मामले में इसे अभी भी फिक्सिंग की आवश्यकता है)। दुर्भाग्यवश मैन्युअल दृष्टिकोण शायद आपका एकमात्र विकल्प है। आनंद लें ... – DaveRandom

+0

सावधान रहें, PHP 5.4.0 के बाद से 'register_globals' हटा दिया गया था। – Florent

उत्तर

13

एक छोटा सा स्क्रिप्ट मैं सिर्फ एक साथ काट दिया सरल अपरिभाषित चर पता लगाने के लिए। आप इस के लिए PHP-Parser की आवश्यकता होगी:

<?php 

error_reporting(E_ALL); 

$dir = './foo'; 

require_once './lib/bootstrap.php'; 

class Scope { 
    protected $stack; 
    protected $pos; 

    public function __construct() { 
     $this->stack = array(); 
     $this->pos = -1; 
    } 

    public function addVar($name) { 
     $this->stack[$this->pos][$name] = true; 
    } 

    public function hasVar($name) { 
     return isset($this->stack[$this->pos][$name]); 
    } 

    public function pushScope() { 
     $this->stack[++$this->pos] = array(); 
    } 

    public function popScope() { 
     --$this->pos; 
    } 
} 

class UndefinedVariableVisitor extends PHPParser_NodeVisitorAbstract { 
    protected $scope; 
    protected $parser; 
    protected $traverser; 

    public function __construct(Scope $scope, PHPParser_Parser $parser, PHPParser_NodeTraverser $traverser) { 
     $this->scope = $scope; 
     $this->parser = $parser; 
     $this->traverser = $traverser; 
    } 

    public function enterNode(PHPParser_Node $node) { 
     if (($node instanceof PHPParser_Node_Expr_Assign || $node instanceof PHPParser_Node_Expr_AssignRef) 
      && $node->var instanceof PHPParser_Node_Expr_Variable 
      && is_string($node->var->name) 
     ) { 
      $this->scope->addVar($node->var->name); 
     } elseif ($node instanceof PHPParser_Node_Stmt_Global || $node instanceof PHPParser_Node_Stmt_Static) { 
      foreach ($node->vars as $var) { 
       if (is_string($var->name)) { 
        $this->scope->addVar($var->name); 
       } 
      } 
     } elseif ($node instanceof PHPParser_Node_Expr_Variable && is_string($node->name)) { 
      if (!$this->scope->hasVar($node->name)) { 
       echo 'Undefined variable $' . $node->name . ' on line ' . $node->getLine() . "\n"; 
      } 
     } elseif ($node instanceof PHPParser_Node_Stmt_Function || $node instanceof PHPParser_Node_Stmt_ClassMethod) { 
      $this->scope->pushScope(); 

      // params are always available 
      foreach ($node->params as $param) { 
       $this->scope->addVar($param->name); 
      } 

      // methods always have $this 
      if ($node instanceof PHPParser_Node_Stmt_ClassMethod) { 
       $this->scope->addVar('this'); 
      } 
     } elseif ($node instanceof PHPParser_Node_Expr_Include && $node->expr instanceof PHPParser_Node_Scalar_String) { 
      $file = $node->expr->value; 
      $code = file_get_contents($file); 
      $stmts = $this->parser->parse($code); 

      // for includes within the file 
      $cwd = getcwd(); 
      chdir(dirname($file)); 

      $this->traverser->traverse($stmts); 

      chdir($cwd); 
     } 
    } 

    public function leaveNode(PHPParser_Node $node) { 
     if ($node instanceof PHPParser_Node_Stmt_Function || $node instanceof PHPParser_Node_Stmt_ClassMethod) { 
      $this->scope->popScope(); 
     } 
    } 
} 

$parser = new PHPParser_Parser(new PHPParser_Lexer()); 

$scope = new Scope; 

$traverser = new PHPParser_NodeTraverser; 
$traverser->addVisitor(new UndefinedVariableVisitor($scope, $parser, $traverser)); 

foreach (new RecursiveIteratorIterator(
      new RecursiveDirectoryIterator($dir), 
      RecursiveIteratorIterator::LEAVES_ONLY) 
     as $file 
) { 
    if (!preg_match('/\.php$/', $file)) continue; 

    echo 'Checking ' . $file . ':', "\n"; 

    $code = file_get_contents($file); 
    $stmts = $parser->parse($code); 

    // for includes within the file 
    $cwd = getcwd(); 
    chdir(dirname($file)); 

    $scope->pushScope(); 
    $traverser->traverse($stmts); 
    $scope->popScope(); 

    chdir($cwd); 

    echo "\n"; 
} 

यह सिर्फ एक बहुत ही बुनियादी कार्यान्वयन है और मैं इसे बड़े पैमाने पर परीक्षण नहीं किया है, लेकिन यह स्क्रिप्ट $GLOBALS और $$varVars साथ जंगली मत जाओ के लिए काम करना चाहिए। इसमें मूलभूत संकल्प शामिल है।

+5

अपाचे वातावरण में बस एक FYI, अगर (! Preg_match ('/ \। Php $ /', $ file) जारी रखें ; मूर्ख प्रमाण नहीं है। अपाचे कुछ भी निष्पादित करेगा जो PHP स्क्रिप्ट के रूप में '/ \। Php (\। | $) /' से मेल खाता है (और उसके पास विंडोज़ पर 'i' संशोधक होगा)। यह अपाचे अजीबता का एक छोटा सा हिस्सा है जो PHP संचालित साइटों की दुनिया में कई सुरक्षा छेदों के लिए जिम्मेदार है। ऐसा लगता है कि * शायद * एक +1 का हकदार है, हालांकि मैं यह नहीं कह सकता कि मैं इसके बारे में पर्याप्त जानता हूं (विशेष रूप से 'PHPParser') आपको ऐसा महसूस करने के लिए कर रहा है जैसे मैं समझ नहीं पा रहा हूं। – DaveRandom

0

यह (php मैनुअल टिप्पणियों में से एक से) काम करना चाहिए:

if (ini_get('register_globals')) { 
    foreach ($GLOBALS as $int_temp_name => $int_temp_value) { 
     if (!in_array($int_temp_name, array (
       'GLOBALS', 
       '_FILES', 
       '_REQUEST', 
       '_COOKIE', 
       '_SERVER', 
       '_ENV', 
       '_SESSION', 
       ini_get('session.name'), 
       'int_temp_name', 
       'int_temp_value' 
      ))) { 
      unset ($GLOBALS[$int_temp_name]); 
     } 
    } 
} 
+0

यह स्थिर रूप से ग्लोबल्स के उपयोग का पता कैसे लगाएगा? –

+1

हां, या आप * केवल 'register_globals' बंद कर सकते हैं। लेकिन ओपी पूछ रहा है कि प्रोग्रामेटिक रूप से यह पता लगाना संभव है कि क्या एक स्क्रिप्ट को चालू होने की उम्मीद है, न कि इसे बंद करने की नकल कैसे करें। इसके अलावा जो कई स्थितियों को पकड़ नहीं पाता है जो विभिन्न स्थितियों में * हो सकता है। '$ Argv' के बारे में क्या? '$ Argc' के बारे में क्या? 'HTTP_RAW_POST_DATA' के बारे में क्या? – DaveRandom

+0

हां आप 2 दोनों इस चेक को सही करते हैं कि यह चालू है या नहीं, लेकिन इसका उपयोग नहीं है .. –

संबंधित मुद्दे