root/eaccelerator/branches/0.9.5/loader.c

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

Fix loader.c too so we don't get any linking errors.

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