Category
Regression · php-src-strict · stdlib · intl · serialize · pillar 4
Problem
Zend marks Intl formatter / calendar / collator / resource-bundle classes @not-serializable. The VM emits empty O:…:0:{} payloads instead of throwing.
Verified 2026-07-25 (host Zend PHP 8.2.32 vs php bin/vm.php):
| Repro |
Zend 8.2+ |
VM |
serialize(new IntlDateFormatter(…)) |
Exception: Serialization of 'IntlDateFormatter' is not allowed |
O:17:"IntlDateFormatter":0:{} |
serialize(new NumberFormatter(…)) |
Exception: … 'NumberFormatter' … |
O:15:"NumberFormatter":0:{} |
serialize(new Collator(…)) |
Exception: … 'Collator' … |
O:8:"Collator":0:{} |
serialize(new MessageFormatter(…)) |
Exception: … 'MessageFormatter' … |
O:16:"MessageFormatter":0:{} |
serialize(ResourceBundle::create(…)) |
Exception: … 'ResourceBundle' … |
O:14:"ResourceBundle":0:{} |
serialize(IntlCalendar::createInstance()) |
Exception: … 'IntlGregorianCalendar' … |
O:21:"IntlGregorianCalendar":0:{} |
Sibling of CurlHandle/SimpleXMLElement serialize bans (#23074, #23072). Separate from ResourceBundle create/fallback parity (#22902, #22854).
php-src reference
PHP implementation target
- Shared serialize/unserialize deny in
ext/intl/ (+ hook from ext/standard/VmSerialize.php) — throw Zend-identical Exception
- Reuse pattern from
CurlFileSerializeDeny / SimpleXmlSerializeDeny; PHP-in-PHP; no new runtime/*.c
- Cover subclass name in message (
IntlGregorianCalendar when that is the runtime class)
Repro
./script/docker-exec.sh -- bash -lc 'cat > /tmp/intl_ser.php <<'"'"'PHP'"'"'
<?php
\$objs = [
"IntlDateFormatter" => new IntlDateFormatter("en_US", IntlDateFormatter::FULL, IntlDateFormatter::FULL),
"NumberFormatter" => new NumberFormatter("en_US", NumberFormatter::DECIMAL),
"Collator" => new Collator("en_US"),
"MessageFormatter" => new MessageFormatter("en_US", "{0}"),
"ResourceBundle" => ResourceBundle::create("en", "ICUDATA"),
"IntlCalendar" => IntlCalendar::createInstance(),
];
foreach (\$objs as \$n => \$o) {
try {
echo \$n, " ALLOW ", substr(serialize(\$o), 0, 40), "\n";
} catch (Throwable \$e) {
echo \$n, " ", get_class(\$e), ":", \$e->getMessage(), "\n";
}
}
PHP
php bin/vm.php /tmp/intl_ser.php
# expect Exception:Serialization of '"'"'<Class>'"'"' is not allowed for each
'
Done when
Category
Regression· php-src-strict · stdlib · intl · serialize · pillar 4Problem
Zend marks Intl formatter / calendar / collator / resource-bundle classes
@not-serializable. The VM emits emptyO:…:0:{}payloads instead of throwing.Verified 2026-07-25 (host Zend PHP 8.2.32 vs
php bin/vm.php):serialize(new IntlDateFormatter(…))Exception: Serialization of 'IntlDateFormatter' is not allowedO:17:"IntlDateFormatter":0:{}serialize(new NumberFormatter(…))Exception: … 'NumberFormatter' …O:15:"NumberFormatter":0:{}serialize(new Collator(…))Exception: … 'Collator' …O:8:"Collator":0:{}serialize(new MessageFormatter(…))Exception: … 'MessageFormatter' …O:16:"MessageFormatter":0:{}serialize(ResourceBundle::create(…))Exception: … 'ResourceBundle' …O:14:"ResourceBundle":0:{}serialize(IntlCalendar::createInstance())Exception: … 'IntlGregorianCalendar' …O:21:"IntlGregorianCalendar":0:{}Sibling of CurlHandle/SimpleXMLElement serialize bans (#23074, #23072). Separate from ResourceBundle create/fallback parity (#22902, #22854).
php-src reference
ext/intl/dateformat/dateformat.stub.php—@not-serializableonIntlDateFormatterext/intl/formatter/formatter.stub.php—NumberFormatterext/intl/collator/collator.stub.php—Collatorext/intl/msgformat/msgformat.stub.php—MessageFormatterext/intl/resourcebundle/resourcebundle.stub.php—ResourceBundleext/intl/calendar/calendar.stub.php—IntlCalendar/IntlGregorianCalendarPHP implementation target
ext/intl/(+ hook fromext/standard/VmSerialize.php) — throw Zend-identicalExceptionCurlFileSerializeDeny/SimpleXmlSerializeDeny; PHP-in-PHP; no newruntime/*.cIntlGregorianCalendarwhen that is the runtime class)Repro
Done when
serialize()on each listed Intl class throws Zend-identicalException(message includes the runtime class name)unserialize('O:…')for those class names also denied (Zend parity).phptundertest/compliance/cases/intl/(or language/serialize)