mirror of
https://github.com/dunglas/frankenphp.git
synced 2025-09-26 19:41:13 +08:00
fix(types): better zval handling to avoid leaks with arrays (#1780)
This commit is contained in:

committed by
GitHub

parent
365eae1a99
commit
1d0169d321
14
types.c
14
types.c
@@ -20,3 +20,17 @@ void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor,
|
||||
bool persistent) {
|
||||
zend_hash_init(ht, nSize, NULL, pDestructor, persistent);
|
||||
}
|
||||
|
||||
void __zval_null__(zval *zv) { ZVAL_NULL(zv); }
|
||||
|
||||
void __zval_bool__(zval *zv, bool val) { ZVAL_BOOL(zv, val); }
|
||||
|
||||
void __zval_long__(zval *zv, zend_long val) { ZVAL_LONG(zv, val); }
|
||||
|
||||
void __zval_double__(zval *zv, double val) { ZVAL_DOUBLE(zv, val); }
|
||||
|
||||
void __zval_string__(zval *zv, zend_string *str) { ZVAL_STR(zv, str); }
|
||||
|
||||
void __zval_arr__(zval *zv, zend_array *arr) { ZVAL_ARR(zv, arr); }
|
||||
|
||||
zend_array *__zend_new_array__(uint32_t size) { return zend_new_array(size); }
|
||||
|
44
types.go
44
types.go
@@ -179,8 +179,9 @@ func PHPArray(arr *Array) unsafe.Pointer {
|
||||
zval := convertGoToZval(arr.values[i])
|
||||
|
||||
if k.Type == PHPStringKey {
|
||||
keyStr := PHPString(k.Str, false)
|
||||
C.zend_hash_update(zendArray, (*C.zend_string)(keyStr), zval)
|
||||
keyStr := k.Str
|
||||
keyData := (*C.char)(unsafe.Pointer(unsafe.StringData(keyStr)))
|
||||
C.zend_hash_str_add(zendArray, keyData, C.size_t(len(keyStr)), zval)
|
||||
|
||||
continue
|
||||
}
|
||||
@@ -229,47 +230,36 @@ func convertZvalToGo(zval *C.zval) interface{} {
|
||||
|
||||
// convertGoToZval converts a Go interface{} to a PHP zval
|
||||
func convertGoToZval(value interface{}) *C.zval {
|
||||
zval := (*C.zval)(C.__emalloc__(C.size_t(unsafe.Sizeof(C.zval{}))))
|
||||
u1 := (*C.uint8_t)(unsafe.Pointer(&zval.u1[0]))
|
||||
v0 := unsafe.Pointer(&zval.value[0])
|
||||
var zval C.zval
|
||||
|
||||
switch v := value.(type) {
|
||||
case nil:
|
||||
*u1 = C.IS_NULL
|
||||
C.__zval_null__(&zval)
|
||||
case bool:
|
||||
if v {
|
||||
*u1 = C.IS_TRUE
|
||||
} else {
|
||||
*u1 = C.IS_FALSE
|
||||
}
|
||||
C.__zval_bool__(&zval, C._Bool(v))
|
||||
case int:
|
||||
*u1 = C.IS_LONG
|
||||
*(*C.zend_long)(v0) = C.zend_long(v)
|
||||
C.__zval_long__(&zval, C.zend_long(v))
|
||||
case int64:
|
||||
*u1 = C.IS_LONG
|
||||
*(*C.zend_long)(v0) = C.zend_long(v)
|
||||
C.__zval_long__(&zval, C.zend_long(v))
|
||||
case float64:
|
||||
*u1 = C.IS_DOUBLE
|
||||
*(*C.double)(v0) = C.double(v)
|
||||
C.__zval_double__(&zval, C.double(v))
|
||||
case string:
|
||||
*u1 = C.IS_STRING
|
||||
*(**C.zend_string)(v0) = (*C.zend_string)(PHPString(v, false))
|
||||
str := (*C.zend_string)(PHPString(v, false))
|
||||
C.__zval_string__(&zval, str)
|
||||
case *Array:
|
||||
*u1 = C.IS_ARRAY
|
||||
*(**C.zend_array)(v0) = (*C.zend_array)(PHPArray(v))
|
||||
arr := (*C.zend_array)(PHPArray(v))
|
||||
C.__zval_arr__(&zval, arr)
|
||||
default:
|
||||
*u1 = C.IS_NULL
|
||||
C.__zval_null__(&zval)
|
||||
}
|
||||
|
||||
return zval
|
||||
return &zval
|
||||
}
|
||||
|
||||
// createNewArray creates a new zend_array with the specified size.
|
||||
func createNewArray(size uint32) *C.HashTable {
|
||||
ht := C.__emalloc__(C.size_t(unsafe.Sizeof(C.HashTable{})))
|
||||
C.__zend_hash_init__((*C.struct__zend_array)(ht), C.uint32_t(size), nil, C._Bool(false))
|
||||
|
||||
return (*C.HashTable)(ht)
|
||||
arr := C.__zend_new_array__(C.uint32_t(size))
|
||||
return (*C.HashTable)(unsafe.Pointer(arr))
|
||||
}
|
||||
|
||||
// htIsPacked checks if a HashTable is a list (packed) or hashmap (not packed).
|
||||
|
8
types.h
8
types.h
@@ -14,4 +14,12 @@ void *__emalloc__(size_t size);
|
||||
void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor,
|
||||
bool persistent);
|
||||
|
||||
void __zval_null__(zval *zv);
|
||||
void __zval_bool__(zval *zv, bool val);
|
||||
void __zval_long__(zval *zv, zend_long val);
|
||||
void __zval_double__(zval *zv, double val);
|
||||
void __zval_string__(zval *zv, zend_string *str);
|
||||
void __zval_arr__(zval *zv, zend_array *arr);
|
||||
zend_array *__zend_new_array__(uint32_t size);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user