Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:104535 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 23024 invoked from network); 1 Mar 2019 14:39:00 -0000 Received: from unknown (HELO mail-it1-f180.google.com) (209.85.166.180) by pb1.pair.com with SMTP; 1 Mar 2019 14:39:00 -0000 Received: by mail-it1-f180.google.com with SMTP id z131so19581687itf.5 for ; Fri, 01 Mar 2019 03:26:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=Se47Gqc4L5HQPOjFwogFzMqcfhq+8KNcksibHameP90=; b=Emh1jLGRHqMBqLUz9n9xCtLyKCso7yJqlELfy2L9WltFlhpSPpuCjtVGxgcaN7Lwdg 8qbluO/o6O0g2Q/wZHb0I2O3fxfJez95LsGYdb7d0Yz52RvpXqt6ahbs80OPfZd4MRTD xLhmzb6vWFHX97zjgZqDoEp2nuYe0zJ098jCAwXXKZOZ5uezdn9SCNWALYTfVCpRA4O3 4XUTFSv+T8M8iSg7W30Ot70nwnxEjCfG2VENdZxwJ4hko73tDTB2voJZKBJPh794sAa0 BFxo286DwrwhNMpJvKSpCCrhmVe8gfOlH6ECXJSo4Z2LJKesf8x+fvIYFUpz30iROluG nEkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=Se47Gqc4L5HQPOjFwogFzMqcfhq+8KNcksibHameP90=; b=PDOLHpcKrJ3MsXtVx2nYhWB0f/RzKDu/QrUM+23U15CEZmRy1KFmSwYegoWkYBLYcE 4UH/EBKGCv1T09uifRAMN370+2PIMiRry+LMx2aUjDJZgfZLe4SHIp19UZsS7C8R+QSQ whYMLZl30DXUUfaAjDTTPBS6SUei5zUTptJ0KZz6Wr7tPwstO5p+dfFFSRlVfO4GXXO6 rWYRk8FgyyYm4eKhIbVbCqmFfcl8D5t2ByBX9ePQCXBHo2uUxapnSZ1WXlMIiNELBkRG aMahM447lSJ4f2kPgC98hQvjIQA9qMR1SW3QESbgqSKutkNgEQtLkRTPpuRowAbIrPYG PFkQ== X-Gm-Message-State: APjAAAXKMbhn13sFW935tQHf2Bkj3zEykWayA1eNbaliP9cy7bCTxYGa y3HV8utNxaKm4raoa6CGyIsTGOS5m4t9VxP66TlKyC7z X-Google-Smtp-Source: APXvYqyuiHR6ZNx20ZuJ1aViPMEwC3qyjZwfkT/C6kbwk9ZEY8xCd3/FOpVCBiCdrbiilBhpadZmVVoPOHy+pB6r+ZM= X-Received: by 2002:a24:c4c5:: with SMTP id v188mr1140673itf.27.1551439567186; Fri, 01 Mar 2019 03:26:07 -0800 (PST) MIME-Version: 1.0 Date: Fri, 1 Mar 2019 12:25:47 +0100 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="0000000000004af10d058306ac53" Subject: Allow throwing from __toString() From: nikita.ppv@gmail.com (Nikita Popov) --0000000000004af10d058306ac53 Content-Type: text/plain; charset="UTF-8" Hi internals, We currently forbid throwing exceptions from __toString() and instead convert them into fatal errors. The rationale for this behavior is that string conversions are performed in many places throughout the engine and standard library, and not all places performing these conversions will deal with exceptions correctly (in the sense of "as soon as possible"). While this limitation is ultimately futile, because exceptions during string conversion can still be triggered by error handlers that convert warnings to exceptions, the sentiment in past discussions on this topic has been to not relax this restriction until we have audited string conversions across the codebase for exception safety. I have now done this, with the patch available at https://github.com/php/php-src/pull/3887. The PR * allows exceptions to be thrown from __toString(). * converts the "could not be converted to string" and "__toString() must return a string value" recoverable fatal errors into proper Error exceptions. * audits uses of zval_get_string(), convert_to_string() and friends across the codebase and adds exception checks where necessary. For extension authors, the guideline is: * If zval_get_string() / convert_to_string() generate an exception, they will always produce an interned string. This means that the result does not need to be freed in case of an exception (but freeing it is also fine -- do whatever is more convenient). * The return value will be an empty string if an object to string conversion fails, and "Array" if an array is converted to string and the resulting notice is promoted to an exception by an error handler. (This behavior is as before.) * As usual, whether an exception has been thrown may be checked using if (EG(exception)). A typical example would be: zend_string *str = zval_get_string(val); if (EG(exception)) { return; // Possibly do some cleanup here. } * While checking every single string conversion certainly puts you on the safe side, leaving out these checks will usually only result in some unneeded computation and possibly redundant warnings. The main thing you should watch out for are operations modifying persistent structures such as databases. I would like to land this change in PHP 7.4. Are there any objections to that? I'm skipping an RFC for this, because the change here is pretty much a purely technical matter, but I can put up an RFC if it turns out to be controversial. Regards, Nikita PS: If I remember correctly https://wiki.php.net/rfc/array-to-string was accepted but never implemented due to the inability to throw from string conversions. We should probably revisit this for PHP 8.0. --0000000000004af10d058306ac53--