comparison vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents
children
comparison
equal deleted inserted replaced
12:7a779792577d 13:5fb285c0d0e3
1 <?php declare(strict_types=1);
2
3 namespace PhpParser;
4
5 class JsonDecoder
6 {
7 /** @var \ReflectionClass[] Node type to reflection class map */
8 private $reflectionClassCache;
9
10 public function decode(string $json) {
11 $value = json_decode($json, true);
12 if (json_last_error()) {
13 throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg());
14 }
15
16 return $this->decodeRecursive($value);
17 }
18
19 private function decodeRecursive($value) {
20 if (\is_array($value)) {
21 if (isset($value['nodeType'])) {
22 if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
23 return $this->decodeComment($value);
24 }
25 return $this->decodeNode($value);
26 }
27 return $this->decodeArray($value);
28 }
29 return $value;
30 }
31
32 private function decodeArray(array $array) : array {
33 $decodedArray = [];
34 foreach ($array as $key => $value) {
35 $decodedArray[$key] = $this->decodeRecursive($value);
36 }
37 return $decodedArray;
38 }
39
40 private function decodeNode(array $value) : Node {
41 $nodeType = $value['nodeType'];
42 if (!\is_string($nodeType)) {
43 throw new \RuntimeException('Node type must be a string');
44 }
45
46 $reflectionClass = $this->reflectionClassFromNodeType($nodeType);
47 /** @var Node $node */
48 $node = $reflectionClass->newInstanceWithoutConstructor();
49
50 if (isset($value['attributes'])) {
51 if (!\is_array($value['attributes'])) {
52 throw new \RuntimeException('Attributes must be an array');
53 }
54
55 $node->setAttributes($this->decodeArray($value['attributes']));
56 }
57
58 foreach ($value as $name => $subNode) {
59 if ($name === 'nodeType' || $name === 'attributes') {
60 continue;
61 }
62
63 $node->$name = $this->decodeRecursive($subNode);
64 }
65
66 return $node;
67 }
68
69 private function decodeComment(array $value) : Comment {
70 $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
71 if (!isset($value['text'])) {
72 throw new \RuntimeException('Comment must have text');
73 }
74
75 return new $className(
76 $value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1
77 );
78 }
79
80 private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {
81 if (!isset($this->reflectionClassCache[$nodeType])) {
82 $className = $this->classNameFromNodeType($nodeType);
83 $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
84 }
85 return $this->reflectionClassCache[$nodeType];
86 }
87
88 private function classNameFromNodeType(string $nodeType) : string {
89 $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
90 if (class_exists($className)) {
91 return $className;
92 }
93
94 $className .= '_';
95 if (class_exists($className)) {
96 return $className;
97 }
98
99 throw new \RuntimeException("Unknown node type \"$nodeType\"");
100 }
101 }