From 3a607a44b27bf794f84daa75c4ff9c6990e4caf6 Mon Sep 17 00:00:00 2001 From: Philip Hofstetter Date: Fri, 30 Aug 2024 15:28:38 +0200 Subject: [PATCH 1/2] deprecate json_encode() of non-serializable instances there's a good reason for classes being marked as non-serializable, so it follows that the same should probably be true for json_encoding them as well. As this flag is only available to internal classes, no userland code should be affected. --- ext/json/json_encoder.c | 3 +++ .../json_encode_non_serializable_deprecated.phpt | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/classes/json_encode_non_serializable_deprecated.phpt diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 1e344cde436ff..4f95c86bca43a 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -677,6 +677,9 @@ zend_result php_json_encode_zval(smart_str *buf, zval *val, int options, php_jso if (Z_OBJCE_P(val)->ce_flags & ZEND_ACC_ENUM) { return php_json_encode_serializable_enum(buf, val, options, encoder); } + if (Z_OBJCE_P(val)->ce_flags & ZEND_ACC_NOT_SERIALIZABLE) { + zend_error(E_DEPRECATED, "json_encode() of non-serializable class %s is deprecated", ZSTR_VAL(Z_OBJCE_P(val)->name)); + } /* fallthrough -- Non-serializable object */ ZEND_FALLTHROUGH; case IS_ARRAY: { diff --git a/tests/classes/json_encode_non_serializable_deprecated.phpt b/tests/classes/json_encode_non_serializable_deprecated.phpt new file mode 100644 index 0000000000000..6def5da0bb340 --- /dev/null +++ b/tests/classes/json_encode_non_serializable_deprecated.phpt @@ -0,0 +1,15 @@ +--TEST-- +json_encode() on instances of classes market with ZEND_ACC_NOT_SERIALIZABLE +--FILE-- + +--EXPECTF-- +Deprecated: json_encode() of non-serializable class Generator is deprecated in %s on line %d +{} +Deprecated: json_encode() of non-serializable class Closure is deprecated in %s on line %d +{} From 588ad2b96e5da5b6f3a7280c405c86ba8bf985f3 Mon Sep 17 00:00:00 2001 From: Philip Hofstetter Date: Thu, 5 Sep 2024 10:10:53 +0200 Subject: [PATCH 2/2] allow json_encode() on most anonymous classes anonymous classes are market as ZEND_ACC_NOT_SERIALIZABLE because unserisalizing them for later use is hard to impossible. However, in the case jon json_encode(), as long as the parent class is serializable, there's very little reason to forbidding to json_encode() anonymous classes, indeed, that's probably very useful in case of userland parent classes. --- ext/json/json_encoder.c | 4 +++- .../classes/json_encode_non_serializable_deprecated.phpt | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 4f95c86bca43a..f074389c6f38e 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -678,7 +678,9 @@ zend_result php_json_encode_zval(smart_str *buf, zval *val, int options, php_jso return php_json_encode_serializable_enum(buf, val, options, encoder); } if (Z_OBJCE_P(val)->ce_flags & ZEND_ACC_NOT_SERIALIZABLE) { - zend_error(E_DEPRECATED, "json_encode() of non-serializable class %s is deprecated", ZSTR_VAL(Z_OBJCE_P(val)->name)); + if (!(Z_OBJCE_P(val)->ce_flags & ZEND_ACC_ANON_CLASS) || (Z_OBJCE_P(val)->parent && Z_OBJCE_P(val)->parent->ce_flags & ZEND_ACC_NOT_SERIALIZABLE)) { + zend_error(E_DEPRECATED, "json_encode() of non-serializable class %s is deprecated", ZSTR_VAL(Z_OBJCE_P(val)->name)); + } } /* fallthrough -- Non-serializable object */ ZEND_FALLTHROUGH; diff --git a/tests/classes/json_encode_non_serializable_deprecated.phpt b/tests/classes/json_encode_non_serializable_deprecated.phpt index 6def5da0bb340..a1673373ef5fd 100644 --- a/tests/classes/json_encode_non_serializable_deprecated.phpt +++ b/tests/classes/json_encode_non_serializable_deprecated.phpt @@ -5,11 +5,20 @@ json_encode() on instances of classes market with ZEND_ACC_NOT_SERIALIZABLE function a() { for ($i=0; $i < 10; $i++) { yield $i; }}; $fn = a(...); +$c1 = new class() extends PDOStatement {}; +$c2 = new class() extends stdClass {}; +$c3 = new class() {}; + echo json_encode(a()); echo json_encode($fn); +echo json_encode($c1); +echo json_encode($c2); +echo json_encode($c3); ?> --EXPECTF-- Deprecated: json_encode() of non-serializable class Generator is deprecated in %s on line %d {} Deprecated: json_encode() of non-serializable class Closure is deprecated in %s on line %d {} +Deprecated: json_encode() of non-serializable class PDOStatement@anonymous is deprecated in %s on line %d +{}{}{}