Skip to content

Commit b2963e9

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix phpGH-14286 (ffi enum type (when enum has no name) make memory leak)
2 parents 0338e8d + c0de721 commit b2963e9

File tree

7 files changed

+85
-2
lines changed

7 files changed

+85
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ PHP NEWS
1313
. Fixed case when curl_error returns an empty string.
1414
(David Carlier)
1515

16+
- FFI:
17+
. Fixed bug GH-14286 (ffi enum type (when enum has no name) make memory
18+
leak). (nielsdos, dstogov)
19+
1620
- Soap:
1721
. Fixed bug #55639 (Digest autentication dont work). (nielsdos)
1822

ext/ffi/ffi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3582,7 +3582,7 @@ ZEND_METHOD(FFI, scope) /* {{{ */
35823582
}
35833583
/* }}} */
35843584

3585-
static void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl) /* {{{ */
3585+
void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl) /* {{{ */
35863586
{
35873587
if (dcl) {
35883588
zend_ffi_type_dtor(dcl->type);

ext/ffi/ffi.g

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ declarations:
9797
initializer?
9898
{zend_ffi_declare(name, name_len, &dcl);}
9999
)*
100-
)?
100+
|
101+
/* empty */
102+
{if (common_dcl.flags & (ZEND_FFI_DCL_ENUM | ZEND_FFI_DCL_STRUCT | ZEND_FFI_DCL_UNION)) zend_ffi_cleanup_dcl(&common_dcl);}
103+
)
101104
";"
102105
)*
103106
;

ext/ffi/ffi_parser.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,10 @@ static int parse_declarations(int sym) {
21152115
}
21162116
zend_ffi_declare(name, name_len, &dcl);
21172117
}
2118+
} else if (sym == YY__SEMICOLON) {
2119+
if (common_dcl.flags & (ZEND_FFI_DCL_ENUM | ZEND_FFI_DCL_STRUCT | ZEND_FFI_DCL_UNION)) zend_ffi_cleanup_dcl(&common_dcl);
2120+
} else {
2121+
yy_error_sym("unexpected", sym);
21182122
}
21192123
if (sym != YY__SEMICOLON) {
21202124
yy_error_sym("';' expected, got", sym);

ext/ffi/php_ffi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ typedef struct _zend_ffi_val {
208208

209209
zend_result zend_ffi_parse_decl(const char *str, size_t len);
210210
zend_result zend_ffi_parse_type(const char *str, size_t len, zend_ffi_dcl *dcl);
211+
void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl);
211212

212213
/* parser callbacks */
213214
void ZEND_NORETURN zend_ffi_parser_error(const char *msg, ...);

ext/ffi/tests/gh14286_1.phpt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
GH-14286 (ffi enum type (when enum has no name) make memory leak)
3+
--EXTENSIONS--
4+
ffi
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$ffi = FFI::cdef("
10+
enum {
11+
TEST_ONE=1,
12+
TEST_TWO=2,
13+
};
14+
enum TestEnum {
15+
TEST_THREE=3,
16+
};
17+
struct TestStruct {
18+
enum {
19+
TEST_FOUR=4,
20+
} test1;
21+
enum TestEnum2 {
22+
TEST_FIVE=5,
23+
} test2;
24+
};
25+
typedef enum { TEST_SIX=6 } TestEnum3;
26+
struct {
27+
int x;
28+
};
29+
union {
30+
int x;
31+
};
32+
");
33+
var_dump($ffi->TEST_ONE);
34+
var_dump($ffi->TEST_TWO);
35+
var_dump($ffi->TEST_THREE);
36+
var_dump($ffi->TEST_FOUR);
37+
var_dump($ffi->TEST_FIVE);
38+
var_dump($ffi->TEST_SIX);
39+
?>
40+
--EXPECT--
41+
int(1)
42+
int(2)
43+
int(3)
44+
int(4)
45+
int(5)
46+
int(6)

ext/ffi/tests/gh14286_2.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-14286 (ffi enum type (when enum has no name) make memory leak)
3+
--EXTENSIONS--
4+
ffi
5+
--SKIPIF--
6+
<?php
7+
if (PHP_DEBUG || getenv('SKIP_ASAN')) die("xfail: FFI cleanup after parser error is nor implemented");
8+
?>
9+
--INI--
10+
ffi.enable=1
11+
--FILE--
12+
<?php
13+
try {
14+
$ffi = FFI::cdef("
15+
enum {
16+
TEST_ONE=1,
17+
TEST_TWO=2,
18+
} x;
19+
");
20+
} catch (Throwable $e) {
21+
echo $e->getMessage(), "\n";
22+
}
23+
?>
24+
--EXPECT--
25+
Failed resolving C variable 'x'

0 commit comments

Comments
 (0)