Example #1
0
 public function leaveNode($node)
 {
     /**
      * PHP 4 style constructors
      *
      * @see http://php.net/manual/en/migration70.deprecated.php#migration70.deprecated.php4-constructors
      */
     if ($node instanceof Stmt\ClassMethod && $node->migName == $this->visitor->getClass()->name) {
         $this->addSpot('DEPRECATED', true, 'PHP 4 style constructor is deprecated');
         /**
          * password_hash() salt option
          *
          * @see http://php.net/manual/en/migration70.deprecated.php#migration70.deprecated.pwshash-salt-option
          */
     } elseif ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->migName, 'password_hash') && isset($node->args[2])) {
         $this->addSpot('DEPRECATED', false, 'salt option for password_hash() is deprecated');
         /**
          * LDAP deprecations
          *
          * @see http://php.net/manual/en/migration70.deprecated.php#migration70.deprecated.ldap
          */
     } elseif ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->migName, 'ldap_sort')) {
         $this->addSpot('DEPRECATED', true, 'ldap_sort() is deprecated');
     }
 }
Example #2
0
 public function leaveNode($node)
 {
     /**
      * set_exception_handler() is no longer guaranteed to receive Exception
      * objects
      *
      * @see http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.error-handling
      */
     if (!$node instanceof Expr\FuncCall || !ParserHelper::isSameFunc($node->name, 'set_exception_handler') || !isset($node->args[0])) {
         return;
     }
     $affected = true;
     $certain = false;
     $callback = $node->args[0]->value;
     if ($callback instanceof Expr\Closure) {
         if (!isset($callback->params[0]) || !isset($callback->params[0]->type)) {
             $affected = false;
             $certain = true;
         } elseif (ParserHelper::isSameClass($callback->params[0]->type, 'Exception')) {
             $affected = true;
             $certain = true;
         }
     }
     if ($affected) {
         $this->addSpot('WARNING', $certain, 'set_exception_handler() is no longer guaranteed to receive Exception objects');
     }
 }
Example #3
0
 public function leaveNode($node)
 {
     if ($node instanceof Expr\FuncCall && $this->mysqlTable->has($node->name)) {
         /**
          * {Description}
          * The original MySQL extension is now deprecated, and will generate
          * E_DEPRECATED errors when connecting to a database. Instead, use the
          * MySQLi or PDO_MySQL extensions.
          *
          * {Reference}
          * http://php.net/manual/en/migration55.deprecated.php#migration55.deprecated.mysql
          */
         $this->addSpot('DEPRECATED', true, 'The original MySQL extension is deprecated, use MySQLi or PDO_MySQL extensions instead');
     } elseif ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->name, 'preg_replace')) {
         /**
          * {Description}
          * The preg_replace() /e modifier is now deprecated. Instead, use the
          * preg_replace_callback() function.
          *
          * {Reference}
          * http://php.net/manual/en/migration55.deprecated.php#migration55.deprecated.preg-replace-e
          */
         $affected = true;
         $certain = false;
         if (!isset($node->args[0])) {
             return;
         }
         $pattern = $node->args[0]->value;
         // TODO: shoud be full tested
         // Read right-most if concat, encapsed
         if ($pattern instanceof Expr\BinaryOp\Concat) {
             $pattern = $pattern->right;
         }
         if ($pattern instanceof Scalar\Encapsed) {
             $pattern = end($pattern->parts);
         }
         // Extract to string
         if ($pattern instanceof Scalar\String_ || $pattern instanceof Scalar\EncapsedStringPart) {
             $pattern = $pattern->value;
         }
         // Guess whether e in modifier
         if (is_string($pattern)) {
             $modifier = strrchr($pattern, '/');
             $certain = $affected = strpos($modifier, 'e') !== false;
         }
         if ($affected) {
             $this->addSpot('DEPRECATED', $certain, 'preg_replace() /e modifier is deprecated, use preg_replace_callback() instead');
         }
     } elseif ($node instanceof Expr\FuncCall && $this->funcTable->has($node->name)) {
         /**
          * TODO: how to check IntlDateFormatter::setTimeZoneId
          *
          * {Reference}
          * http://php.net/manual/en/migration55.deprecated.php#migration55.deprecated.intl
          * http://php.net/manual/en/migration55.deprecated.php#migration55.deprecated.mcrypt
          */
         $this->addSpot('DEPRECATED', true, 'Function ' . $node->name . '() is deprecated');
     }
 }
Example #4
0
 public function leaveNode($node)
 {
     if (!$node instanceof Stmt\Class_) {
         return;
     }
     foreach ($node->getMethods() as $mnode) {
         if ((!$mnode->isPublic() || $mnode->isStatic()) && $this->funcTable->has($mnode->name)) {
             $this->emitNonPub($mnode);
         } elseif (ParserHelper::isSameFunc($mnode->name, '__toString') && count($mnode->params) > 0) {
             $this->emitToString($mnode);
         }
     }
 }
Example #5
0
 public function leaveNode($node)
 {
     // json_decode()
     if ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->name, 'json_decode')) {
         /**
          * {Description}
          * json_decode() now rejects non-lowercase variants of the JSON
          * literals true, false and null at all times, as per the JSON
          * specification, and sets json_last_error() accordingly.
          * Previously, inputs to json_decode() that consisted solely of one
          * of these values in upper or mixed case were accepted.
          *
          * This change will only affect cases where invalid JSON was being
          * passed to json_decode(): valid JSON input is unaffected and will
          * continue to be parsed normally.
          *
          * {Reference}
          * http://php.net/manual/en/migration56.incompatible.php#migration56.incompatible.json-decode
          */
         $this->addSpot('NOTICE', false, 'json_decode() rejects non-lowercase variants of true, false, null');
         // GMP
     } elseif ($node instanceof Expr\FuncCall && $this->gmpTable->has($node->name)) {
         /**
          * {Description}
          * GMP resources are now objects. The functional API implemented in
          * the GMP extension has not changed, and code should run
          * unmodified unless it checks explicitly for a resource using
          * is_resource() or similar.
          *
          * {Reference}
          * http://php.net/manual/en/migration56.incompatible.php#migration56.incompatible.gmp
          */
         $this->addSpot('NOTICE', false, 'GMP resource is now object, do not use is_resource() to test');
         // Mcrypt
     } elseif ($node instanceof Expr\FuncCall && $this->mcryptTable->has($node->name)) {
         /**
          * {Description}
          * mcrypt_encrypt(), mcrypt_decrypt(), mcrypt_cbc(), mcrypt_cfb(),
          * mcrypt_ecb(), mcrypt_generic() and mcrypt_ofb() will no longer
          * accept keys or IVs with incorrect sizes, and block cipher modes
          * that require IVs will now fail if an IV isn't provided.
          *
          * {Reference}
          * http://php.net/manual/en/migration56.incompatible.php#migration56.incompatible.mcrypt
          */
         $this->addSpot('NOTICE', false, $node->name . '() no longer accept keys or IVs with incorrect size');
     }
 }
 public function leaveNode($node)
 {
     $non_public = [];
     $has_magic_call = false;
     if ($node instanceof Stmt\Class_) {
         foreach ($node->getMethods() as $mnode) {
             if (ParserHelper::isSameFunc($mnode->name, '__call')) {
                 $has_magic_call = true;
                 $magic_node = $mnode;
             } elseif (!$mnode->isPublic()) {
                 $non_public[] = $mnode->name;
             }
         }
     }
     if ($has_magic_call && $non_public) {
         $this->emitSpot($magic_node, $non_public);
     }
 }
 public function leaveNode($node)
 {
     /**
      * {Description}
      * These words have special meaning in PHP. Some of them represent
      * things which look like functions, some look like constants, and so
      * on - but they're not, really: they are language constructs. You
      * cannot use any of the following words as constants, class names,
      * function or method names. Using them as variable names is generally
      * OK, but could lead to confusion.
      *
      * {Reference}
      * http://php.net/manual/en/reserved.keywords.php
      */
     $name = null;
     if ($node instanceof Stmt\ClassLike || $node instanceof Stmt\Function_ || $node instanceof Stmt\ClassMethod || $node instanceof Expr\MethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\ConstFetch || $node instanceof Expr\FuncCall && !ParserHelper::isDynamicCall($node)) {
         $name = $node->migName;
     }
     if (!is_null($name) && $this->wordTable->has($name)) {
         $this->addSpot('FATAL', true, 'Keyword "' . $name . '" is reserved');
     }
 }
Example #8
0
 public function leaveNode($node)
 {
     /**
      * {Description}
      * Changes were made to pack() and unpack() to make them more compatible with Perl:
      *
      * pack() now supports the "Z" format code, which behaves identically
      * to "a".
      *
      * unpack() now support the "Z" format code for NULL padded strings,
      * and behaves as "a" did in previous versions: it will strip trailing
      * NULL bytes.
      *
      * unpack() now keeps trailing NULL bytes when the "a" format code is
      * used.
      *
      * unpack() now strips all trailing ASCII whitespace when the "A"
      * format code is used.
      *
      * {Reference}
      * http://php.net/manual/en/migration55.incompatible.php#migration55.incompatible.pack
      */
     if ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->name, 'unpack')) {
         $affected = true;
         $certain = false;
         if (!isset($node->args[0])) {
             return;
         }
         $format = $node->args[0]->value;
         // Try to check arg $format
         if ($format instanceof Scalar\String_) {
             // using stripos for both "a" and "A"
             $certain = $affected = stripos($format->value, 'a') !== false;
         }
         if ($affected) {
             $this->addSpot('WARNING', $certain, 'Behavior of pack() with "a", "A" in format is changed');
         }
     }
 }
Example #9
0
 public function leaveNode($node)
 {
     // array_combine()
     if ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->name, 'array_combine')) {
         /**
          * {Description}
          * array_combine() now returns array() instead of FALSE when two empty
          * arrays are provided as parameters.
          *
          * {Reference}
          * http://php.net/manual/en/migration54.incompatible.php
          */
         $this->addSpot('NOTICE', false, 'array_combine() now returns array() instead of FALSE when two empty arrays given');
         // ob_start()
     } elseif ($node instanceof Expr\FuncCall && ParserHelper::isSameFunc($node->name, 'ob_start') && isset($node->args[2])) {
         /**
          * {Description}
          * The third parameter of ob_start() has changed from boolean erase
          * to integer flags. Note that code that explicitly set erase to
          * FALSE will no longer behave as expected in PHP 5.4: please
          * follow this example to write code that is compatible with PHP
          * 5.3 and 5.4.
          *
          * {Reference}
          * http://php.net/manual/en/function.ob-start.php
          * http://php.net/manual/en/migration54.incompatible.php
          */
         $this->addSpot('WARNING', true, 'The third parameter of ob_start() has changed');
     } elseif ($node instanceof Expr\FuncCall && (ParserHelper::isSameFunc($node->name, 'htmlentities') || ParserHelper::isSameFunc($node->name, 'htmlspecialchars'))) {
         /**
          * {Description}
          * If you use htmlentities() with asian character sets, it works
          * like htmlspecialchars() - this has always been the case in
          * previous versions of PHP, but now an E_STRICT level error is
          * emitted.
          *
          * The default character set for htmlspecialchars() and
          * htmlentities() is now UTF-8, instead of ISO-8859-1. Note that
          * changing your output charset via the default_charset
          * configuration setting does not affect
          * htmlspecialchars/htmlentities unless you are passing "" (an
          * empty string) as the encoding parameter to your
          * htmlspecialchars()/htmlentities() calls. Generally we do not
          * recommend doing this because you should be able to change your
          * output charset without affecting the runtime charset used by
          * these functions. The safest approach is to explicitly set the
          * charset on each call to htmlspecialchars() and htmlentities().
          *
          * {Reference}
          * http://php.net/manual/en/function.htmlentities.php
          * http://php.net/manual/en/function.htmlspecialchars.php
          * http://php.net/manual/en/migration54.other.php
          * http://php.net/manual/en/migration54.incompatible.php
          */
         $level = false;
         $msgbox = [];
         if (ParserHelper::isSameFunc($node->name, 'htmlentities')) {
             $level = 'WARNING';
             $msgbox[] = 'won\'t encode asian character sets';
         }
         if (!isset($node->args[2])) {
             // Set encoding
             $level = 'NOTICE';
             $msgbox[] = 'default encoding was changed';
         }
         if ($level) {
             $this->addSpot($level, false, $node->name . '() ' . implode(', ', $msgbox));
         }
     }
 }
Example #10
0
 public function leaveNode($node)
 {
     if ($node instanceof Expr\FuncCall) {
         if (ParserHelper::isSameFunc($node->name, 'clearstatcache')) {
             /**
              * {Description}
              * clearstatcache() no longer clears the realpath cache by default.
              *
              * {Reference}
              * http://php.net/manual/en/migration53.incompatible.php
              */
             $this->addSpot('NOTICE', false, 'clearstatcache() no longer clears the realpath cache by default');
         } elseif (ParserHelper::isSameFunc($node->name, 'realpath')) {
             /**
              * {Description}
              * realpath() is now fully platform-independent. Consequence of
              * this is that invalid relative paths such as __FILE__ . "/../x"
              * do not work anymore.
              * Prior to this release, if only the last path component did not
              * exist, realpath() would not fail on *BSD systems. realpath() now
              * fails in this case.
              *
              * {Reference}
              * http://php.net/manual/en/function.realpath.php
              * http://php.net/manual/en/migration53.incompatible.php
              */
             $this->addSpot('NOTICE', false, 'realpath() is now fully platform-independent, especially on *BSD.');
         } elseif ($this->arrFuncTable->has($node->name)) {
             /**
              * {Description}
              * The array functions natsort(), natcasesort(), usort(), uasort(),
              * uksort(), array_flip(), and array_unique() no longer accept
              * objects passed as arguments. To apply these functions to an
              * object, cast the object to an array first.
              *
              * {Reference}
              * http://php.net/manual/en/migration53.incompatible.php
              */
             $this->addSpot('NOTICE', false, sprintf('%s() no longer accept objects passed as arguments', $node->name));
         } elseif (ParserHelper::isSameFunc($node->name, 'call_user_func_array')) {
             /**
              * {Description}
              * call_user_func_array() no longer accepts null as a second
              * parameter and calls the function. It now emits a warning and
              * does not call the function.
              *
              * {Reference}
              * User Contributed Notes by Chris Bolt
              * http://php.net/manual/en/migration53.incompatible.php
              */
             if (isset($node->args[1]) && !$node->args[1]->value instanceof Expr\Array_) {
                 $this->addSpot('NOTICE', false, sprintf('%s() no longer accept non-array passed as arguments', $node->name));
             }
         } elseif (ParserHelper::isSameFunc($node->name, 'gd_info')) {
             /**
              * {Description}
              * Image Processing and GD The "JPG Support" index returned from
              * gd_info() has been renamed to "JPEG Support".
              *
              * {Reference}
              * http://php.net/manual/en/migration53.extensions-other.php
              */
             $this->addSpot('NOTICE', false, 'gd_info() JPG Support attribute renamed to JPEG Support');
         }
     }
 }
 /**
  * Conditional checking
  */
 protected function isConditionalDeclare($node, $testfunc)
 {
     if (!$node instanceof Stmt\If_ || !$node->cond instanceof Expr\BooleanNot) {
         return false;
     }
     $expr = $node->cond->expr;
     return $expr instanceof Expr\FuncCall && ParserHelper::isSameFunc($expr->migName, $testfunc);
 }
 protected function populateCall($node, $type)
 {
     if (ParserHelper::isDynamicCall($node)) {
         return;
     }
     $posbit = $this->positionByValue($node);
     if (!$posbit) {
         return;
     }
     if ($type == 'func') {
         $callname = $node->name;
     } elseif ($type == 'static') {
         $class = $node->class->toString();
         if ($class == 'self' && $this->visitor->inClass()) {
             $class = $this->visitor->getClassName();
         }
         $callname = $class . '::' . $node->name;
     } elseif ($type == 'method') {
         if ($node->var instanceof Expr\Variable && $node->var->name == 'this' && $this->visitor->inClass()) {
             $oname = $this->visitor->getClassName();
         } else {
             $oname = '';
         }
         $callname = $oname . '->' . $node->name;
     }
     $this->callList[] = ['name' => $callname, 'pos' => $posbit, 'file' => $this->visitor->getFile(), 'line' => $node->getLine()];
 }