root/eaccelerator/tags/0.9.4-rc1/loader.c

Revision 127, 31.7 kB (checked in by zoeloelip, 3 years ago)

Included some compile fixes. (Thanks Matt)

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