From 9ef21b7606f00a879f15e236c9c1cdf0fa685e31 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 7 May 2014 13:50:29 +0800 Subject: [PATCH] Refactor fileinfo --- ext/fileinfo/fileinfo.c | 89 ++++++------ ext/fileinfo/libmagic/funcs.c | 38 ++--- ext/fileinfo/libmagic/softmagic.c | 226 ++++++++++++------------------ main/spprintf.c | 11 +- 4 files changed, 153 insertions(+), 211 deletions(-) diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 2f61944ad7..86cd02a613 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -43,32 +43,38 @@ #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; diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c index e1aa7b9c3d..3c9d387470 100644 --- a/ext/fileinfo/libmagic/funcs.c +++ b/ext/fileinfo/libmagic/funcs.c @@ -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, ""); diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c index 1d5db8966a..fb275f7f26 100644 --- a/ext/fileinfo/libmagic/softmagic.c +++ b/ext/fileinfo/libmagic/softmagic.c @@ -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; ival[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: diff --git a/main/spprintf.c b/main/spprintf.c index dfee6d9612..57548a5fcb 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -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; } -- 2.40.0