Skip to content

Commit 6b7d122

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix bug #79075: FFI header parser chokes on comments
2 parents b81bddd + 226a0c5 commit 6b7d122

File tree

4 files changed

+101
-66
lines changed

4 files changed

+101
-66
lines changed

ext/ffi/ffi.c

Lines changed: 61 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4995,107 +4995,102 @@ ZEND_METHOD(FFI_CType, getFuncParameterType) /* {{{ */
49954995
}
49964996
/* }}} */
49974997

4998+
static char *zend_ffi_skip_ws_and_comments(char *p, bool allow_standalone_newline)
4999+
{
5000+
while (true) {
5001+
if (*p == ' ' || *p == '\t') {
5002+
p++;
5003+
} else if (allow_standalone_newline && (*p == '\r' || *p == '\n' || *p == '\f' || *p == '\v')) {
5004+
p++;
5005+
} else if (allow_standalone_newline && *p == '/' && p[1] == '/') {
5006+
p += 2;
5007+
while (*p && *p != '\r' && *p != '\n') {
5008+
p++;
5009+
}
5010+
} else if (*p == '/' && p[1] == '*') {
5011+
p += 2;
5012+
while (*p && (*p != '*' || p[1] != '/')) {
5013+
p++;
5014+
}
5015+
if (*p == '*') {
5016+
p++;
5017+
if (*p == '/') {
5018+
p++;
5019+
}
5020+
}
5021+
} else {
5022+
break;
5023+
}
5024+
}
5025+
5026+
return p;
5027+
}
5028+
49985029
static char *zend_ffi_parse_directives(const char *filename, char *code_pos, char **scope_name, char **lib, bool preload) /* {{{ */
49995030
{
50005031
char *p;
50015032

5033+
code_pos = zend_ffi_skip_ws_and_comments(code_pos, true);
5034+
50025035
*scope_name = NULL;
50035036
*lib = NULL;
50045037
while (*code_pos == '#') {
5005-
if (strncmp(code_pos, "#define FFI_SCOPE", sizeof("#define FFI_SCOPE") - 1) == 0
5006-
&& (code_pos[sizeof("#define FFI_SCOPE") - 1] == ' '
5007-
|| code_pos[sizeof("#define FFI_SCOPE") - 1] == '\t')) {
5008-
p = code_pos + sizeof("#define FFI_SCOPE");
5009-
while (*p == ' ' || *p == '\t') {
5010-
p++;
5011-
}
5012-
if (*p != '"') {
5013-
if (preload) {
5014-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_SCOPE define", filename);
5015-
} else {
5016-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_SCOPE define", filename);
5017-
}
5018-
return NULL;
5019-
}
5020-
p++;
5021-
if (*scope_name) {
5022-
if (preload) {
5023-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', FFI_SCOPE defined twice", filename);
5024-
} else {
5025-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', FFI_SCOPE defined twice", filename);
5026-
}
5027-
return NULL;
5028-
}
5029-
*scope_name = p;
5030-
while (1) {
5031-
if (*p == '\"') {
5032-
*p = 0;
5038+
if (strncmp(code_pos, ZEND_STRL("#define")) == 0) {
5039+
p = zend_ffi_skip_ws_and_comments(code_pos + sizeof("#define") - 1, false);
5040+
5041+
char **target = NULL;
5042+
const char *target_name = NULL;
5043+
if (strncmp(p, ZEND_STRL("FFI_SCOPE")) == 0) {
5044+
p = zend_ffi_skip_ws_and_comments(p + sizeof("FFI_SCOPE") - 1, false);
5045+
target = scope_name;
5046+
target_name = "FFI_SCOPE";
5047+
} else if (strncmp(p, ZEND_STRL("FFI_LIB")) == 0) {
5048+
p = zend_ffi_skip_ws_and_comments(p + sizeof("FFI_LIB") - 1, false);
5049+
target = lib;
5050+
target_name = "FFI_LIB";
5051+
} else {
5052+
while (*p && *p != '\n' && *p != '\r') {
50335053
p++;
5034-
break;
5035-
} else if (*p <= ' ') {
5036-
if (preload) {
5037-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_SCOPE define", filename);
5038-
} else {
5039-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_SCOPE define", filename);
5040-
}
5041-
return NULL;
50425054
}
5043-
p++;
5044-
}
5045-
while (*p == ' ' || *p == '\t') {
5046-
p++;
5047-
}
5048-
while (*p == '\r' || *p == '\n') {
5049-
p++;
5050-
}
5051-
code_pos = p;
5052-
} else if (strncmp(code_pos, "#define FFI_LIB", sizeof("#define FFI_LIB") - 1) == 0
5053-
&& (code_pos[sizeof("#define FFI_LIB") - 1] == ' '
5054-
|| code_pos[sizeof("#define FFI_LIB") - 1] == '\t')) {
5055-
p = code_pos + sizeof("#define FFI_LIB");
5056-
while (*p == ' ' || *p == '\t') {
5057-
p++;
5055+
code_pos = zend_ffi_skip_ws_and_comments(p, true);
5056+
continue;
50585057
}
5058+
50595059
if (*p != '"') {
50605060
if (preload) {
5061-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_LIB define", filename);
5061+
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad %s define", filename, target_name);
50625062
} else {
5063-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_LIB define", filename);
5063+
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad %s define", filename, target_name);
50645064
}
50655065
return NULL;
50665066
}
50675067
p++;
5068-
if (*lib) {
5068+
if (*target) {
50695069
if (preload) {
5070-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', FFI_LIB defined twice", filename);
5070+
zend_error(E_WARNING, "FFI: failed pre-loading '%s', %s defined twice", filename, target_name);
50715071
} else {
5072-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', FFI_LIB defined twice", filename);
5072+
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', %s defined twice", filename, target_name);
50735073
}
50745074
return NULL;
50755075
}
5076-
*lib = p;
5076+
*target = p;
50775077
while (1) {
50785078
if (*p == '\"') {
50795079
*p = 0;
50805080
p++;
50815081
break;
50825082
} else if (*p <= ' ') {
50835083
if (preload) {
5084-
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_LIB define", filename);
5084+
zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad %s define", filename, target_name);
50855085
} else {
5086-
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_LIB define", filename);
5086+
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad %s define", filename, target_name);
50875087
}
50885088
return NULL;
50895089
}
50905090
p++;
50915091
}
5092-
while (*p == ' ' || *p == '\t') {
5093-
p++;
5094-
}
5095-
while (*p == '\r' || *p == '\n') {
5096-
p++;
5097-
}
5098-
code_pos = p;
5092+
5093+
code_pos = zend_ffi_skip_ws_and_comments(p, true);
50995094
} else {
51005095
break;
51015096
}

ext/ffi/tests/bug79075.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Multiline comment
3+
*/
4+
// whitespace line
5+
6+
#define ignore_this_line 1
7+
//
8+
#define/* inline */FFI_SCOPE /* multi-
9+
line */ "bug79075" /* end
10+
*/
11+
12+
int printf(const char *format, ...);

ext/ffi/tests/bug79075.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
FFI::load(__DIR__ . "/bug79075.h");

ext/ffi/tests/bug79075.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #79075 (FFI header parser chokes on comments)
3+
--EXTENSIONS--
4+
ffi
5+
opcache
6+
posix
7+
--SKIPIF--
8+
<?php
9+
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip not for Windows');
10+
if (posix_geteuid() == 0) die('skip Cannot run test as root.');
11+
?>
12+
--INI--
13+
ffi.enable=1
14+
opcache.enable=1
15+
opcache.enable_cli=1
16+
opcache.optimization_level=-1
17+
opcache.preload={PWD}/bug79075.inc
18+
opcache.file_cache_only=0
19+
--FILE--
20+
<?php
21+
$ffi = FFI::scope("bug79075");
22+
$ffi->printf("Hello World from %s!\n", "PHP");
23+
?>
24+
--EXPECT--
25+
Hello World from PHP!

0 commit comments

Comments
 (0)