From f07ce7f9745c61e5151c4355d29374b08d2a8933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20M=C3=AD=C5=A1ek?= Date: Tue, 25 Feb 2025 13:12:00 +0100 Subject: [PATCH] safe print_r/var_dump when resolving property values ref https://github.com/peachpiecompiler/peachpie/issues/1162 --- src/Peachpie.Library/Variables.cs | 6 +++- .../Reflection/TypeMembersUtils.cs | 29 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Peachpie.Library/Variables.cs b/src/Peachpie.Library/Variables.cs index 1ceebcc6c5..29f3d5120a 100644 --- a/src/Peachpie.Library/Variables.cs +++ b/src/Peachpie.Library/Variables.cs @@ -1027,7 +1027,11 @@ public override void AcceptObject(object obj) _indent++; // object members - var flds = (obj is IPhpPrintable printable ? printable.Properties : TypeMembersUtils.EnumerateInstanceFieldsForPrint(obj)).ToList(); + var flds = obj is IPhpPrintable printable + ? printable.Properties + : TypeMembersUtils.EnumerateInstanceFieldsForPrint(obj) + ; + foreach (var fld in flds) { // [name] => value diff --git a/src/Peachpie.Runtime/Reflection/TypeMembersUtils.cs b/src/Peachpie.Runtime/Reflection/TypeMembersUtils.cs index c36eb28876..5af94b24fa 100644 --- a/src/Peachpie.Runtime/Reflection/TypeMembersUtils.cs +++ b/src/Peachpie.Runtime/Reflection/TypeMembersUtils.cs @@ -81,7 +81,8 @@ public static IEnumerable> EnumerateVisible return EnumerateInstanceFields(instance, (p) => new IntStringKey(p.PropertyName), FuncExtensions.Identity(), - (m) => m.IsVisible(caller)); + (m) => m.IsVisible(caller) + ); } /// @@ -93,9 +94,23 @@ public static IEnumerable> EnumerateInstanceField { return EnumerateInstanceFields(instance, s_formatPropertyNameForPrint, - s_keyToString); + s_keyToString, + getValue: s_getValueWithTryCatch + ); } + static readonly Func s_getValueWithTryCatch = (p, instance) => + { + try + { + return p.GetValue(null, instance); + } + catch (Exception e) + { + return $"Property '{p.PropertyName}' threw an exception of type {e.GetType().Name}: {e.Message}"; + } + }; + public static readonly Func s_keyToString = k => k.ToString(); public static readonly Func s_propertyName = p => p.PropertyName; @@ -127,7 +142,9 @@ public static IEnumerable> EnumerateInstanceField { return EnumerateInstanceFields(instance, s_formatPropertyNameForDump, - s_keyToString); + s_keyToString, + getValue: s_getValueWithTryCatch + ); } /// @@ -170,9 +187,10 @@ public static IEnumerable> EnumerateInstanceField /// Function converting /// Optional. Predicate filtering fields. /// Whether to ignore listing runtime fields. + /// Function getting property value on given . /// Enumeration of fields and their values, including runtime fields. /// Enumerated pairs key. Usually . - public static IEnumerable> EnumerateInstanceFields(object instance, Func keyFormatter, Func keyFormatter2, Func predicate = null, bool ignoreRuntimeFields = false) + public static IEnumerable> EnumerateInstanceFields(object instance, Func keyFormatter, Func keyFormatter2, Func predicate = null, bool ignoreRuntimeFields = false, Func getValue = null) { Debug.Assert(instance != null); @@ -189,7 +207,8 @@ public static IEnumerable> EnumerateInstanceFields< { yield return new KeyValuePair( keyFormatter(p), - p.GetValue(null, instance)); + getValue != null ? getValue(p, instance) : p.GetValue(null, instance) + ); } } }