root/eaccelerator/branches/0.9.4/loader.c

Revision 215, 31.8 kB (checked in by bart, 2 years ago)

* Branched the 0.9.4 release to fix win32
* Fixes from Simon Westwood

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | eAccelerator project                                                 |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2004 - 2005 eAccelerator                               |
6    | http://eaccelerator.net                                                      |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author(s): Dmitry Stogov <dstogov@users.sourceforge.net>             |
26    +----------------------------------------------------------------------+
27    $Id$
28 */
29
30 #include "eaccelerator.h"
31 #include "eaccelerator_version.h"
32
33 #ifdef HAVE_EACCELERATOR
34 #ifdef WITH_EACCELERATOR_LOADER
35
36 #include "opcodes.h"
37 #include "zend.h"
38 #include "zend_API.h"
39 #include "php.h"
40 #include "ea_restore.h"
41 #include <math.h>
42
43
44
45
46 #ifdef HAVE_EACCELERATOR_STANDALONE_LOADER
47 zend_extension* ZendOptimizer = NULL;
48 #endif
49
50
51 typedef struct loader_data {
52   long  version;
53   char* filename;
54   uint  lineno;
55 } loader_data;
56
57 static inline unsigned char decode(char** p, unsigned int* l) {
58   unsigned char c;
59   if (*l == 0) {
60     zend_bailout();
61   }
62   c = **p;
63   (*p)++;
64   (*l)--;
65   return c;
66 }
67
68 static inline unsigned int decode32(char** p, unsigned int* l) {
69   unsigned int i = decode(p, l);
70   i += ((unsigned int)decode(p, l)) << 8;
71   i += ((unsigned int)decode(p, l)) << 16;
72   i += ((unsigned int)decode(p, l)) << 24;
73   return i;
74 }
75
76 static inline unsigned short decode16(char** p, unsigned int* l) {
77   unsigned short i = decode(p, l);
78   i += ((unsigned short)decode(p, l)) << 8;
79   return i;
80 }
81
82 static unsigned int decode_var(unsigned int count, char** p, unsigned int* l) {
83   unsigned int var;
84   if (count < 0xff) {
85     var = decode(p, l);
86   } else if (count < 0xffff) {
87     var = decode16(p, l);
88   } else {
89     var = decode32(p, l);
90   }
91   if (var >= count) {
92     zend_bailout();
93   }
94 #ifdef ZEND_ENGINE_2
95   return (unsigned int)(((temp_variable*)NULL) + var);
96 #else
97   return var;
98 #endif
99 }
100
101 static unsigned int decode_opline(unsigned int last, char** p, unsigned int* l) {
102   unsigned int opline;
103   if (last < 0xff-1) {
104     opline = decode(p, l);
105     if (opline == 0xff) return (unsigned int)-1;
106   } else if (last < 0xffff-1) {
107     opline = decode16(p, l);
108     if (opline == 0xffff) return (unsigned int)-1;
109   } else {
110     opline = decode32(p, l);
111   }
112   if (opline >= last) {
113     zend_bailout();
114   }
115   return opline;
116 }
117
118 static char* decode_zstr(char** p, unsigned int* l) {
119   char *s = *p;
120   unsigned int len = 0;
121   while (s[len] != '\0') {
122     len++;
123     if (len > (*l)) {
124       zend_bailout();
125     }
126   }
127   if (len == 0) {
128     (*p)++;
129     (*l)--;
130     return NULL;
131   } else {
132     char *str = emalloc(len+1);
133     memcpy(str, *p, len+1);
134     *p += len+1;
135     *l -= len+1;
136     return str;
137   }
138 }
139
140 static char* decode_zstr_noalloc(char** p, unsigned int* l) {
141   char *s = *p;
142   unsigned int len = 0;
143   while (s[len] != '\0') {
144     len++;
145     if (len > (*l)) {
146       zend_bailout();
147     }
148   }
149   if (len == 0) {
150     (*p)++;
151     (*l)--;
152     return NULL;
153   } else {
154     *p += len+1;
155     *l -= len+1;
156     return s;
157   }
158 }
159
160 #if EA_ENCODER_VERSION < 2
161 static char* decode_filename(char** p, unsigned int* l TSRMLS_DC) {
162   char *s = *p;
163   unsigned int len = 0;
164   while (s[len] != '\0') {
165     len++;
166     if (len > (*l)) {
167       zend_bailout();
168     }
169   }
170   if (len == 0) {
171     (*p)++;
172     (*l)--;
173     return NULL;
174   } else {
175     if (((loader_data*)EAG(mem))->filename == NULL ||
176         strcmp(((loader_data*)EAG(mem))->filename,*p) != 0) {
177       char* old = CG(compiled_filename);
178       ((loader_data*)EAG(mem))->filename = zend_set_compiled_filename(*p TSRMLS_CC);
179       CG(compiled_filename) = old;
180     }
181     *p += len+1;
182     *l -= len+1;
183     return ((loader_data*)EAG(mem))->filename;
184   }
185 }
186 #endif
187
188 static char* decode_lstr(unsigned int* len, char** p, unsigned int* l) {
189   *len = decode32(p, l);
190   if (*len == 0) {
191     return NULL;
192   } else {
193     char* str;
194     if (*len > *l) {
195       zend_bailout();
196     }
197     str = emalloc((*len)+1);
198     memcpy(str, *p, *len);
199     str[(*len)] = '\0';
200     *p += *len;
201     *l -= *len;
202     return str;
203   }
204 }
205
206 static char* decode_lstr_noalloc(unsigned int* len, char** p, unsigned int* l) {
207   *len = decode32(p, l);
208   if (*len == 0) {
209     return NULL;
210   } else {
211     char* str = *p;
212     if (*len > *l) {
213       zend_bailout();
214     }
215     *p += *len;
216     *l -= *len;
217     return str;
218   }
219 }
220
221 static unsigned char* decode_pstr(char** p, unsigned int* l) {
222   unsigned char c = decode(p, l);
223   if (c == 0) {
224     return NULL;
225   } else {
226     unsigned char *str;
227     if (c > *l) {
228       zend_bailout();
229     }
230     str = emalloc(c+1);
231     str[0] = c;
232     memcpy(&str[1], *p, c);
233     *p += c;
234     *l -= c;
235     return str;
236   }
237 }
238
239 static double decode_double(char** p, unsigned int* l) {
240   unsigned char sign;
241   int exp;
242   unsigned int i1, i2;
243   double d;
244
245   sign = decode(p, l);
246   exp = decode32(p, l);
247   i1 = decode32(p, l);
248   i2 = decode32(p, l);
249   d = ldexp((((double)i2 / 4294967296.0) + (double)i1) / 4294967296.0, exp);
250   if (sign) {
251     d = -d;
252   }
253   return d;
254 }
255
256 typedef void* (*decode_bucket_t)(void* to, char**, unsigned int* TSRMLS_DC);
257
258 #define decode_zval_hash(to, p, l) decode_hash(to, sizeof(zval*), (decode_bucket_t)decode_zval_ptr, p, l TSRMLS_CC)
259 #define decode_zval_hash_noref(to, p, l) decode_hash(to, sizeof(zval*), (decode_bucket_t)decode_zval_ptr_noref, p, l TSRMLS_CC)
260
261 static HashTable* decode_hash(HashTable* to, int size, decode_bucket_t decode_bucket, char**p, unsigned int* l TSRMLS_DC);
262 static zval* decode_zval_ptr(zval* to, char** p, unsigned int* l TSRMLS_DC);
263
264 static zval* decode_zval(zval* to, int refs, char** p, unsigned int* l TSRMLS_DC) {
265   to->type     = decode(p ,l);
266   if (refs) {
267     to->is_ref = decode(p, l);
268     to->refcount = decode32(p, l);
269   } else {
270     to->is_ref   = 1;
271     to->refcount = 2;
272   }
273   switch (to->type & ~IS_CONSTANT_INDEX) {
274     case IS_NULL:
275       break;
276     case IS_BOOL:
277       to->value.lval = decode(p, l);
278       break;
279     case IS_LONG:
280       {
281   int x = decode32(p,l);
282         to->value.lval = x;
283       }
284       break;
285     case IS_DOUBLE:
286       to->value.dval = decode_double(p, l);
287       break;
288     case IS_CONSTANT:
289     case IS_STRING:
290 /*???    case FLAG_IS_BC:*/
291       to->value.str.val = decode_lstr((unsigned int*)&to->value.str.len, p, l);
292       if (to->value.str.val == NULL) {
293         to->value.str.val = empty_string;
294       }
295       break;
296     case IS_ARRAY:
297     case IS_CONSTANT_ARRAY:
298       to->value.ht = decode_zval_hash(NULL, p ,l);
299       if (to->value.ht) {
300         to->value.ht->pDestructor = ZVAL_PTR_DTOR;
301       } else {
302         ALLOC_HASHTABLE(to->value.ht);
303         zend_hash_init(to->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
304       }
305       break;
306     case IS_OBJECT:
307     case IS_RESOURCE:
308       /*???*/
309     default:
310       zend_bailout();
311       break;
312   }
313   return to;
314 }
315
316 static zval* decode_zval_ptr(zval* to, char** p, unsigned int* l TSRMLS_DC) {
317   if (to == NULL) {
318     ALLOC_ZVAL(to);
319   }
320   decode_zval(to, 1, p, l TSRMLS_CC);
321   return to;
322 }
323
324 static zval* decode_zval_ptr_noref(zval* to, char** p, unsigned int* l TSRMLS_DC) {
325   if (to == NULL) {
326     ALLOC_ZVAL(to);
327   }
328   decode_zval(to, 1, p, l TSRMLS_CC);
329   to->is_ref   = 0;
330   to->refcount = 1;
331   return to;
332 }
333
334 static void decode_znode(znode* to, unsigned int vars_count, char** p, unsigned int* l TSRMLS_DC) {
335   to->op_type = decode(p, l);
336   if (to->op_type == IS_CONST) {
337     decode_zval(&to->u.constant, 0, p, l TSRMLS_CC);
338     to->u.constant.is_ref = 1;
339     to->u.constant.refcount = 2;
340   } else if (to->op_type == IS_VAR ||
341              to->op_type == IS_TMP_VAR) {
342     to->u.var = decode_var(vars_count, p, l);
343   } else if (to->op_type != IS_UNUSED) {
344     zend_bailout();
345   }
346 }
347
348 static HashTable* decode_hash(HashTable* to, int size, decode_bucket_t decode_bucket, char** p, unsigned int* l TSRMLS_DC) {
349   unsigned int n;
350   void *data = NULL;
351
352   if (size != sizeof(void*)) {
353     data = do_alloca(size);
354   }
355   n = decode32(p, l);
356   if (to == NULL) {
357     if (n == 0 ) return NULL;
358     ALLOC_HASHTABLE(to);
359     zend_hash_init(to, 0, NULL, NULL, 0);
360   }
361   while (n > 0) {
362     void* x;
363     char* s;
364     unsigned int len;
365
366     s = decode_lstr_noalloc(&len, p, l);
367     if (s == NULL) {
368       len = decode32(p, l);
369     }
370     if (size == sizeof(void*)) {
371       x = decode_bucket(NULL, p, l TSRMLS_CC);
372       if (s != NULL) {
373         zend_hash_add(to, s, len, &x, size, NULL);
374       } else {
375         zend_hash_index_update(to, len, &x, size, NULL);
376       }
377     } else {
378       decode_bucket(data, p, l TSRMLS_CC);
379       if (s != NULL) {
380         zend_hash_add(to, s, len, data, size, NULL);
381       } else {
382         zend_hash_index_update(to, len, data, size, NULL);
383       }
384     }
385     --n;
386   }
387   if (size != sizeof(void*)) {
388     free_alloca(data);
389   }
390   return to;
391 }
392
393 static void call_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) {
394   if (extension->op_array_ctor) {
395     extension->op_array_ctor(op_array);
396   }
397 }
398
399 static void decode_op(zend_op_array *to, zend_op *opline, unsigned int ops,
400         char **p, unsigned int* l TSRMLS_DC) {
401 #ifdef ZEND_ENGINE_2
402 #ifdef HAVE_EACCELERATOR_STANDALONE_LOADER
403     opline->handler = zend_opcode_handlers[opline->opcode];
404 #else
405     opline->handler = get_opcode_handler(opline->opcode TSRMLS_CC);
406 #endif
407 #endif
408     opline->lineno = decode32(p, l);
409     ((loader_data*)EAG(mem))->lineno = opline->lineno;
410     opline->extended_value = 0;
411     opline->result.op_type = IS_UNUSED;
412     opline->op1.op_type    = IS_UNUSED;
413     opline->op2.op_type    = IS_UNUSED;
414
415     switch (ops & EXT_MASK) {
416         case EXT_UNUSED:
417             break;
418         case EXT_STD:
419         case EXT_FCALL:
420         case EXT_ARG:
421         case EXT_IFACE:
422             opline->extended_value = decode32(p, l);
423             break;
424         case EXT_SEND:
425         case EXT_SEND_NOREF:
426         case EXT_INIT_FCALL:
427         case EXT_FETCH:
428         case EXT_CAST:
429         case EXT_DECLARE:
430         case EXT_FCLASS:
431         case EXT_BIT:
432         case EXT_ISSET:
433         case EXT_ASSIGN:
434             opline->extended_value = decode(p, l);
435             break;
436         case EXT_FE:
437             opline->extended_value = decode(p, l);
438             break;
439         case EXT_OPLINE:
440             opline->extended_value = decode_opline(to->last, p, l);
441             break;
442         case EXT_CLASS:
443             opline->extended_value = decode_var(to->T, p, l);
444             break;
445         default:
446             zend_bailout();
447             break;
448     }
449
450     switch (ops & RES_MASK) {
451         case RES_UNUSED:
452             break;
453         case RES_TMP:
454             opline->result.op_type = IS_TMP_VAR;
455             opline->result.u.var = decode_var(to->T, p, l);
456             break;
457         case RES_CLASS:
458             opline->result.u.var = decode_var(to->T, p, l);
459             opline->result.op_type = IS_CONST;
460             break;
461         case RES_VAR:
462             opline->result.op_type = IS_VAR;
463             opline->result.u.var = decode_var(to->T, p, l);
464             opline->result.u.EA.type = 0;
465             if (decode(p, l)) {
466                 opline->result.u.EA.type |= EXT_TYPE_UNUSED;
467             }
468             break;
469         case RES_STD:
470             decode_znode(&opline->result, to->T, p, l TSRMLS_CC);
471             if (opline->result.op_type == IS_VAR) {
472                 opline->result.u.EA.type = 0;
473                 if (decode(p, l)) {
474                     opline->result.u.EA.type |= EXT_TYPE_UNUSED;
475                 }
476             }
477             break;
478         default:
479             zend_bailout();
480             break;
481     }
482     switch (ops & OP1_MASK) {
483         case OP1_UNUSED:
484             break;
485         case OP1_OPLINE:
486             opline->op1.u.opline_num = decode_opline(to->last, p, l);
487             break;
488         case OP1_BRK:
489         case OP1_CONT:
490             opline->op1.u.opline_num = decode_opline(to->last_brk_cont, p, l);
491             break;
492         case OP1_CLASS:
493             opline->op1.u.var = decode_var(to->T, p, l);
494             break;
495         case OP1_UCLASS:
496             opline->op1.op_type = decode(p, l);
497             if (opline->op1.op_type != IS_UNUSED) {
498                 opline->op1.u.var = decode_var(to->T, p, l);
499             }
500             break;
501         case OP1_TMP:
502             opline->op1.op_type = IS_TMP_VAR;
503             opline->op1.u.var = decode_var(to->T, p, l);
504             break;
505         case OP1_VAR:
506             opline->op1.op_type = IS_VAR;
507             opline->op1.u.var = decode_var(to->T, p, l);
508             break;
509         case OP1_ARG:
510             opline->op1.op_type = IS_CONST;
511             opline->op1.u.constant.type = IS_LONG;
512             opline->op1.u.constant.value.lval = decode32(p, l);
513             break;
514 #ifdef ZEND_ENGINE_2
515         case OP1_JMPADDR:
516             opline->op1.u.jmp_addr = to->opcodes + decode_opline(to->last, p, l);
517             break;
518 #endif
519         case OP1_STD:
520             decode_znode(&opline->op1, to->T, p, l TSRMLS_CC);
521             break;
522         default:
523             zend_bailout();
524             break;
525     }
526     switch (ops & OP2_MASK) {
527         case OP2_UNUSED:
528             break;
529         case OP2_OPLINE:
530             opline->op2.u.opline_num = decode_opline(to->last, p, l);
531             break;
532         case OP2_ARG:
533             opline->op2.u.opline_num = decode32(p, l);
534             break;
535         case OP2_ISSET:
536         case OP2_INCLUDE:
537             opline->op2.op_type = IS_CONST;
538             opline->op2.u.constant.type = IS_LONG;
539             opline->op2.u.constant.value.lval = decode(p, l);
540             break;
541         case OP2_FETCH:
542 #ifdef ZEND_ENGINE_2
543             opline->op2.u.EA.type = decode(p, l);
544             if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
545                 opline->op2.u.var = decode_var(to->T, p, l);
546             }
547 #else
548             opline->op2.u.fetch_type = decode(p, l);
549 #endif
550             break;
551         case OP2_CLASS:
552             opline->op2.u.var = decode_var(to->T, p, l);
553             break;
554         case OP2_TMP:
555             opline->op2.op_type = IS_TMP_VAR;
556             opline->op2.u.var = decode_var(to->T, p, l);
557             break;
558         case OP2_VAR:
559             opline->op2.op_type = IS_VAR;
560             opline->op2.u.var = decode_var(to->T, p, l);
561             break;
562 #ifdef ZEND_ENGINE_2
563         case OP2_JMPADDR:
564             opline->op2.u.jmp_addr = to->opcodes + decode_opline(to->last, p, l);
565             break;
566 #endif
567         case OP2_STD:
568             decode_znode(&opline->op2, to->T, p, l TSRMLS_CC);
569             break;
570         default:
571             zend_bailout();
572             break;
573     }
574 }
575
576 static zend_op_array* decode_op_array(zend_op_array *to, char** p, unsigned int* l TSRMLS_DC) {
577   char c;
578   zend_op *opline;
579   zend_op *end;
580 #ifdef ZEND_ENGINE_2
581   char* scope_name;
582   int   scope_name_len;
583 #endif
584
585   c = decode(p, l);
586   if (c == ZEND_INTERNAL_FUNCTION) {
587     if (to == NULL) {
588       to = (zend_op_array*)emalloc(sizeof(zend_internal_function));
589     }
590     memset(to, 0, sizeof(zend_internal_function));
591   } else if (c == ZEND_USER_FUNCTION) {
592     if (to == NULL) {
593       to = (zend_op_array*)emalloc(sizeof(zend_op_array));
594     }
595     memset(to, 0, sizeof(zend_op_array));
596     zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) call_op_array_ctor_handler, to TSRMLS_CC);
597   } else {
598     zend_bailout();
599   }
600   to->type = c;
601 #ifdef ZEND_ENGINE_2
602   to->num_args = decode32(p, l);
603   if (to->num_args > 0) {
604     zend_uint i;
605     to->arg_info = (zend_arg_info*)emalloc(to->num_args * sizeof(zend_arg_info));
606     for (i = 0; i < to->num_args; i++) {
607       to->arg_info[i].name = decode_lstr(&to->arg_info[i].name_len, p ,l);
608       to->arg_info[i].class_name = decode_lstr(&to->arg_info[i].class_name_len, p ,l);
609       to->arg_info[i].allow_null = decode(p, l);
610       to->arg_info[i].pass_by_reference = decode(p, l);
611     }
612   } else {
613     to->arg_info = NULL;
614   }
615   to->pass_rest_by_reference = decode(p, l);
616 #else
617   to->arg_types     = decode_pstr(p, l);
618 #endif
619   to->function_name = decode_zstr(p, l);
620 #ifdef ZEND_ENGINE_2
621         to->scope            = EAG(class_entry);
622         to->fn_flags         = decode32(p, l);
623         scope_name = decode_lstr((unsigned int*)&scope_name_len, p, l);
624         if (to->scope == NULL && scope_name != NULL) {
625                 if (zend_hash_find(CG(class_table), (void *)scope_name,
626                     scope_name_len, (void **)&to->scope) == SUCCESS) {
627                         to->scope = *(zend_class_entry**)to->scope;
628                 } else {
629             to->scope = NULL;
630         }
631         }
632 #endif
633   if (to->type == ZEND_INTERNAL_FUNCTION) {
634     return to;
635   }
636   to->T = decode32(p, l);
637 #ifdef ZEND_ENGINE_2
638   to->uses_this = decode(p, l);
639 #else
640   to->uses_globals = decode(p, l);
641 #endif
642   to->return_reference = decode(p, l);
643
644   to->last = decode32(p, l);
645   to->size = to->last;
646   if (to->last > 0) {
647     to->last_brk_cont = decode32(p, l);
648     if (to->last_brk_cont > 0) {
649       zend_uint i;
650       to->brk_cont_array = emalloc(sizeof(zend_brk_cont_element)*to->last_brk_cont);
651       for (i = 0; i < to->last_brk_cont; i++) {
652         to->brk_cont_array[i].brk = decode_opline(to->last, p, l);
653         to->brk_cont_array[i].cont = decode_opline(to->last, p, l);
654         to->brk_cont_array[i].parent = decode_opline(to->last_brk_cont, p, l);
655       }
656     } else {
657       to->brk_cont_array = NULL;
658     }
659 #ifdef ZEND_ENGINE_2
660         to->last_try_catch = decode32(p, l);
661         if (to->last_try_catch > 0)
662         {
663                 zend_uint i;
664                 to->try_catch_array = emalloc(sizeof(zend_try_catch_element)*to->last_try_catch);
665                 for (i = 0; i < to->last_try_catch; i++)
666                 {
667                         to->try_catch_array[i].try_op = decode_opline(to->last, p, l);
668                         to->try_catch_array[i].catch_op = decode_opline(to->last, p, l);
669 //                      to->try_catch_array[i].parent = decode_opline(to->last_brk_cont, p, l);
670                 }
671         }
672         else
673         {
674                 to->try_catch_array = NULL;
675 }
676 #endif
677     to->opcodes = emalloc(sizeof(zend_op)*to->last);
678     memset(to->opcodes, 0, sizeof(zend_op)*to->last);
679     opline = to->opcodes;
680     end = opline + to->last;
681     for (;opline < end; opline++) {
682       const opcode_dsc* op_dsc;
683       opline->opcode = decode(p, l);
684       op_dsc = get_opcode_dsc(opline->opcode);
685       if (op_dsc == NULL) {
686         zend_bailout();
687       } else {
688         decode_op(to, opline, op_dsc->ops, p, l TSRMLS_CC);
689       }
690     }
691   } else {
692     to->opcodes = NULL;
693   }
694
695 #ifdef ZEND_ENGINE_2
696   to->static_variables = decode_zval_hash(NULL, p, l);
697 #else
698   to->static_variables = decode_zval_hash_noref(NULL, p, l);
699 #endif
700   if (to->static_variables) {
701     to->static_variables->pDestructor = ZVAL_PTR_DTOR;
702   }
703 #if EA_ENCODER_VERSION < 2
704   to->filename = decode_filename(p, l TSRMLS_CC);
705 #else
706   if (((loader_data*)EAG(mem))->version < 2) {
707     to->filename = decode_zstr(p, l);
708     efree(to->filename);
709   }
710   to->filename = ((loader_data*)EAG(mem))->filename;
711 #endif
712 #ifdef ZEND_ENGINE_2
713   to->line_start = decode32(p, l);
714   to->line_end = decode32(p, l);
715   to->doc_comment = decode_lstr(&to->doc_comment_len, p, l);
716 #endif
717   to->start_op = to->opcodes;
718   to->current_brk_cont = 0xffffffff;
719   to->backpatch_count  = 0;
720   to->done_pass_two    = 1;
721   to->refcount = emalloc(sizeof(*to->refcount));
722    *to->refcount=1;
723   return to;
724 }
725
726
727 #ifdef ZEND_ENGINE_2
728 static zend_property_info* decode_property_info(zend_property_info* to, char** p, unsigned int* l TSRMLS_DC) {
729   if (to == NULL) {
730     to = emalloc(sizeof(zend_property_info));
731   }
732   to->flags = decode32(p, l);
733   to->name = decode_lstr((unsigned int*)&to->name_length, p, l);
734   return to;
735 }
736 #endif
737
738 static zend_class_entry* decode_class_entry(zend_class_entry* to, char** p, unsigned int* l TSRMLS_DC) {
739   char c;
740   zend_class_entry* old;
741   char*             s;
742   unsigned int      len;
743
744   c = decode(p, l);
745   if (c != ZEND_USER_CLASS) {
746     zend_bailout();
747   }
748
749   if (to == NULL) {
750       to = emalloc(sizeof(zend_class_entry));
751   }
752   memset(to, 0, sizeof(zend_class_entry));
753
754   to->type = c;
755   to->name = decode_lstr(&to->name_length, p ,l);
756 #ifdef ZEND_ENGINE_2
757   to->ce_flags = decode32(p ,l);
758   to->num_interfaces = decode32(p, l);
759   if (to->num_interfaces > 0) {
760     to->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *)*to->num_interfaces);
761   } else {
762     to->interfaces = NULL;
763   }
764   to->create_object = NULL;
765 #endif
766
767   to->parent      = NULL;
768   s = decode_lstr(&len, p, l);
769   if (s != NULL)
770       restore_class_parent(s, len, to TSRMLS_CC);
771
772   old = EAG(class_entry);
773   EAG(class_entry) = to;
774
775 #ifdef ZEND_ENGINE_2
776   to->refcount = 1;
777
778 #if EA_ENCODER_VERSION < 2
779   to->line_start = decode32(p, l);
780   to->line_end = decode32(p, l);
781   to->filename = decode_filename(p, l TSRMLS_CC);
782 #else
783   if (((loader_data*)EAG(mem))->version < 2) {
784     to->line_start = decode32(p, l);
785     to->line_end = decode32(p, l);
786     to->filename = decode_zstr(p, l);
787     efree(to->filename);
788   }
789   to->line_start = ((loader_data*)EAG(mem))->lineno;
790   to->line_end = ((loader_data*)EAG(mem))->lineno;
791   to->filename = ((loader_data*)EAG(mem))->filename;
792 #endif
793   to->doc_comment = decode_lstr(&to->doc_comment_len, p, l);
794
795   zend_hash_init(&to->constants_table, 0, NULL, ZVAL_PTR_DTOR, 0);
796   decode_zval_hash(&to->constants_table, p, l);
797
798   zend_hash_init(&to->default_properties, 0, NULL, ZVAL_PTR_DTOR, 0);
799   decode_zval_hash(&to->default_properties, p, l);
800
801 /*???FIXME
802   zend_hash_init_ex(&to->properties_info, 0, NULL, (dtor_func_t)zend_destroy_property_info, 0, 0);
803 */
804   zend_hash_init_ex(&to->properties_info, 0, NULL, (dtor_func_t)NULL, 0, 0);
805   decode_hash(&to->properties_info, sizeof(zend_property_info), (decode_bucket_t)decode_property_info, p, l TSRMLS_CC);
806
807   ALLOC_HASHTABLE(to->static_members);
808   zend_hash_init_ex(to->static_members, 0, NULL, ZVAL_PTR_DTOR, 0, 0);
809   decode_zval_hash(to->static_members, p, l);
810
811   {
812     Bucket *q = to->properties_info.pListHead;
813     while (q != NULL) {
814       zend_property_info* x = (zend_property_info*)q->pData;
815       Bucket * y = NULL;
816       if ((x->flags & ZEND_ACC_STATIC) && to->static_members != NULL && to->static_members->nNumOfElements > 0) {
817         y = to->static_members->pListHead;
818       } else if ((x->flags & ZEND_ACC_STATIC) == 0 && to->default_properties.nNumOfElements > 0) {
819         y = to->default_properties.pListHead;
820       }
821       while (y != NULL) {
822         if ((int)y->nKeyLength == x->name_length+1 &&
823              memcmp(y->arKey, x->name, x->name_length+1) == 0) {
824           x->h = y->h;
825           break;
826         }
827         y = y->pListNext;
828       }
829       q = q->pListNext;
830     }
831   }
832
833 #else
834   to->refcount = emalloc(sizeof(*to->refcount));
835   *to->refcount = 1;
836
837   zend_hash_init(&to->default_properties, 0, NULL, ZVAL_PTR_DTOR, 0);
838   decode_zval_hash_noref(&to->default_properties, p, l);
839 #endif
840   zend_hash_init(&to->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 0);
841   decode_hash(&to->function_table, sizeof(zend_op_array), (decode_bucket_t)decode_op_array, p, l TSRMLS_CC);
842   to->constants_updated = 0;
843
844 #ifdef ZEND_ENGINE_2
845   restore_class_methods(to TSRMLS_CC);
846 #endif
847
848   EAG(class_entry) = old;
849
850   return to;
851 }
852
853 zend_op_array* eaccelerator_load(char* src, int src_len TSRMLS_DC) {
854   zval func;
855   zval gzstring;
856   zval retval;
857   zval param;
858   zval *params[1];
859   zend_op_array* to = NULL;
860   zend_bool error_reported = 0;
861
862   if (!zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
863     zend_error(E_ERROR, "eAccelerator Loader requires php_zlib extension\n");
864     return NULL;
865   }
866
867   ZVAL_STRING(&func, "base64_decode", 0);
868   INIT_ZVAL(param);
869   params[0] = &param;
870   ZVAL_STRINGL(params[0], src, src_len, 0);
871   if (call_user_function(CG(function_table), (zval**)NULL, &func, &gzstring, 1, params TSRMLS_CC) == SUCCESS &&
872       gzstring.type == IS_STRING) {
873     ZVAL_STRING(&func, "gzuncompress", 0);
874     params[0] = &gzstring;
875     if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
876         retval.type == IS_STRING) {
877       zend_bool old_in_compilation = CG(in_compilation);
878       zend_bool old_in_execution   = EG(in_execution);
879       zval_dtor(&gzstring);
880       zend_try {
881         char*        p = retval.value.str.val;
882         unsigned int l = retval.value.str.len;
883         char *s;
884         unsigned char c;
885         unsigned int  v;
886
887         s = decode_zstr_noalloc(&p, &l);
888         if (s != NULL && strcmp(s,"EACCELERATOR") == 0) {
889           v = decode32(&p, &l);
890           if (v <= EA_ENCODER_VERSION) {
891             loader_data data;
892             data.version  = v;
893             data.filename = NULL;
894             data.lineno = 0;
895             EAG(mem) = (char*)&data;
896             c = decode(&p, &l);
897 #ifdef ZEND_ENGINE_2
898             if (c == 2) {
899 #else
900             if (c == 1) {
901 #endif
902               EAG(class_entry) = NULL;
903 #if EA_ENCODER_VERSION > 1
904               if (CG(in_compilation)) {
905                 data.filename = CG(compiled_filename);
906                 data.lineno = 0;
907               } else {
908                 char* old = CG(compiled_filename);
909                 if (EG(active_op_array && EG(active_op_array)->filename)) {
910                   data.filename = zend_set_compiled_filename(EG(active_op_array)->filename TSRMLS_CC);
911                 }
912                 CG(compiled_filename) = old;
913                 data.lineno = zend_get_executed_lineno(TSRMLS_C);
914               }
915 #endif
916               while (1) {
917                 c = decode(&p, &l);
918                 if (c == EA_ENCODER_CLASS) {
919 #ifdef ZEND_ENGINE_2
920                   zend_class_entry* x;
921                   s = decode_lstr_noalloc(&v, &p, &l);
922                   x = decode_class_entry(NULL, &p, &l TSRMLS_CC);
923 #else
924                   zend_class_entry x;
925                   s = decode_lstr_noalloc(&v, &p, &l);
926                   decode_class_entry(&x, &p, &l TSRMLS_CC);
927 #endif
928                   if ((s[0] == '\000') &&
929                       zend_hash_exists(CG(class_table), s, v)) {
930 #ifdef ZEND_ENGINE_2
931                   } else if (zend_hash_add(CG(class_table), s, v,
932                       &x, sizeof(zend_class_entry*), NULL) == FAILURE) {
933 #else
934                   } else if (zend_hash_add(CG(class_table), s, v,
935                       &x, sizeof(zend_class_entry), NULL) == FAILURE) {
936 #endif
937                     error_reported = 1;
938                     zend_error(E_ERROR, "Cannot redeclare class %s", s);
939                   }
940                 } else if (c == EA_ENCODER_END) {
941                   break;
942                 } else {
943                   zend_bailout();
944                 }
945               }
946               while (1) {
947                 c = decode(&p, &l);
948                 if (c == EA_ENCODER_FUNCTION) {
949                   zend_op_array x;
950                   s = decode_lstr_noalloc(&v, &p, &l);
951                   decode_op_array(&x, &p, &l TSRMLS_CC);
952                   if ((s[0] == '\000') &&
953                       zend_hash_exists(CG(function_table), s, v)) {
954                   } else if (zend_hash_add(CG(function_table), s, v,
955                              &x, sizeof(zend_op_array), NULL) == FAILURE) {
956                     error_reported = 1;
957                     zend_error(E_ERROR, "Cannot redeclare %s()", s);
958                   }
959                 } else if (c == EA_ENCODER_END) {
960                   break;
961                 } else {
962                   zend_bailout();
963                 }
964               }
965               to = decode_op_array(NULL, &p, &l TSRMLS_CC);
966               if (l != 0) {
967                 zend_bailout();
968               }
969             } else {
970               error_reported = 1;
971               zend_error(E_ERROR, "eAccelerator Loader can't load code. Incorrect Zend Engine version");
972             }
973           } else {
974             error_reported = 1;
975             zend_error(E_ERROR, "eAccelerator Loader can't load code. Incorrect eAccelerator encoder version (%u)", v);
976           }
977         } else {
978           error_reported = 1;
979           zend_error(E_ERROR, "eAccelerator Loader can't load code. Incorrect code");
980         }
981       } zend_catch {
982         CG(in_compilation) = old_in_compilation;
983         EG(in_execution)   = old_in_execution;
984         to = NULL;
985       } zend_end_try();
986       zval_dtor(&retval);
987     }
988   }
989   if (to == NULL) {
990     if (error_reported) {
991       zend_bailout();
992     } else {
993       zend_error(E_ERROR, "eAccelerator Loader can't load code. Incorrect code");
994     }
995   }
996   return to;
997 }
998
999 PHP_FUNCTION(eaccelerator_load) {
1000   char *src;
1001   int   src_len;
1002   zend_op_array* op_array;
1003
1004   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
1005     "s", &src, &src_len) == FAILURE) {
1006     RETURN_FALSE;
1007   }
1008   if ((op_array = eaccelerator_load(src, src_len TSRMLS_CC)) != NULL) {
1009     zval *local_retval_ptr=NULL;
1010     zend_function_state *original_function_state_ptr = EG(function_state_ptr);
1011     zval **original_return_value = EG(return_value_ptr_ptr);
1012     zend_op_array *original_op_array = EG(active_op_array);
1013     zend_op **original_opline_ptr = EG(opline_ptr);
1014
1015     EG(return_value_ptr_ptr) = &local_retval_ptr;
1016     EG(active_op_array) = op_array;
1017
1018     zend_execute(op_array TSRMLS_CC);
1019
1020     if (local_retval_ptr) {
1021       if (return_value != NULL) {
1022         COPY_PZVAL_TO_ZVAL(*return_value, local_retval_ptr);
1023       } else {
1024         zval_ptr_dtor(&local_retval_ptr);
1025       }
1026     } else if (return_value) {
1027       INIT_ZVAL(*return_value);
1028     }
1029
1030 #ifdef ZEND_ENGINE_2
1031     destroy_op_array(op_array TSRMLS_CC);
1032 #else
1033     destroy_op_array(op_array);
1034 #endif
1035     efree(op_array);
1036
1037     EG(active_op_array) = original_op_array;
1038     EG(return_value_ptr_ptr)=original_return_value;
1039     EG(opline_ptr) = original_opline_ptr;
1040     EG(function_state_ptr) = original_function_state_ptr;
1041
1042     return;
1043   }
1044   RETURN_FALSE;
1045 }
1046
1047 PHP_FUNCTION(_eaccelerator_loader_file) {
1048   if (EG(active_op_array) && EG(active_op_array)->filename) {
1049     RETURN_STRING(EG(active_op_array)->filename, 1);
1050   } else {
1051     RETURN_EMPTY_STRING();
1052   }
1053 }
1054
1055 PHP_FUNCTION(_eaccelerator_loader_line) {
1056   RETURN_LONG(zend_get_executed_lineno(TSRMLS_C));
1057 }
1058
1059 #ifdef HAVE_EACCELERATOR_STANDALONE_LOADER
1060 ZEND_DECLARE_MODULE_GLOBALS(eaccelerator)
1061
1062 function_entry eaccelerator_loader_functions[] = {
1063   PHP_FE(eaccelerator_load, NULL)
1064   PHP_FE(_eaccelerator_loader_file, NULL)
1065   PHP_FE(_eaccelerator_loader_line, NULL)
1066   {NULL, NULL, NULL}
1067 };
1068
1069 static void eaccelerator_init_globals(zend_eaccelerator_globals *eaccelerator_globals) {
1070 }
1071
1072 PHP_MINIT_FUNCTION(eaccelerator_loader) {
1073   if (zend_hash_exists(&module_registry, EACCELERATOR_EXTENSION_NAME, sizeof(EACCELERATOR_EXTENSION_NAME)) &&
1074       zend_hash_exists(CG(function_table), "eaccelerator_load", sizeof("eaccelerator_load"))) {
1075     zend_error(E_CORE_WARNING,"Extension \"%s\" is not need with \"%s\". Remove it from php.ini\n", EACCELERATOR_LOADER_EXTENSION_NAME, EACCELERATOR_EXTENSION_NAME);
1076     return FAILURE;
1077   }
1078   ZEND_INIT_MODULE_GLOBALS(eaccelerator, eaccelerator_init_globals, NULL);
1079   return SUCCESS;
1080 }
1081
1082 zend_module_entry eaccelerator_loader_module_entry = {
1083 #if ZEND_MODULE_API_NO >= 20010901
1084   STANDARD_MODULE_HEADER,
1085 #endif
1086   EACCELERATOR_LOADER_EXTENSION_NAME,
1087   eaccelerator_loader_functions,
1088   PHP_MINIT(eaccelerator_loader),
1089   NULL,
1090   NULL,
1091   NULL,
1092   NULL,
1093 #if ZEND_MODULE_API_NO >= 20010901
1094   EACCELERATOR_VERSION,          /* extension version number (string) */
1095 #endif
1096   STANDARD_MODULE_PROPERTIES
1097 };
1098
1099 #if defined(COMPILE_DL_ELOADER)
1100 ZEND_GET_MODULE(eaccelerator_loader)
1101 #endif
1102 #endif
1103
1104 #endif
1105 #endif
Note: See TracBrowser for help on using the browser.