CVE-2011-3441
CVE-2011-3246
A series of regex-writing challenges.
A series of XSS challenges: here's some unsafe code; exploit it! Shortest code wins.

My CSS-fu is weak; please use a recent browser.

Some rights reserved.

Random, semi-related image by Andrew*.

PHP Closures

A hacky implementation of closures for PHP.

This article is from 2004 and is kept here for historical reasons. Apparently (as of 2008) PHP will get native support for closures soon, making this ugly hack even less useful.

Why?!

A closure is a standard feature found of most modern languages. Here's one explanation, and here's another... there's a nice Wikipedia article as well.

What we would like to have

Ideally, we could say something like this:

function rot13widget() {
        $a = new TextField();
        $b = new Button('Rotate!');

        $b->setClickHandler(function() {   // NOT VALID CODE!
                $a->setText(str_rot13($a->getText()));
        });
        return Layout::horizontal($a, $b);
}

$panel->add(rot13widget());
... the point being that the function object passed to onClick contains the necessary pointers to $a.

What we can get

We don't really want to add more stuff to the PHP parser. We can settle for this:

function rot13widget() {
        $a = new TextField();
        $b = new Button('Rotate!');

        $b->setClickHandler(eval(closure('
                $a->setText(str_rot13($a->getText()));
        ')));
        return Layout::horizontal($a, $b);
}

The button class would just store the function object, and call it like this:

class Button {
        function setClickHandler($o) {
                $this->clickHandler = $o;
        }
        function handleClick() {
                if($this->clickHandler)
                        $this->clickHandler->call();
        }
}

The hassle of maintaining the necessary pointers to the various widgets would be handled invisibly by the closure "library".

Implementation

What we do (internally) is this: the closure() function takes the snippet of code, does a very cheesy parse of it, and returns a magic string which is then evaluated by passing it to eval(). That code grabs the necessary variables from the outer scope, and wraps them in a Closure object. That object is then returned to the function that needs it. The call above would result in this string:

new Closure(
        '$a->setText(str_rot13($a->getText()));',
        array('a' => &$a));
Here's the actual code:

Downlod this snippet as closures.txt

/**
 * Simple closure class; Erling Ellingsen, 2003.
 *
 * http://steike.com/PhpClosures
 */

class Closure {	
  var $code;	
  var $env;	
	
  function Closure($code, $env) {
    $this->code = $code;
    $this->env = $env;
  }

  function call($__args = NULL) {
    // $this will probably be clobbered by the next step, so grab our
    // code and environment now
    $__code = $this->code;
    $__env =& $this->env;

    // set up the scope we need
    // extract() doesn't do references, so we can't use that
    foreach(array_keys($__env) as $__key)
      $$__key =& $__env[$__key];

    return eval($__code);
  }

  function makeGrabber($s) {
    $zot = $seen = array();

    // basically, grab everything that looks like a variable reference.
    // noone gets hurt if we happen to grab too much.
    if(preg_match_all('/\$(\w+)/', $s, $m))
      foreach($m[1] as $var) 
        if(!$seen[$var]++)
          $zot[] = "'$var' => &\$$var";

    $grabber = join(', ', $zot);

    $escaped = preg_replace("/['\\\\]/", "\\$&", $s);

    $grabber = "return new Closure('$escaped', array($grabber));";
    return $grabber;
  }
}

function closure($s) {
  return Closure::makeGrabber($s);
}


function _test_closure($n) {
  return eval(closure('
    return $n++;
  '));
}

$a =& _test_closure(5);
$b =& _test_closure(10);

assert($a->call() == 5);
assert($b->call() == 10);
assert($a->call() == 6);

Comments