Kaynağa Gözat

[php] avoid infinite recursion on stringification (fixes #6180)

Alexander Kuzmenko 6 yıl önce
ebeveyn
işleme
075787f8ef

+ 17 - 3
std/php/Boot.hx

@@ -325,7 +325,10 @@ class Boot {
 	/**
 		Returns string representation of `value`
 	**/
-	public static function stringify( value : Dynamic ) : String {
+	public static function stringify( value : Dynamic, maxRecursion:Int = 10 ) : String {
+		if(maxRecursion <= 0) {
+			return '<...>';
+		}
 		if (value == null) {
 			return 'null';
 		}
@@ -341,11 +344,14 @@ class Boot {
 		if (value.is_array()) {
 			var strings = Syntax.arrayDecl();
 			Syntax.foreach(value, function(key:Dynamic, item:Dynamic) {
-				Global.array_push(strings, (key:String) + ' => ' + stringify(item));
+				strings.push(Syntax.string(key) + ' => ' + stringify(item, maxRecursion - 1));
 			});
 			return '[' + Global.implode(', ', strings) + ']';
 		}
 		if (value.is_object()) {
+			if(Std.is(value, Array)) {
+				return inline stringifyNativeIndexedArray(value.arr, maxRecursion - 1);
+			}
 			if (value.method_exists('toString')) {
 				return value.toString();
 			}
@@ -359,7 +365,7 @@ class Boot {
 				var result = new NativeIndexedArray<String>();
 				var data = Global.get_object_vars(value);
 				for (key in data.array_keys()) {
-					result.array_push('$key : ' + stringify(data[key]));
+					result.array_push('$key : ' + stringify(data[key], maxRecursion - 1));
 				}
 				return '{ ' + Global.implode(', ', result) + ' }';
 			}
@@ -375,6 +381,14 @@ class Boot {
 		throw "Unable to stringify value";
 	}
 
+	static public function stringifyNativeIndexedArray<T>( arr : NativeIndexedArray<T>, maxRecursion : Int = 10 ) : String {
+		var strings = Syntax.arrayDecl();
+		Syntax.foreach(arr, function(index:Int, value:T) {
+			strings[index] = Boot.stringify(value, maxRecursion - 1);
+		});
+		return '[' + Global.implode(',', strings) + ']';
+	}
+
 	static public inline function isNumber( value:Dynamic ) {
 		return value.is_int() || value.is_float();
 	}

+ 4 - 0
std/php/NativeIndexedArray.hx

@@ -51,6 +51,10 @@ abstract NativeIndexedArray<T>(NativeArray) from NativeArray to NativeArray {
 	@:from
 	static inline function fromHaxeArray<T>(a:Array<T>):NativeIndexedArray<T>
 		return @:privateAccess a.arr;
+
+	public inline function toString():String {
+		return Boot.stringifyNativeIndexedArray(this);
+	}
 }
 
 private class NativeIndexedArrayIterator<T> {

+ 1 - 2
std/php/_std/Array.hx

@@ -170,8 +170,7 @@ final class Array<T> implements ArrayAccess<Int,T> {
 	}
 
 	public function toString():String {
-		var strings = Global.implode(',', Global.array_map(Syntax.nativeClassName(Boot) + '::stringify', arr));
-		return '[' + strings + ']';
+		return inline Boot.stringifyNativeIndexedArray(arr);
 	}
 
 	public function resize( len:Int ) : Void {

+ 2 - 0
tests/unit/src/unit/TestPhp.hx

@@ -265,6 +265,8 @@ class TestPhp extends Test
 		}
 		aeq([for(i in 0...expected.length) i], indexes);
 		aeq(expected, values);
+
+		eq('[10,20,30]', Std.string(a));
 	}
 
 	function testNativeAssocArray() {