Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:75924 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 78492 invoked from network); 23 Jul 2014 08:16:53 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 23 Jul 2014 08:16:53 -0000 Authentication-Results: pb1.pair.com smtp.mail=bobwei9@hotmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=bobwei9@hotmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain hotmail.com designates 65.55.111.109 as permitted sender) X-PHP-List-Original-Sender: bobwei9@hotmail.com X-Host-Fingerprint: 65.55.111.109 blu004-omc2s34.hotmail.com Received: from [65.55.111.109] ([65.55.111.109:62678] helo=BLU004-OMC2S34.hotmail.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id C0/DF-21666-47F6FC35 for ; Wed, 23 Jul 2014 04:16:53 -0400 Received: from BLU436-SMTP143 ([65.55.111.71]) by BLU004-OMC2S34.hotmail.com with Microsoft SMTPSVC(7.5.7601.22712); Wed, 23 Jul 2014 01:16:51 -0700 X-TMN: [Jw53zQwAZqcGUZEhWaM8u87qGgFBzQCK] X-Originating-Email: [bobwei9@hotmail.com] Message-ID: Received: from bobweinandsimac.fritz.box ([78.141.132.157]) by BLU436-SMTP143.smtp.hotmail.com over TLS secured channel with Microsoft SMTPSVC(8.0.9200.16384); Wed, 23 Jul 2014 01:16:49 -0700 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 (Mac OS X Mail 7.3 \(1878.2\)) In-Reply-To: Date: Wed, 23 Jul 2014 10:16:45 +0200 CC: Nikita Popov , Stas Malyshev , Julien Pauli , PHP Internals Content-Transfer-Encoding: quoted-printable References: To: Dmitry Stogov X-Mailer: Apple Mail (2.1878.2) X-OriginalArrivalTime: 23 Jul 2014 08:16:49.0515 (UTC) FILETIME=[73A903B0:01CFA64E] Subject: Re: [PHP-DEV] Weird constant expression syntax and bug From: bobwei9@hotmail.com (Bob Weinand) Hey, thank you for looking into it :-) Am 23.7.2014 um 00:23 schrieb Dmitry Stogov : > hi Bob, >=20 > I still think that current array usage in constant expressions is not > consistent and dangerous. It "smells" to me, and I think it may bring > troubles in the future even if the existing known bugs are fixed. >=20 > I see few issues: >=20 > 1) It is possible to declare array class constants however they can't = be > used. I can't remember why array in constants were prohibited before = and > what problems they brought. The following script works without any = warnings. >=20 > class Foo { > const BAR =3D [1]; > } > ?> Because it's actually valid. You don't use it in non-static scalar = context. > 2) In some cases array constants may be used, but not in the others. >=20 > class Foo { > const BAR =3D [0]; > static $a =3D Foo::BAR; // constant array usage > } > var_dump(Foo::$a); // prints array > var_dump(Foo::BAR); // emits fatal error > ?> They can only be used in static scalar contexts. I wanted to introduce constants to be used and dereferenced also at = run-time, but that requires a RFC. If anyone would allow me to introduce that still now (it'd be a = relatively simple patch), I'll happily do it. The issue just was that I was a bit late to create a RFC (beta freeze = etc...) > 3) The fact that constants are allowed in compile time and even = stored, but > can't be used confuses me as well as the error message "PHP Fatal = error: > Arrays are not allowed in constants at run-time". See above... > 4) Zend/tests/constant_expressions_arrays.phpt crashes whit > opcache.protect_memory=3D1 (that indicates petential SHM memory = corruption) >=20 > This may be fixed with the following patch: >=20 > diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h > index 144930e..f1aab9a 100644 > --- a/Zend/zend_vm_execute.h > +++ b/Zend/zend_vm_execute.h > @@ -4323,6 +4323,16 @@ static int ZEND_FASTCALL > ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD > c.value =3D *tmp_ptr; > } else { > INIT_PZVAL_COPY(&c.value, val); > + if (Z_TYPE(c.value) =3D=3D IS_ARRAY) { > + HashTable *ht; > + > + ALLOC_HASHTABLE(ht); > + zend_hash_init(ht, > zend_hash_num_elements(Z_ARRVAL(c.value)), NULL, ZVAL_PTR_DTOR, 0); > + zend_hash_copy(ht, Z_ARRVAL(c.value), > (copy_ctor_func_t) zval_deep_copy, NULL, sizeof(zval *)); > + Z_ARRVAL(c.value) =3D ht; > + } else { > + zval_copy_ctor(&c.value); > + } > zval_copy_ctor(&c.value); > } > c.flags =3D CONST_CS; /* non persistent, case sensetive */ I assume you wanted to patch zend_vm_def.h, not zend_vm_execute.h. If you can fix it, please apply the patch, I'm not so deep into opcache = to take responsibility for that one. > 5) Circular constant references crash (found by Nikita) >=20 > class A { > const FOO =3D [self::BAR]; > const BAR =3D [self::FOO]; > } > var_dump(A::FOO); // crashes because of infinity recursion > ?> That isn't a specific problems with arrays: I didn't find any useful way to fix it. One of the ideas with = following > hack seemed to work, but it breaks another test > (Zend/tests/constant_expressions_classes.phpt) >=20 > diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c > index 12f9405..8798737 100644 > --- a/Zend/zend_ast.c > +++ b/Zend/zend_ast.c > @@ -251,10 +251,22 @@ ZEND_API void zend_ast_evaluate(zval *result, > zend_ast *ast, zend_class_entry *s > zval_dtor(&op2); > break; > case ZEND_CONST: > - *result =3D *ast->u.val; > - zval_copy_ctor(result); > - if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) { > - zval_update_constant_ex(&result, 1, = scope > TSRMLS_CC); > + if (EG(in_execution) && EG(opline_ptr) && > *EG(opline_ptr) && > + ((*EG(opline_ptr))->opcode =3D=3D = ZEND_RECV_INIT || > + (*EG(opline_ptr))->opcode =3D=3D > ZEND_DECLARE_CONST)) { > + *result =3D *ast->u.val; > + zval_copy_ctor(result); > + if = (IS_CONSTANT_TYPE(Z_TYPE_P(result))) { > + = zval_update_constant_ex(&result, 1, > scope TSRMLS_CC); > + } > + } else { > + if = (IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val))) > { > + > zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC); > + *result =3D *ast->u.val; > + } else { > + *result =3D *ast->u.val; > + zval_copy_ctor(result); > + } > } > break; > case ZEND_BOOL_AND: >=20 > I spent few hours trying to find a solution, but failed. May be my = ideas > could lead you to something... >=20 > Otherwise, I would recommend to remove this feature from PHP-5.6. >=20 > Thanks. Dmitry. So, as we see, it's not especially because of arrays, but everytime the = two self-referencing constants are inside an expression of each other, = it'll fail. I'm just wondering if we can't somehow deeply copy the asts for opcache = between compile time and run time in pass_two() (If I'm not wrong = pass_two() has some hook for zend extensions?) Then we can fix the ast and don't have to take care of opcache at run = time (=3D when the (dynamic) asts will be evaluated). It'd maybe even be = a bit faster as it then doesn't have to copy so much at run-time. Bob > On Tue, Jul 22, 2014 at 10:00 AM, Dmitry Stogov = wrote: >=20 >> Hi Bob, >>=20 >> Now I think it's not fixable by design :( >>=20 >> I'll try to think about it later today. >> Could you please collect all related issues. >>=20 >> Thanks. Dmitry. >>=20 >>=20 >> On Mon, Jul 21, 2014 at 8:36 PM, Bob Weinand = wrote: >>=20 >>> Am 2.7.2014 um 15:43 schrieb Dmitry Stogov : >>>=20 >>> I don't have good ideas out of the box and I probably won't be able = to >>> look into this before next week. >>>=20 >>>=20 >>> Hey, I still have no real idea how to solve it without breaking = opcache. >>>=20 >>> This one seems to be considered like a blocking bug for 5.6. >>>=20 >>> Could you please try to fix this in a sane manner? >>>=20 >>> Bob