Re: Null bytes in anonymous class names
| From: | Steven Hilder | Date: | Mon, 09 Nov 2015 15:27:14 +0000 |
| Subject: | Re: Null bytes in anonymous class names | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-89122@lists.php.net to get a copy of this message | ||
On Thu, 05 Nov 2015 15:14:47, Leigh <leight@gmail.com> wrote:
On 5 November 2015 at 14:59, Rowan Collins <rowan.collins@gmail.com> wrote:Internal names for anonymous classes need to be unique. The current method of ensuring uniqueness ('\0' + filename + lexer pos) was written by Dmitry[1], following from Joe's original implementation[2]. As I understand it, this was supposed to be entirely hidden from userland; hence the null byte. So, I prepared a patch forPHP uses null bytes quite a lot to produce deliberately illegal identifiers. For instance the old eval-like create_function() [e.g. https://3v4l.org/hqHjh] and the serialization of private members [e.g. https://3v4l.org/R6Y6k] In this case, I guess the "@" in "class@anonymous" makes the name illegal anyway, but I'm not sold on the null byte being more unacceptable here than anywhere else. Regards, -- Rowan Collins [IMSoP]That doesn't mean it's a good approach (*cough* namespaces *cough*), and these bits of "magic" are supposed to be hidden away from users. I'm guessing in this particular instance, the point of the null is to make string operations cut off after "anonymous", however string operations that respect the zval string length aren't going to do this. e.g. var_dump() the class name is put through sprintf and it cuts off at the null, but get_class or ReflectionClass::getName() just returns the original string, and exposes the implementation details.
get_class() and ReflectionClass::getName(),
which in my view should behave the same way as var_dump() etc., but I've
now realised that ignoring the unique suffix from the class name will break
functionality that is otherwise desirable:
* Aliasing an anonymous class... (see bug70106[3])
$instance = new class {};
$class_name = get_class($instance);
class_alias($class_name, 'MyAlias');
* Creating a new anonymous class instance dynamically...
$instance = new class {};
$class_name = get_class($instance);
$new_instance = new $class_name;
...although theOur options seem to be: (A) Leave everything as it is. This puts us in a situation where anonymousget_class()used here isn't necessary, and you could write= new $instance;without ever knowing $instance's class.
class names are treated inconsistently in userland; a situation that I
think could lead to considerable confusion about the "real" names of
these classes and how they should be used.
(B) Patch get_class() and ReflectionClass::getName() (any others?) to
strip the suffix (the '\0' and everything after it) from anonymous class
names prior to display. This prevents userland code from distinguishing
between multiple anonymous classes; breaking functionality as described
above. To mitigate this, we could allow class_alias() to accept either
a class name OR an instance in the first argument. The new operator
already supports an instance in place of a class name.
(C) Assuming that userland SHOULD have access to the internal names of
anonymous classes, remove the null byte so that the full names are
displayed everywhere. The drawback of this option is that class names
won't be as predictable. It occurs to me that a different naming scheme
could help here - wouldn't a monotonically increasing integer suffix be
enough? The current scheme seems like an awful waste of memory, too.
Option (B) seems like the best to me, because I can't really see a need to
know the unique suffix -- provided any use-cases are catered for by an
alternative (modifying class_alias() should be enough).
Thoughts?
Steve
[1] http://git.php.net/?p=php-src.git;a=commitdiff;h=2a1b0b1#patch1
[2] http://git.php.net/?p=php-src.git;a=commitdiff;h=49608e0#patch12
[3] https://bugs.php.net/bug.php?id=70106