Skip to content

Commit a1940a1

Browse files
alexandre-dauboishenderkes
authored andcommitted
fix(types): better zval handling to avoid leaks with arrays (php#1780)
1 parent 13fc911 commit a1940a1

File tree

3 files changed

+39
-27
lines changed

3 files changed

+39
-27
lines changed

types.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@ void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor,
2020
bool persistent) {
2121
zend_hash_init(ht, nSize, NULL, pDestructor, persistent);
2222
}
23+
24+
void __zval_null__(zval *zv) { ZVAL_NULL(zv); }
25+
26+
void __zval_bool__(zval *zv, bool val) { ZVAL_BOOL(zv, val); }
27+
28+
void __zval_long__(zval *zv, zend_long val) { ZVAL_LONG(zv, val); }
29+
30+
void __zval_double__(zval *zv, double val) { ZVAL_DOUBLE(zv, val); }
31+
32+
void __zval_string__(zval *zv, zend_string *str) { ZVAL_STR(zv, str); }
33+
34+
void __zval_arr__(zval *zv, zend_array *arr) { ZVAL_ARR(zv, arr); }
35+
36+
zend_array *__zend_new_array__(uint32_t size) { return zend_new_array(size); }

types.go

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ func PHPArray(arr *Array) unsafe.Pointer {
179179
zval := convertGoToZval(arr.values[i])
180180

181181
if k.Type == PHPStringKey {
182-
keyStr := PHPString(k.Str, false)
183-
C.zend_hash_update(zendArray, (*C.zend_string)(keyStr), zval)
182+
keyStr := k.Str
183+
keyData := (*C.char)(unsafe.Pointer(unsafe.StringData(keyStr)))
184+
C.zend_hash_str_add(zendArray, keyData, C.size_t(len(keyStr)), zval)
184185

185186
continue
186187
}
@@ -229,47 +230,36 @@ func convertZvalToGo(zval *C.zval) interface{} {
229230

230231
// convertGoToZval converts a Go interface{} to a PHP zval
231232
func convertGoToZval(value interface{}) *C.zval {
232-
zval := (*C.zval)(C.__emalloc__(C.size_t(unsafe.Sizeof(C.zval{}))))
233-
u1 := (*C.uint8_t)(unsafe.Pointer(&zval.u1[0]))
234-
v0 := unsafe.Pointer(&zval.value[0])
233+
var zval C.zval
235234

236235
switch v := value.(type) {
237236
case nil:
238-
*u1 = C.IS_NULL
237+
C.__zval_null__(&zval)
239238
case bool:
240-
if v {
241-
*u1 = C.IS_TRUE
242-
} else {
243-
*u1 = C.IS_FALSE
244-
}
239+
C.__zval_bool__(&zval, C._Bool(v))
245240
case int:
246-
*u1 = C.IS_LONG
247-
*(*C.zend_long)(v0) = C.zend_long(v)
241+
C.__zval_long__(&zval, C.zend_long(v))
248242
case int64:
249-
*u1 = C.IS_LONG
250-
*(*C.zend_long)(v0) = C.zend_long(v)
243+
C.__zval_long__(&zval, C.zend_long(v))
251244
case float64:
252-
*u1 = C.IS_DOUBLE
253-
*(*C.double)(v0) = C.double(v)
245+
C.__zval_double__(&zval, C.double(v))
254246
case string:
255-
*u1 = C.IS_STRING
256-
*(**C.zend_string)(v0) = (*C.zend_string)(PHPString(v, false))
247+
str := (*C.zend_string)(PHPString(v, false))
248+
C.__zval_string__(&zval, str)
257249
case *Array:
258-
*u1 = C.IS_ARRAY
259-
*(**C.zend_array)(v0) = (*C.zend_array)(PHPArray(v))
250+
arr := (*C.zend_array)(PHPArray(v))
251+
C.__zval_arr__(&zval, arr)
260252
default:
261-
*u1 = C.IS_NULL
253+
C.__zval_null__(&zval)
262254
}
263255

264-
return zval
256+
return &zval
265257
}
266258

267259
// createNewArray creates a new zend_array with the specified size.
268260
func createNewArray(size uint32) *C.HashTable {
269-
ht := C.__emalloc__(C.size_t(unsafe.Sizeof(C.HashTable{})))
270-
C.__zend_hash_init__((*C.struct__zend_array)(ht), C.uint32_t(size), nil, C._Bool(false))
271-
272-
return (*C.HashTable)(ht)
261+
arr := C.__zend_new_array__(C.uint32_t(size))
262+
return (*C.HashTable)(unsafe.Pointer(arr))
273263
}
274264

275265
// htIsPacked checks if a HashTable is a list (packed) or hashmap (not packed).

types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,12 @@ void *__emalloc__(size_t size);
1414
void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor,
1515
bool persistent);
1616

17+
void __zval_null__(zval *zv);
18+
void __zval_bool__(zval *zv, bool val);
19+
void __zval_long__(zval *zv, zend_long val);
20+
void __zval_double__(zval *zv, double val);
21+
void __zval_string__(zval *zv, zend_string *str);
22+
void __zval_arr__(zval *zv, zend_array *arr);
23+
zend_array *__zend_new_array__(uint32_t size);
24+
1725
#endif

0 commit comments

Comments
 (0)