summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/fileinfo/fileinfo.c89
-rw-r--r--ext/fileinfo/libmagic/funcs.c38
-rw-r--r--ext/fileinfo/libmagic/softmagic.c226
-rw-r--r--main/spprintf.c11
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; 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:
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;
}