]> granicus.if.org Git - php/commitdiff
Refactor fileinfo
authorXinchen Hui <laruence@php.net>
Wed, 7 May 2014 05:50:29 +0000 (13:50 +0800)
committerXinchen Hui <laruence@php.net>
Wed, 7 May 2014 05:50:29 +0000 (13:50 +0800)
ext/fileinfo/fileinfo.c
ext/fileinfo/libmagic/funcs.c
ext/fileinfo/libmagic/softmagic.c
main/spprintf.c

index 2f61944ad764fe04cc1a33f84b00499b223e4f1e..86cd02a613943e35d6b70643b91d58414fe32c5a 100644 (file)
 #endif
 
 /* {{{ macros and type definitions */
-struct php_fileinfo {
+typedef struct _php_fileinfo {
        long options;
        struct magic_set *magic;
-};
+} php_fileinfo;
 
 static zend_object_handlers finfo_object_handlers;
 zend_class_entry *finfo_class_entry;
 
-struct finfo_object {
+typedef struct _finfo_object {
+       php_fileinfo *ptr;
        zend_object zo;
-       struct php_fileinfo *ptr;
-};
+} finfo_object;
 
 #define FILEINFO_DECLARE_INIT_OBJECT(object) \
        zval *object = getThis();
 
+static inline finfo_object *php_finfo_fetch_object(zend_object *obj) {
+       return (finfo_object *)((char*)(obj) - XtOffsetOf(finfo_object, zo));
+}
+
+#define Z_FINFO_P(zv) php_finfo_fetch_object(Z_OBJ_P((zv)))
+
 #define FILEINFO_REGISTER_OBJECT(_object, _ptr) \
 { \
-       struct finfo_object *obj; \
-        obj = (struct finfo_object*)zend_object_store_get_object(_object TSRMLS_CC); \
-        obj->ptr = _ptr; \
+       finfo_object *obj; \
+    obj = Z_FINFO_P(_object); \
+    obj->ptr = _ptr; \
 }
 
 #define FILEINFO_FROM_OBJECT(finfo, object) \
 { \
-       struct finfo_object *obj = zend_object_store_get_object(object TSRMLS_CC); \
+       finfo_object *obj = Z_FINFO_P(object); \
        finfo = obj->ptr; \
        if (!finfo) { \
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The invalid fileinfo object."); \
@@ -78,9 +84,9 @@ struct finfo_object {
 
 /* {{{ finfo_objects_free
  */
-static void finfo_objects_free(void *object TSRMLS_DC)
+static void finfo_objects_free(zend_object *object TSRMLS_DC)
 {
-       struct finfo_object *intern = (struct finfo_object *) object;
+       finfo_object *intern = php_finfo_fetch_object(object);
 
        if (intern->ptr) {
                magic_close(intern->ptr->magic);
@@ -88,30 +94,22 @@ static void finfo_objects_free(void *object TSRMLS_DC)
        }
 
        zend_object_std_dtor(&intern->zo TSRMLS_CC);
-       efree(intern);
 }
 /* }}} */
 
 /* {{{ finfo_objects_new
  */
-PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_type TSRMLS_DC)
+PHP_FILEINFO_API zend_object *finfo_objects_new(zend_class_entry *class_type TSRMLS_DC)
 {
-       zend_object_value retval;
-       struct finfo_object *intern;
+       finfo_object *intern;
 
-       intern = emalloc(sizeof(struct finfo_object));
-       memset(intern, 0, sizeof(struct finfo_object));
+       intern = ecalloc(1, sizeof(finfo_object) + sizeof(zval) * (class_type->default_properties_count - 1));
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
        object_properties_init(&intern->zo, class_type);
+       intern->zo.handlers = &finfo_object_handlers;
 
-       intern->ptr = NULL;
-
-       retval.handle = zend_objects_store_put(intern, NULL,
-               finfo_objects_free, NULL TSRMLS_CC);
-       retval.handlers = (zend_object_handlers *) &finfo_object_handlers;
-
-       return retval;
+       return &intern->zo;
 }
 /* }}} */
 
@@ -187,10 +185,10 @@ zend_function_entry finfo_class_functions[] = {
 static int le_fileinfo;
 /* }}} */
 
-void finfo_resource_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+void finfo_resource_destructor(zend_resource *rsrc TSRMLS_DC) /* {{{ */
 {
        if (rsrc->ptr) {
-               struct php_fileinfo *finfo = (struct php_fileinfo *) rsrc->ptr;
+               php_fileinfo *finfo = (php_fileinfo *) rsrc->ptr;
                magic_close(finfo->magic);
                efree(rsrc->ptr);
                rsrc->ptr = NULL;
@@ -223,6 +221,8 @@ PHP_MINIT_FUNCTION(finfo)
 
        /* copy the standard object handlers to you handler table */
        memcpy(&finfo_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       finfo_object_handlers.offset = XtOffsetOf(finfo_object, zo);
+       finfo_object_handlers.free_obj = finfo_objects_free;
 
        le_fileinfo = zend_register_list_destructors_ex(finfo_resource_destructor, NULL, "file_info", module_number);
 
@@ -282,13 +282,12 @@ PHP_MINFO_FUNCTION(fileinfo)
 }
 /* }}} */
 
-#define FILEINFO_DESTROY_OBJECT(object)                                                        \
-       do {                                                                                                            \
-               if (object) {                                                                                   \
-                       zend_object_store_ctor_failed(object TSRMLS_CC);        \
-                       zval_dtor(object);                                                                      \
-                       ZVAL_NULL(object);                                                                      \
-               }                                                                                                               \
+#define FILEINFO_DESTROY_OBJECT(object)                                                                        \
+       do {                                                                                                                            \
+               if (object) {                                                                                                   \
+                       zend_object_store_ctor_failed(Z_OBJ_P(object) TSRMLS_CC);       \
+                       Z_OBJ_P(object) = NULL;                                                                         \
+               }                                                                                                                               \
        } while (0)
 
 /* {{{ proto resource finfo_open([int options [, string arg]])
@@ -298,7 +297,7 @@ PHP_FUNCTION(finfo_open)
        long options = MAGIC_NONE;
        char *file = NULL;
        int file_len = 0;
-       struct php_fileinfo *finfo;
+       php_fileinfo *finfo;
        FILEINFO_DECLARE_INIT_OBJECT(object)
        char resolved_path[MAXPATHLEN];
 
@@ -308,7 +307,7 @@ PHP_FUNCTION(finfo_open)
        }
 
        if (object) {
-               struct finfo_object *finfo_obj = (struct finfo_object*)zend_object_store_get_object(object TSRMLS_CC);
+               finfo_object *finfo_obj = Z_FINFO_P(object);
 
                if (finfo_obj->ptr) {
                        magic_close(finfo_obj->ptr->magic);
@@ -332,7 +331,7 @@ PHP_FUNCTION(finfo_open)
                file = resolved_path;
        }
 
-       finfo = emalloc(sizeof(struct php_fileinfo));
+       finfo = emalloc(sizeof(php_fileinfo));
 
        finfo->options = options;
        finfo->magic = magic_open(options);
@@ -364,15 +363,15 @@ PHP_FUNCTION(finfo_open)
    Close fileinfo resource. */
 PHP_FUNCTION(finfo_close)
 {
-       struct php_fileinfo *finfo;
+       php_fileinfo *finfo;
        zval *zfinfo;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zfinfo) == FAILURE) {
                RETURN_FALSE;
        }
-       ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo);
+       ZEND_FETCH_RESOURCE(finfo, php_fileinfo *, zfinfo, -1, "file_info", le_fileinfo);
 
-       zend_list_delete(Z_RESVAL_P(zfinfo));
+       zend_list_close(Z_RES_P(zfinfo));
 
        RETURN_TRUE;
 }
@@ -383,7 +382,7 @@ PHP_FUNCTION(finfo_close)
 PHP_FUNCTION(finfo_set_flags)
 {
        long options;
-       struct php_fileinfo *finfo;
+       php_fileinfo *finfo;
        zval *zfinfo;
        FILEINFO_DECLARE_INIT_OBJECT(object)
 
@@ -396,7 +395,7 @@ PHP_FUNCTION(finfo_set_flags)
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zfinfo, &options) == FAILURE) {
                        RETURN_FALSE;
                }
-               ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo);
+               ZEND_FETCH_RESOURCE(finfo, php_fileinfo *, zfinfo, -1, "file_info", le_fileinfo);
        }
 
        FINFO_SET_OPTION(finfo->magic, options)
@@ -415,7 +414,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime
        long options = 0;
        char *ret_val = NULL, *buffer = NULL;
        int buffer_len;
-       struct php_fileinfo *finfo = NULL;
+       php_fileinfo *finfo = NULL;
        zval *zfinfo, *zcontext = NULL;
        zval *what;
        char mime_directory[] = "directory";
@@ -461,7 +460,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lr", &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
                        RETURN_FALSE;
                }
-               ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo);
+               ZEND_FETCH_RESOURCE(finfo, php_fileinfo *, zfinfo, -1, "file_info", le_fileinfo);
                magic = finfo->magic;
        }       
 
@@ -482,7 +481,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime
                                php_stream *stream;
                                off_t streampos;
 
-                               php_stream_from_zval_no_verify(stream, &what);
+                               php_stream_from_zval_no_verify(stream, what);
                                if (!stream) {
                                        goto common;
                                }
@@ -554,7 +553,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime
 
 common:
        if (ret_val) {
-               RETVAL_STRING(ret_val, 1);
+               RETVAL_STRING(ret_val);
        } else {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
                RETVAL_FALSE;
index e1aa7b9c3decf2a7810393d03a48b2889c70a8d1..3c9d387470243b22eacc236d29692c0088cda275 100644 (file)
@@ -56,7 +56,7 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.67 2014/02/12 23:20:53 christos Exp $")
 # define PREG_OFFSET_CAPTURE                 (1<<8)
 #endif
 
-extern public void convert_libmagic_pattern(zval *pattern, int options);
+extern public void convert_libmagic_pattern(zval *pattern, char *val, int len, int options);
 
 protected int
 file_printf(struct magic_set *ms, const char *fmt, ...)
@@ -440,46 +440,38 @@ file_printedlen(const struct magic_set *ms)
 
 file_replace(struct magic_set *ms, const char *pat, const char *rep)
 {
-       zval *patt;
+       zval patt;
        int opts = 0;
        pcre_cache_entry *pce;
-       char *res;
-       zval *repl;
-       int res_len, rep_cnt = 0;
+       zend_string *res;
+       zval repl;
+       int  rep_cnt = 0;
        TSRMLS_FETCH();
 
        (void)setlocale(LC_CTYPE, "C");
 
-       MAKE_STD_ZVAL(patt);
-       ZVAL_STRINGL(patt, pat, strlen(pat), 0);
        opts |= PCRE_MULTILINE;
-       convert_libmagic_pattern(patt, opts);
-       if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
-               zval_dtor(patt);
-               FREE_ZVAL(patt);
+       convert_libmagic_pattern(&patt, pat, strlen(pat), opts);
+       if ((pce = pcre_get_compiled_regex_cache(Z_STR(patt) TSRMLS_CC)) == NULL) {
+               zval_ptr_dtor(&patt);
                rep_cnt = -1;
                goto out;
        }
+       zval_ptr_dtor(&patt);
 
-       MAKE_STD_ZVAL(repl);
-       ZVAL_STRINGL(repl, rep, strlen(rep), 0);
-
-       res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), repl,
-                       0, &res_len, -1, &rep_cnt TSRMLS_CC);
-
-       FREE_ZVAL(repl);
-       zval_dtor(patt);
-       FREE_ZVAL(patt);
+       ZVAL_STRING(&repl, rep);
+       res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), &repl, 0, -1, &rep_cnt TSRMLS_CC);
 
+       zval_ptr_dtor(&repl);
        if (NULL == res) {
                rep_cnt = -1;
                goto out;
        }
 
-       strncpy(ms->o.buf, res, res_len);
-       ms->o.buf[res_len] = '\0';
+       strncpy(ms->o.buf, res->val, res->len);
+       ms->o.buf[res->len] = '\0';
 
-       efree(res);
+       STR_RELEASE(res);
 
 out:
        (void)setlocale(LC_CTYPE, "");
index 1d5db8966a0b2a33851f31598e945c7efce95429..fb275f7f26139bd41ce8d83573a576d178f161c1 100644 (file)
@@ -359,17 +359,20 @@ check_fmt(struct magic_set *ms, struct magic *m)
        pcre *pce;
        int re_options, rv = -1;
        pcre_extra *re_extra;
+       zend_string *pattern;
        TSRMLS_FETCH();
        
        if (strchr(m->desc, '%') == NULL)
                return 0;
 
        (void)setlocale(LC_CTYPE, "C");
-       if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
+       pattern = STR_INIT("~%[-0-9.]*s~", sizeof("~%[-0-9.]*s~") - 1, 0);
+       if ((pce = pcre_get_compiled_regex(pattern, &re_extra, &re_options TSRMLS_CC)) == NULL) {
                rv = -1;
        } else {
                rv = !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
        }
+       STR_RELEASE(pattern);
        (void)setlocale(LC_CTYPE, "");
        return rv;
 }
@@ -1864,39 +1867,38 @@ file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
 }
 
 public void
-convert_libmagic_pattern(zval *pattern, int options)
+convert_libmagic_pattern(zval *pattern, char *val, int len, int options)
 {
-               int i, j=0;
-               char *t;
+       int i, j=0;
+       zend_string *t;
 
-               t = (char *) safe_emalloc(Z_STRLEN_P(pattern), 2, 5);
-               
-               t[j++] = '~';
-               
-               for (i=0; i<Z_STRLEN_P(pattern); i++, j++) {
-                       switch (Z_STRVAL_P(pattern)[i]) {
-                               case '~':
-                                       t[j++] = '\\';
-                                       t[j] = '~';
-                                       break;
-                               default:
-                                       t[j] = Z_STRVAL_P(pattern)[i];
-                                       break;
-                       }
+       t = STR_ALLOC(len * 2 + 4, 0);
+
+       t->val[j++] = '~';
+
+       for (i = 0; i < len; i++, j++) {
+               switch (val[i]) {
+                       case '~':
+                               t->val[j++] = '\\';
+                               t->val[j] = '~';
+                               break;
+                       default:
+                               t->val[j] = val[i];
+                               break;
                }
-               t[j++] = '~';
-       
-               if (options & PCRE_CASELESS) 
-                       t[j++] = 'i';
-       
-               if (options & PCRE_MULTILINE)
-                       t[j++] = 'm';
+       }
+       t->val[j++] = '~';
 
-               t[j]='\0';
-       
-               Z_STRVAL_P(pattern) = t;
-               Z_STRLEN_P(pattern) = j;
+       if (options & PCRE_CASELESS) 
+               t->val[j++] = 'i';
+
+       if (options & PCRE_MULTILINE)
+               t->val[j++] = 'm';
+
+       t->val[j]='\0';
+       t->len = j;
 
+       ZVAL_STR(pattern, t);
 }
 
 private int
@@ -2059,151 +2061,95 @@ magiccheck(struct magic_set *ms, struct magic *m)
                break;
        }
        case FILE_REGEX: {
-               zval *pattern;
+               zval pattern;
                int options = 0;
                pcre_cache_entry *pce;
                TSRMLS_FETCH();
                
-               MAKE_STD_ZVAL(pattern);
-               ZVAL_STRINGL(pattern, (char *)m->value.s, m->vallen, 0);
-       
                options |= PCRE_MULTILINE;
                
                if (m->str_flags & STRING_IGNORE_CASE) {
                        options |= PCRE_CASELESS;
                }
                
-               convert_libmagic_pattern(pattern, options);
+               convert_libmagic_pattern(&pattern, (char *)m->value.s, m->vallen, options);
                
                l = v = 0;
-               if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
-                       zval_dtor(pattern);
-                       FREE_ZVAL(pattern);
+               if ((pce = pcre_get_compiled_regex_cache(Z_STR(pattern) TSRMLS_CC)) == NULL) {
+                       zval_ptr_dtor(&pattern);
                        return -1;
                } else {
                        /* pce now contains the compiled regex */
-                       zval *retval;
-                       zval *subpats;
+                       zval retval;
+                       zval subpats;
                        char *haystack;
                        
-                       MAKE_STD_ZVAL(retval);
-                       ALLOC_INIT_ZVAL(subpats);
-                       
+                       ZVAL_NULL(&subpats);
                        /* Cut the search len from haystack, equals to REG_STARTEND */
                        haystack = estrndup(ms->search.s, ms->search.s_len);
 
                        /* match v = 0, no match v = 1 */
-                       php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
+                       php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
                        /* Free haystack */
                        efree(haystack);
                        
-                       if (Z_LVAL_P(retval) < 0) {
+                       if (Z_LVAL(retval) < 0) {
                                zval_ptr_dtor(&subpats);
-                               FREE_ZVAL(retval);
-                               zval_dtor(pattern);
-                               FREE_ZVAL(pattern);
+                               zval_ptr_dtor(&pattern);
                                return -1;
-                       } else if ((Z_LVAL_P(retval) > 0) && (Z_TYPE_P(subpats) == IS_ARRAY)) {
-                               
+                       } else if ((Z_LVAL(retval) > 0) && (Z_TYPE(subpats) == IS_ARRAY)) {
                                /* Need to fetch global match which equals pmatch[0] */
-                               HashTable *ht = Z_ARRVAL_P(subpats);
-                               HashPosition outer_pos;
+                               zval *pzval;
+                               HashTable *ht = Z_ARRVAL(subpats);
                                zval *pattern_match = NULL, *pattern_offset = NULL;
-                               
-                               zend_hash_internal_pointer_reset_ex(ht, &outer_pos); 
-                               
-                               if (zend_hash_has_more_elements_ex(ht, &outer_pos) == SUCCESS &&
-                                       zend_hash_move_forward_ex(ht, &outer_pos)) {
-                                       
-                                       zval **ppzval;
-                                       
-                                       /* The first element (should be) is the global match 
-                                          Need to move to the inner array to get the global match */
-                                       
-                                       if (zend_hash_get_current_data_ex(ht, (void**)&ppzval, &outer_pos) != FAILURE) { 
-                                               
-                                               HashTable *inner_ht;
-                                               HashPosition inner_pos;
-                                               zval **match, **offset;
-                                               zval tmpcopy = **ppzval, matchcopy, offsetcopy;
-                                               
-                                               zval_copy_ctor(&tmpcopy); 
-                                               INIT_PZVAL(&tmpcopy);
-                                               
-                                               inner_ht = Z_ARRVAL(tmpcopy);
-                                               
-                                               /* If everything goes according to the master plan
-                                                  tmpcopy now contains two elements:
-                                                  0 = the match
-                                                  1 = starting position of the match */
-                                               zend_hash_internal_pointer_reset_ex(inner_ht, &inner_pos); 
-                                               
-                                               if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
-                                                       zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
-                                               
-                                                       if (zend_hash_get_current_data_ex(inner_ht, (void**)&match, &inner_pos) != FAILURE) { 
-                                                                       
-                                                               matchcopy = **match;
-                                                               zval_copy_ctor(&matchcopy);
-                                                               INIT_PZVAL(&matchcopy);
-                                                               convert_to_string(&matchcopy); 
-                                                               
-                                                               MAKE_STD_ZVAL(pattern_match);
-                                                               Z_STRVAL_P(pattern_match) = (char *)Z_STRVAL(matchcopy);
-                                                               Z_STRLEN_P(pattern_match) = Z_STRLEN(matchcopy);
-                                                               Z_TYPE_P(pattern_match) = IS_STRING; 
-
-                                                               zval_dtor(&matchcopy);
-                                                       }
-                                               }
-                                               
-                                               if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
-                                                       zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
-                                                       
-                                                       if (zend_hash_get_current_data_ex(inner_ht, (void**)&offset, &inner_pos) != FAILURE) { 
-                                                               
-                                                               offsetcopy = **offset;
-                                                               zval_copy_ctor(&offsetcopy);
-                                                               INIT_PZVAL(&offsetcopy);
-                                                               convert_to_long(&offsetcopy); 
-                                                               
-                                                               MAKE_STD_ZVAL(pattern_offset);
-                                                               Z_LVAL_P(pattern_offset) = Z_LVAL(offsetcopy);
-                                                               Z_TYPE_P(pattern_offset) = IS_LONG;
-                                                               
-                                                               zval_dtor(&offsetcopy);
-                                                       }
-                                               }
-                                               zval_dtor(&tmpcopy);    
-                                       }
-                                       
-                                       if ((pattern_match != NULL) && (pattern_offset != NULL)) {
-                                               ms->search.s += (int)Z_LVAL_P(pattern_offset); /* this is where the match starts */
-                                               ms->search.offset += (size_t)Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
-                                               ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
-                                               v = 0;
-                                               
-                                               efree(pattern_match);
-                                               efree(pattern_offset);
-                                               
-                                       } else {
-                                               zval_ptr_dtor(&subpats);
-                                               FREE_ZVAL(retval);
-                                               zval_dtor(pattern);
-                                               FREE_ZVAL(pattern);
-                                               return -1;
-                                       }
-                               }
-
 
+                               ZEND_HASH_FOREACH_VAL(ht, pzval) {
+                                       HashTable *inner_ht;
+                                       zval *match, *offset;
+                                       zval tmpcopy, matchcopy, offsetcopy;
+
+                                       ZVAL_DUP(&tmpcopy, pzval);
+
+                                       inner_ht = Z_ARRVAL(tmpcopy);
+
+                                       /* If everything goes according to the master plan
+                                          tmpcopy now contains two elements:
+                                          0 = the match
+                                          1 = starting position of the match */
+                                       ZEND_HASH_FOREACH_VAL(inner_ht, match) {
+                                               ZVAL_DUP(&matchcopy, match);
+                                               convert_to_string(&matchcopy); 
+                                               pattern_match = &matchcopy;
+                                       } ZEND_HASH_FOREACH_END();
+
+                                       ZEND_HASH_FOREACH_VAL(inner_ht, offset) {
+                                               ZVAL_DUP(&offsetcopy, offset);
+                                               convert_to_long(&offsetcopy); 
+                                               pattern_offset = &offsetcopy;
+                                       } ZEND_HASH_FOREACH_END();
+
+                                       zval_dtor(&tmpcopy);    
+                               } ZEND_HASH_FOREACH_END();
+
+                               if ((pattern_match != NULL) && (pattern_offset != NULL)) {
+                                       ms->search.s += Z_LVAL_P(pattern_offset); /* this is where the match starts */
+                                       ms->search.offset += Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
+                                       ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
+                                       v = 0;
+
+                                       zval_ptr_dtor(pattern_match);
+                                       zval_ptr_dtor(pattern_offset);
+                               } else {
+                                       zval_ptr_dtor(&subpats);
+                                       zval_ptr_dtor(&pattern);
+                                       return -1;
+                               }
                        } else {
                                v = 1;
                        }
                        zval_ptr_dtor(&subpats);
-                       FREE_ZVAL(retval);
+                       zval_ptr_dtor(&pattern);
                }
-               zval_dtor(pattern);
-               FREE_ZVAL(pattern);
                break;
        }
        case FILE_INDIRECT:
index dfee6d9612d22747975c2523b3183fe843d08c0f..57548a5fcbd736df2a1baf727aab770b2e14782c 100644 (file)
@@ -804,9 +804,14 @@ PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap
        }
        smart_str_0(&xbuf);
 
-       *pbuf = estrndup(xbuf.s->val, xbuf.s->len);
-       result = xbuf.s->len;
-       smart_str_free(&xbuf);
+       if (xbuf.s) {
+               *pbuf = estrndup(xbuf.s->val, xbuf.s->len);
+               result = xbuf.s->len;
+               smart_str_free(&xbuf);
+       } else {
+               *pbuf = NULL;
+               result = 0;
+       }
 
        return result;
 }