source: eaccelerator/tags/0.9.4-rc1/loader.c @ 127

Revision 127, 31.7 KB checked in by zoeloelip, 5 years ago (diff)

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
43typedef struct loader_data {
44  long  version;
45  char* filename;
46  uint  lineno;
47} loader_data;
48
49static 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
60static 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
68static 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
74static 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
93static 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
110static 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
132static 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
153static 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
180static 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
198static 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
213static 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
231static 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
248typedef 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
253static HashTable* decode_hash(HashTable* to, int size, decode_bucket_t decode_bucket, char**p, unsigned int* l TSRMLS_DC);
254static zval* decode_zval_ptr(zval* to, char** p, unsigned int* l TSRMLS_DC);
255
256static 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
308static 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
316static 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
326static 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
340static 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
385static 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
391static 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
568static 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
720static 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
730static 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
845zend_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
991PHP_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
1039PHP_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
1047PHP_FUNCTION(_eaccelerator_loader_line) {
1048  RETURN_LONG(zend_get_executed_lineno(TSRMLS_C));
1049}
1050
1051#ifdef HAVE_EACCELERATOR_STANDALONE_LOADER
1052ZEND_DECLARE_MODULE_GLOBALS(eaccelerator)
1053
1054function_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
1061static void eaccelerator_init_globals(zend_eaccelerator_globals *eaccelerator_globals) {
1062}
1063
1064PHP_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
1074zend_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)
1092ZEND_GET_MODULE(eaccelerator_loader)
1093#endif
1094#endif
1095
1096#endif
1097#endif
Note: See TracBrowser for help on using the repository browser.