]> granicus.if.org Git - php/commitdiff
MF5 __HALT_COMPILER fix:
authorStanislav Malyshev <stas@php.net>
Thu, 28 Jun 2007 00:01:58 +0000 (00:01 +0000)
committerStanislav Malyshev <stas@php.net>
Thu, 28 Jun 2007 00:01:58 +0000 (00:01 +0000)
Remove limitation of __HALT_COMPILER() that allowed only one instance
per request.

# Patch by Gregory Beaver

Zend/tests/halt_compiler1.phpt [new file with mode: 0644]
Zend/tests/halt_compiler2.phpt [new file with mode: 0644]
Zend/tests/halt_compiler3.phpt [new file with mode: 0644]
Zend/tests/halt_compiler4.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_constants.c
Zend/zend_language_parser.y

diff --git a/Zend/tests/halt_compiler1.phpt b/Zend/tests/halt_compiler1.phpt
new file mode 100644 (file)
index 0000000..4987b29
--- /dev/null
@@ -0,0 +1,8 @@
+--TEST--
+__HALT_COMPILER();
+--FILE--
+<?php echo 'test'; var_dump(__COMPILER_HALT_OFFSET__); __HALT_COMPILER();
+?>
+===DONE===
+--EXPECT--
+testint(73)
\ No newline at end of file
diff --git a/Zend/tests/halt_compiler2.phpt b/Zend/tests/halt_compiler2.phpt
new file mode 100644 (file)
index 0000000..0ced214
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+__HALT_COMPILER(); 2 files
+--FILE--
+<?php
+$text = "<?php echo 'test'; var_dump(__COMPILER_HALT_OFFSET__); __HALT_COMPILER(); ?>
+hi there";
+file_put_contents(dirname(__FILE__) . '/test1.php', $text);
+$text = "<?php echo 'test2'; var_dump(__COMPILER_HALT_OFFSET__); __HALT_COMPILER(); ?>
+hi there 2";
+file_put_contents(dirname(__FILE__) . '/test2.php', $text);
+include dirname(__FILE__) . '/test1.php';
+include dirname(__FILE__) . '/test2.php';
+?>
+==DONE==
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/test1.php');
+unlink(dirname(__FILE__) . '/test2.php');
+?>
+--EXPECT--
+testint(73)
+test2int(74)
+==DONE==
\ No newline at end of file
diff --git a/Zend/tests/halt_compiler3.phpt b/Zend/tests/halt_compiler3.phpt
new file mode 100644 (file)
index 0000000..6ee16f7
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+__HALT_COMPILER(); bad define() of __COMPILER_HALT_OFFSET__ 1
+--FILE--
+<?php
+define ('__COMPILER_HALT_OFFSET__', 1);
+?>
+==DONE==
+--EXPECTF--
+Notice: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d
+==DONE==
\ No newline at end of file
diff --git a/Zend/tests/halt_compiler4.phpt b/Zend/tests/halt_compiler4.phpt
new file mode 100644 (file)
index 0000000..43e532c
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+__HALT_COMPILER(); bad define() of __COMPILER_HALT_OFFSET__ 2
+--FILE--
+<?php
+define ('__COMPILER_HALT_OFFSET__', 1);
+__HALT_COMPILER();
+?>
+==DONE==
+--EXPECTF--
+Notice: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d
\ No newline at end of file
index 1740564b96c786d6879430da1b14e83dc309f3a8..0173f51f872b5a41a25723c80d4fdecaab727369 100644 (file)
@@ -3338,6 +3338,18 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
        zend_llist_add_element(fetch_list_ptr, &opline);
 }
 
+void zend_do_halt_compiler_register(TSRMLS_D)
+{
+       char *name, *cfilename;
+       char haltoff[] = "__COMPILER_HALT_OFFSET__";
+       int len, clen;
+       cfilename = zend_get_compiled_filename(TSRMLS_C);
+       clen = strlen(cfilename);
+       zend_mangle_property_name(&name, &len, haltoff,
+               sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+       zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
+       pefree(name, 0);
+}
 
 
 void zend_do_declare_implicit_property(TSRMLS_D)
index d5dc4aa615fd2870226909a0809b27a235e862dc..dbf0dd996e005aae31d8e4d4e3b1381cf9e72bf0 100644 (file)
@@ -456,6 +456,7 @@ void zend_do_default_before_statement(znode *case_list, znode *default_token TSR
 void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC);
 void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRMLS_DC);
 void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC);
+void zend_do_halt_compiler_register(TSRMLS_D);
 void zend_do_declare_implicit_property(TSRMLS_D);
 void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC);
 
index 1a2ffc2e2589365cd6d6f982b8d0331a36aa5416..096e174ac3f2aa2e71217226e3132d3127dfdee5 100644 (file)
@@ -348,7 +348,27 @@ ZEND_API int zend_u_get_constant(zend_uchar type, zstr name, uint name_len, zval
                                retval=0;
                        }
                } else {
-                       retval=0;
+                       char haltoff[] = "__COMPILER_HALT_OFFSET__";
+                       if (!EG(in_execution)) {
+                               retval = 0;
+                       } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name.s, name_len) == 0) {
+                               char *cfilename;
+                               zstr haltname;
+                               int len, clen;
+                               cfilename = zend_get_executed_filename(TSRMLS_C);
+                               clen = strlen(cfilename);
+                               /* check for __COMPILER_HALT_OFFSET__ */
+                               zend_mangle_property_name(&haltname.s, &len, haltoff,
+                                       sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+                               if (zend_u_hash_find(EG(zend_constants), IS_STRING, haltname, len+1, (void **) &c) == SUCCESS) {
+                                       retval=1;
+                               } else {
+                                       retval=0;
+                               }
+                               pefree(haltname.s, 0);
+                       } else {
+                               retval=0;
+                       }
                }
                efree(lookup_name.v);
        }
@@ -374,6 +394,7 @@ ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_D
        zstr lookup_name;
        zstr name;
        int ret = SUCCESS;
+       static char haltoff[] = "__COMPILER_HALT_OFFSET__";
 
 #if 0
        printf("Registering constant for module %d\n", c->module_number);
@@ -389,6 +410,13 @@ ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_D
                lookup_name = NULL_ZSTR;
        }
 
+       if (EG(in_execution) && lookup_name_len == sizeof("__COMPILER_HALT_OFFSET__") && memcmp(haltoff, name.s, lookup_name_len) == 0) {
+               zend_error(E_NOTICE,"Constant %R already defined", type, name);
+               if (lookup_name.v) {
+                       efree(lookup_name.v);
+               }
+               ret = FAILURE;
+       }
        if (zend_u_hash_add(EG(zend_constants), type, name, lookup_name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
                zend_error(E_NOTICE,"Constant %R already defined", type, name);
                free(c->name.v);
index 49d5fd132eeb7001ca0f55e942ba60dd82a03167..6846384078dfd76d16b066ba807f07d2121d5677 100644 (file)
@@ -163,7 +163,7 @@ top_statement:
                statement
        |       function_declaration_statement  { zend_do_early_binding(TSRMLS_C); }
        |       class_declaration_statement             { zend_do_early_binding(TSRMLS_C); }
-       |       T_HALT_COMPILER '(' ')' ';'   { zval c; if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &c TSRMLS_CC)) { zval_dtor(&c); zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used once per request"); } else { REGISTER_MAIN_LONG_CONSTANT("__COMPILER_HALT_OFFSET__", zend_get_scanned_file_offset(TSRMLS_C), CONST_CS); } YYACCEPT; }
+       |       T_HALT_COMPILER '(' ')' ';'   { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
 ;