root/eaccelerator/tags/0.9.5-beta2/loader.c

Revision 191, 31.7 kB (checked in by bart, 3 years ago)

* Moved the FLOCK stuff to a place so it can be used by eLoader to
* Fixed quite some compile warnings on Win32
* Updated VC6 project files for Win32

(Note: I feel dirty now, I'm going to take a shower ;-) )

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