Tim Starling has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/338309 )

Change subject: Guard against runtime creation of undeclared properties
......................................................................

Guard against runtime creation of undeclared properties

And fix the bugs which were thus detected.

Also fix an error in TokenGeneratorHandler.

Change-Id: Ica8ebc5ea910e6093e330e90c3e58f9ae167595a
---
A src/PropGuard.php
M src/Serializer/Serializer.php
M src/Serializer/SerializerNode.php
M src/Tokenizer/Attribute.php
M src/Tokenizer/TokenGeneratorHandler.php
M src/Tokenizer/Tokenizer.php
M src/TreeBuilder/Element.php
M src/TreeBuilder/InsertionMode.php
M src/TreeBuilder/Marker.php
M src/TreeBuilder/TreeBuilder.php
M tests/phpunit/SerializerNodeDestructionTest.php
11 files changed, 81 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/libs/RemexHtml 
refs/changes/09/338309/1

diff --git a/src/PropGuard.php b/src/PropGuard.php
new file mode 100644
index 0000000..00c3c4d
--- /dev/null
+++ b/src/PropGuard.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace RemexHtml;
+
+/**
+ * This is a statically configurable mechanism for preventing the setting of
+ * undeclared properties on objects. The point of it is to detect programmer
+ * errors.
+ */
+class PropGuard {
+       public static $armed = true;
+
+       public static function set( $obj, $name, $value ) {
+               if ( self::$armed ) {
+                       throw new \Exception( "Property \"$name\" on object of 
class " . get_class( $obj ) .
+                               " is undeclared" );
+               } else {
+                       $obj->$name = $value;
+               }
+       }
+}
diff --git a/src/Serializer/Serializer.php b/src/Serializer/Serializer.php
index 65da72e..ad7ec8d 100644
--- a/src/Serializer/Serializer.php
+++ b/src/Serializer/Serializer.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace RemexHtml\Serializer;
+use RemexHtml\PropGuard;
 use RemexHtml\TreeBuilder\TreeBuilder;
 use RemexHtml\TreeBuilder\TreeHandler;
 use RemexHtml\TreeBuilder\Element;
@@ -52,6 +53,11 @@
        private $isFragment;
 
        /**
+        * The result string
+        */
+       private $result = '';
+
+       /**
         * Constructor
         *
         * @param Formatter $formatter
@@ -63,6 +69,10 @@
                $this->errorCallback = $errorCallback;
        }
 
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
+
        /**
         * Get the final string. This can only be called after endDocument() is 
received.
         */
diff --git a/src/Serializer/SerializerNode.php 
b/src/Serializer/SerializerNode.php
index f19b20e..2944732 100644
--- a/src/Serializer/SerializerNode.php
+++ b/src/Serializer/SerializerNode.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace RemexHtml\Serializer;
+use RemexHtml\PropGuard;
 
 class SerializerNode {
        public $id;
@@ -24,4 +25,8 @@
                $this->attrs = $attrs;
                $this->void = $void;
        }
+
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
 }
diff --git a/src/Tokenizer/Attribute.php b/src/Tokenizer/Attribute.php
index b53e3c0..293b075 100644
--- a/src/Tokenizer/Attribute.php
+++ b/src/Tokenizer/Attribute.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace RemexHtml\Tokenizer;
+use RemexHtml\PropGuard;
 
 /**
  * A namespaced attribute, as returned by Attributes::getObjects()
@@ -19,4 +20,8 @@
                $this->localName = $localName;
                $this->value = $value;
        }
+
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
 }
diff --git a/src/Tokenizer/TokenGeneratorHandler.php 
b/src/Tokenizer/TokenGeneratorHandler.php
index 4d05b73..29f94f0 100644
--- a/src/Tokenizer/TokenGeneratorHandler.php
+++ b/src/Tokenizer/TokenGeneratorHandler.php
@@ -16,7 +16,7 @@
                ];
        }
 
-       public function endDocument() {
+       public function endDocument( $pos ) {
                $this->tokens[] = [ 'type' => 'endDocument' ];
        }
 
diff --git a/src/Tokenizer/Tokenizer.php b/src/Tokenizer/Tokenizer.php
index f571aba..78b2383 100644
--- a/src/Tokenizer/Tokenizer.php
+++ b/src/Tokenizer/Tokenizer.php
@@ -2,6 +2,7 @@
 
 namespace RemexHtml\Tokenizer;
 use RemexHtml\HTMLData;
+use RemexHtml\PropGuard;
 
 /**
  * HTML 5 tokenizer
@@ -67,6 +68,8 @@
        protected $ignoreErrors;
        protected $ignoreCharRefs;
        protected $ignoreNulls;
+       protected $skipPreprocess;
+       protected $appropriateEndTag;
        protected $listener;
        protected $state;
        protected $preprocessed;
@@ -110,6 +113,10 @@
                $this->skipPreprocess = !empty( $options['skipPreprocess'] );
        }
 
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
+
        public function setEnableCdataCallback( $cb ) {
                $this->enableCdataCallback = $cb;
        }
diff --git a/src/TreeBuilder/Element.php b/src/TreeBuilder/Element.php
index c571a12..56d0ff5 100644
--- a/src/TreeBuilder/Element.php
+++ b/src/TreeBuilder/Element.php
@@ -2,6 +2,7 @@
 
 namespace RemexHtml\TreeBuilder;
 use RemexHtml\HTMLData;
+use RemexHtml\PropGuard;
 use RemexHtml\Tokenizer\Attributes;
 
 /**
@@ -54,6 +55,12 @@
         * Internal to CachingStack. A link in the scope list.
         */
        public $nextScope;
+
+       /**
+        * Internal to CachingStack and SimpleStack. The current stack index, or
+        * null if the element is not in the stack.
+        */
+       public $stackIndex;
 
        /**
         * Internal to ActiveFormattingElements.
@@ -118,6 +125,10 @@
                $this->attrs = $attrs;
        }
 
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
+
        /**
         * Is the element a MathML text integration point?
         *
diff --git a/src/TreeBuilder/InsertionMode.php 
b/src/TreeBuilder/InsertionMode.php
index 9b4e6b8..5d4cd08 100644
--- a/src/TreeBuilder/InsertionMode.php
+++ b/src/TreeBuilder/InsertionMode.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace RemexHtml\TreeBuilder;
+use RemexHtml\PropGuard;
 use RemexHtml\Tokenizer\Attributes;
 use RemexHtml\Tokenizer\TokenHandler;
 
@@ -15,6 +16,10 @@
                $this->dispatcher = $dispatcher;
        }
 
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
+
        public function doctype( $name, $public, $system, $quirks, 
$sourceStart, $sourceLength ) {
                $this->builder->error( "unexpected doctype", $sourceStart );
        }
diff --git a/src/TreeBuilder/Marker.php b/src/TreeBuilder/Marker.php
index 8bd8eb8..80029e5 100644
--- a/src/TreeBuilder/Marker.php
+++ b/src/TreeBuilder/Marker.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace RemexHtml\TreeBuilder;
+use RemexHtml\PropGuard;
 
 /**
  * A pseudo-element used as a marker or bookmark in the list of active 
formatting elements
@@ -8,10 +9,15 @@
 class Marker implements FormattingElement {
        public $nextAFE;
        public $prevAFE;
+       public $nextNoah;
        public $type;
 
        public function __construct( $type ) {
                $this->type = $type;
        }
+
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
 }
 
diff --git a/src/TreeBuilder/TreeBuilder.php b/src/TreeBuilder/TreeBuilder.php
index 7a1f1d1..3523773 100644
--- a/src/TreeBuilder/TreeBuilder.php
+++ b/src/TreeBuilder/TreeBuilder.php
@@ -2,6 +2,7 @@
 
 namespace RemexHtml\TreeBuilder;
 use RemexHtml\HTMLData;
+use RemexHtml\PropGuard;
 use RemexHtml\Tokenizer\Attributes;
 use RemexHtml\Tokenizer\PlainAttributes;
 use RemexHtml\Tokenizer\Tokenizer;
@@ -50,6 +51,7 @@
        public $framesetOK = true;
        public $quirks = self::NO_QUIRKS;
        public $fosterParenting = false;
+       public $pendingTableCharacters = [];
 
        private static $fosterTriggers = [
                'table' => true,
@@ -116,6 +118,10 @@
                }
        }
 
+       public function __set( $name, $value ) {
+               PropGuard::set( $this, $name, $value );
+       }
+
        public function startDocument( Tokenizer $tokenizer, $namespace, $name 
) {
                $tokenizer->setEnableCdataCallback(
                        function () {
diff --git a/tests/phpunit/SerializerNodeDestructionTest.php 
b/tests/phpunit/SerializerNodeDestructionTest.php
index 077e0b4..73d6d8c 100644
--- a/tests/phpunit/SerializerNodeDestructionTest.php
+++ b/tests/phpunit/SerializerNodeDestructionTest.php
@@ -36,8 +36,8 @@
                $sourceStart, $sourceLength
        ) {
                $this->wrap( __FUNCTION__, func_get_args() );
-               if ( !isset( $element->userData->testDestruct ) ) {
-                       $element->userData->testDestruct = new DestructNode( 
$this->count );
+               if ( !$element->userData->snData ) {
+                       $element->userData->snData = new DestructNode( 
$this->count );
                }
        }
 
@@ -71,8 +71,8 @@
                $sourceStart
        ) {
                $this->wrap( __FUNCTION__, func_get_args() );
-               if ( !isset( $newParent->userData->testDestruct ) ) {
-                       $newParent->userData->testDestruct = new DestructNode( 
$this->count );
+               if ( !$newParent->userData->snData ) {
+                       $newParent->userData->snData = new DestructNode( 
$this->count );
                }
        }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/338309
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ica8ebc5ea910e6093e330e90c3e58f9ae167595a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/libs/RemexHtml
Gerrit-Branch: master
Gerrit-Owner: Tim Starling <tstarl...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to