diff options
| author | Nikita Popov <nikic@php.net> | 2014-04-23 19:05:16 +0200 | 
|---|---|---|
| committer | Nikita Popov <nikic@php.net> | 2014-04-23 19:34:51 +0200 | 
| commit | 08ae88157b4f73154b2f1ffe72c3957edb3772fc (patch) | |
| tree | b4c1ae6e553379588d5b214d01297d476de3e4a7 | |
| parent | 20580a511c029582fd2be6c8efbed40c89f7a874 (diff) | |
| download | php-git-08ae88157b4f73154b2f1ffe72c3957edb3772fc.tar.gz | |
Allocate zend_strings with correct size
For me (32bit) sizeof(zend_string) is 20, which means that the
char[1] array at the end is padded with three bytes. Thus allocating
based on sizeof(zend_string)-1 overallocates by those 3 padding bytes.
This commit fixes the allocation size, by using XtOffsetOf.
| -rw-r--r-- | Zend/zend.h | 30 | ||||
| -rw-r--r-- | Zend/zend_ini.h | 30 | ||||
| -rw-r--r-- | Zend/zend_string.h | 10 | ||||
| -rw-r--r-- | ext/opcache/ZendAccelerator.c | 4 | ||||
| -rw-r--r-- | ext/opcache/zend_persist.c | 4 | ||||
| -rw-r--r-- | ext/opcache/zend_persist_calc.c | 2 | ||||
| -rw-r--r-- | ext/standard/php_smart_str.h | 4 | ||||
| -rw-r--r-- | ext/standard/tests/strings/str_pad_variation5.phpt | 2 | 
8 files changed, 44 insertions, 42 deletions
| diff --git a/Zend/zend.h b/Zend/zend.h index 3aae759dde..799eb25cfe 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -347,6 +347,36 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore  # define UNEXPECTED(condition) (condition)  #endif +#ifndef XtOffsetOf +# if defined(CRAY) || (defined(__ARMCC_VERSION) && !defined(LINUX)) +# ifdef __STDC__ +# define XtOffset(p_type, field) _Offsetof(p_type, field) +# else +# ifdef CRAY2 +# define XtOffset(p_type, field) \ +    (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) + +# else /* !CRAY2 */ + +# define XtOffset(p_type, field) ((unsigned int)&(((p_type)NULL)->field)) + +# endif /* !CRAY2 */ +# endif /* __STDC__ */ +# else /* ! (CRAY || __arm) */ + +# define XtOffset(p_type, field) \ +    ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) + +# endif /* !CRAY */ + +# ifdef offsetof +# define XtOffsetOf(s_type, field) offsetof(s_type, field) +# else +# define XtOffsetOf(s_type, field) XtOffset(s_type*, field) +# endif + +#endif +  #include "zend_string.h"  static zend_always_inline zend_uint zval_refcount_p(zval* pz) { diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 8782ec6f20..0a0c1137e1 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -27,36 +27,6 @@  #define ZEND_INI_ALL (ZEND_INI_USER|ZEND_INI_PERDIR|ZEND_INI_SYSTEM) -#ifndef XtOffsetOf -# if defined(CRAY) || (defined(__ARMCC_VERSION) && !defined(LINUX)) -# ifdef __STDC__ -# define XtOffset(p_type, field) _Offsetof(p_type, field) -# else -# ifdef CRAY2 -# define XtOffset(p_type, field) \ -    (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) - -# else /* !CRAY2 */ - -# define XtOffset(p_type, field) ((unsigned int)&(((p_type)NULL)->field)) - -# endif /* !CRAY2 */ -# endif /* __STDC__ */ -# else /* ! (CRAY || __arm) */ - -# define XtOffset(p_type, field) \ -    ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) - -# endif /* !CRAY */ - -# ifdef offsetof -# define XtOffsetOf(s_type, field) offsetof(s_type, field) -# else -# define XtOffsetOf(s_type, field) XtOffset(s_type*, field) -# endif - -#endif -  #define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)  #define ZEND_INI_DISP(name) void name(zend_ini_entry *ini_entry, int type) diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 5226c06e79..af83d4d3b5 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -54,6 +54,8 @@ END_EXTERN_C()  #define STR_RELEASE(s)					zend_str_release(s)  #define STR_EMPTY_ALLOC()				CG(empty_string) +#define _STR_HEADER_SIZE XtOffsetOf(zend_string, val) +  static zend_always_inline zend_ulong zend_str_hash_val(zend_string *s)  {  	if (!s->h) { @@ -93,7 +95,7 @@ static zend_always_inline zend_uint zend_str_delref(zend_string *s)  static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)  { -	zend_string *ret = pemalloc(sizeof(zend_string) + len, persistent); +	zend_string *ret = pemalloc(_STR_HEADER_SIZE + len + 1, persistent);  	GC_REFCOUNT(ret) = 1;  #if 1 @@ -111,7 +113,7 @@ static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)  static zend_always_inline zend_string *zend_str_safe_alloc(size_t n, size_t m, size_t l, int persistent)  { -	zend_string *ret = safe_pemalloc(n, m, sizeof(zend_string) + l - 1, persistent); +	zend_string *ret = safe_pemalloc(n, m, _STR_HEADER_SIZE + l + 1, persistent);  	GC_REFCOUNT(ret) = 1;  #if 1 @@ -161,7 +163,7 @@ static zend_always_inline zend_string *zend_str_realloc(zend_string *s, int len,  		ret = STR_ALLOC(len, persistent);  		memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);  	} else if (STR_REFCOUNT(s) == 1) { -		ret = perealloc(s, sizeof(zend_string) + len, persistent); +		ret = perealloc(s, _STR_HEADER_SIZE + len + 1, persistent);  		ret->len = len;  		STR_FORGET_HASH_VAL(ret);  	} else { @@ -180,7 +182,7 @@ static zend_always_inline zend_string *zend_str_safe_realloc(zend_string *s, siz  		ret = STR_SAFE_ALLOC(n, m, l, persistent);  		memcpy(ret->val, s->val, ((n * m) + l > s->len ? s->len : ((n * m) + l)) + 1);  	} else if (STR_REFCOUNT(s) == 1) { -		ret = safe_perealloc(s, n, m, sizeof(zend_string) + l - 1, persistent); +		ret = safe_perealloc(s, n, m, _STR_HEADER_SIZE + l + 1, persistent);  		ret->len = (n * m) + l;  		STR_FORGET_HASH_VAL(ret);  	} else { diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 84c397d7ab..11ca76e2f3 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -336,7 +336,7 @@ zend_string *accel_new_interned_string(zend_string *str TSRMLS_DC)  		idx = Z_NEXT(p->val);  	} -	if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_string) + str->len) >= +	if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + str->len + 1) >=  	    ZCSG(interned_strings_end)) {  	    /* no memory, return the same non-interned string */  		return str; @@ -348,7 +348,7 @@ zend_string *accel_new_interned_string(zend_string *str TSRMLS_DC)  	ZCSG(interned_strings).nNumOfElements++;  	p = ZCSG(interned_strings).arData + idx;  	p->key = (zend_string*) ZCSG(interned_strings_top); -	ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(zend_string) + str->len); +	ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + str->len + 1);  	p->h = h;  	GC_REFCOUNT(p->key) = 1;  #if 1 diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index ca2ad5150c..39a2aa4a7c 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -40,13 +40,13 @@  			STR_RELEASE(str); \  			str = new_str; \  		} else { \ -	    	new_str = _zend_shared_memdup((void*)str, sizeof(zend_string) + (str)->len, 0 TSRMLS_CC); \ +	    	new_str = _zend_shared_memdup((void*)str, _STR_HEADER_SIZE + (str)->len + 1, 0 TSRMLS_CC); \  			STR_RELEASE(str); \  	    	str = new_str; \  		} \      } while (0)  # define zend_accel_memdup_string(str) \ -	zend_accel_memdup(str, sizeof(zend_string) + (str)->len) +	zend_accel_memdup(str, _STR_HEADER_SIZE + (str)->len + 1)  # define zend_accel_store_interned_string(str) do { \  		if (!IS_ACCEL_INTERNED(str)) { \  			zend_accel_store_string(str); \ diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 6298fb1aa2..a347a34cf3 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -33,7 +33,7 @@  #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO  # define ADD_STRING(str) \ -		ADD_DUP_SIZE((str), sizeof(zend_string) + (str)->len) +		ADD_DUP_SIZE((str), _STR_HEADER_SIZE + (str)->len + 1)  # define ADD_INTERNED_STRING(str, do_free) do { \  		if (!IS_ACCEL_INTERNED(str)) { \  			zend_string *tmp = accel_new_interned_string(str TSRMLS_CC); \ diff --git a/ext/standard/php_smart_str.h b/ext/standard/php_smart_str.h index a518fbfddf..5cc3a62137 100644 --- a/ext/standard/php_smart_str.h +++ b/ext/standard/php_smart_str.h @@ -45,11 +45,11 @@  #ifdef SMART_STR_USE_REALLOC  #define SMART_STR_DO_REALLOC(b, w) do {								\ -	(b)->s = erealloc((buf)->s, sizeof(zend_string) + (b)->a);		\ +	(b)->s = erealloc((buf)->s, _STR_HEADER_SIZE + (b)->a + 1);		\  } while (0)  #else  #define SMART_STR_DO_REALLOC(b, w) do {								\ -	(b)->s = perealloc((b)->s, sizeof(zend_string) + (b)->a, (w));	\ +	(b)->s = perealloc((b)->s, _STR_HEADER_SIZE + (b)->a + 1, (w));	\  } while (0)  #endif diff --git a/ext/standard/tests/strings/str_pad_variation5.phpt b/ext/standard/tests/strings/str_pad_variation5.phpt index 0dee148650..d050ae80e8 100644 --- a/ext/standard/tests/strings/str_pad_variation5.phpt +++ b/ext/standard/tests/strings/str_pad_variation5.phpt @@ -24,7 +24,7 @@ echo "*** Testing str_pad() function: with large value for for 'pad_length' argu  //defining '$input' argument  $input = "Test string"; -$pad_length = PHP_INT_MAX - 20 + 1; /* sizeof(zend_string) is 20, 1 character is included in zend_string structure itself */ +$pad_length = PHP_INT_MAX - 16; /* zend_string header is 16 bytes */  var_dump( str_pad($input, $pad_length) );  ?> | 
