Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128663 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 83FD31A00BC for ; Tue, 9 Sep 2025 13:39:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1757425107; bh=TMtFZx+n+vdyqpOFhPxA4zfTaUD5YLyRl+ippRC5Sk0=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=V1ZZdgM2ysIofxhLNfLxGf7MGZIWkcpDFZIH6QV1fIqm28YjjBTuzgpbi8vXm5hZc I7MkmLnwJVnUDKr9oWdlQENUl+vQ5Fh0ZtSIAEJja8uil3Pq8BtIcsvvuXyxFZkZhD ikR+nNg1Kn6ppPKswcbW8zMSf+k6C3OOo7zQRpUWgUSf7mkoz9nAshrEIw+NmOcrHA W5YfdfwcexTGOfmU4bxPN9rTiNCDg4ZK/CPap8gyU5e5leztIlb+BTQrP1MjelX9Ut hK1E+euJiYaeJYhLC1gqbFyIsDYikKJ22bYzrK6nLCyfft+H6wZwAlnWYEz9eiFduO 0PoVICt2C930A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 00E2B180083 for ; Tue, 9 Sep 2025 13:38:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 9 Sep 2025 13:38:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1757425191; bh=IfCZIrG5sISd6sM53bVdTe8uZUm2mMG6NDB1enCtQRE=; h=MIME-Version:Date:From:To:Cc:Subject:In-Reply-To:References: Message-ID:Content-Type:from:to:cc:subject:message-id; b=AlRWQsqLn/jbTzt71PPLMrDtlxenzr8GGVr+zysECeXAFfmfUC/M50zgKM25QbdV7 3h00KM753U/8yCJ2LFLUQtzxhuDfL1+OybH8IKBG6jbWL16ZhvVDctgHHLaYtfhw4c Tak2H+oh5PQghhIlm0+np7YJspdYWlL3mTtuAlkLCmj6NqDhG3OqcpN5OwDCFdOBXI 613FUGrmBk7Ood9h4X+TRGC/hRqorsmHW7YfZN+2ktaOjXMXpJoVkD6F4rL9zWT2WN D9M2KyYalrzZCrgXVaSnLqMYBVmuKwOtCKKHzVolBPKc6vXFQpFvOEEF8TTourXuyt UCMKFmVIjUG8Q== Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 Date: Tue, 09 Sep 2025 15:39:51 +0200 To: Jakub Zelenka Cc: Nicolas Grekas , PHP Internals List Subject: Re: [PHP-DEV] [RFC] Soft-Deprecate __sleep() and __wakeup() In-Reply-To: References: Message-ID: <7b1b5b71cd32bad2646164c624dc6c7f@bastelstu.be> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi Am 2025-09-08 23:14, schrieb Jakub Zelenka: > I understand your concern about the complexity but this can apply to > many > other parts in php-src. As I'm sure you know, this still wouldn't > likely to > be considered as a security issue. I've intentionally said “security sensitive”. I believe the risk of security issues for the unserializer is significantly higher than in other parts of the language and I also believe that by keeping complexity down it is both easier to verify correctness and also to fix any bugs that crop up. From what I see __wakeup() and __unserialize() work quite differently internally. When there's __unserialize(), the deserialization process only creates an empty object shell (similarly to newInstanceWithoutConstructor) and then calls __unserialize() at the very end. For __wakeup() all the properties are filled directly and then __wakeup() is called at the end. In both cases the destructor is skipped for all following objects once one of the deserialization hooks fails. For __wakeup() this has the interesting effect that in case of circular structures, some objects may appear to already be properly initialized (all the properties are there), but __wakeup() has not executed yet, potentially making them unsafe to touch. In case of __unserialize() the objects are clearly in a partially initialized state (e.g. properties being uninit), which I'd claim is safer: a = $data['a']; $this->name = $data['name']; echo "Waking up ", $this->name, PHP_EOL; var_dump($this->a->name); } public function __wakeup(): void { echo "Waking up ", $this->name, PHP_EOL; var_dump($this->a->name); } public function __destruct() { echo __METHOD__, PHP_EOL; } } $a = new A('A'); $a->a = new A('B'); $a->a->a = new A('C'); $a->a->a->a = $a; echo "Before", PHP_EOL; var_dump(unserialize(serialize($a))); echo "After", PHP_EOL; In case of `__unserialize()` the unsafe access to `$this->a->name` will throw, whereas in `__wakeup()` it will return `A`, despite `A` not being fully available yet. Similarly skipping the destructor for an empty object shell is safer than skipping the destructor for an object that may appear usable. >> Saying that “unserialize is not security-relevant because you must >> only >> feed it safe inputs” as an excuse to avoid making unserialize safer is >> not helping anyone and is downplaying the risks involved in >> unserialization. >> >> > I don't have problem with making unserialize safer as there might be > users > that use it improperly. But we shouldn't be saying that this is a > security > sensitive part when we don't consider those sort of issues as security > issues because none of those issues will get fixed in our security > support > only releases. In that sense I don't think we can consider it as a > security > sensitive part. The unserializer already contains quite a bit of logic to make it as safe as possible, e.g. running the unserialization hooks only at the very end and skipping destructors for objects where the unserialization hook didn't successfully run. The forefathers definitely considered possible edge cases that might lead to security issues. Best regards Tim Düsterhus