diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 06a79d250a633..2000e15c29ea1 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4958,85 +4958,85 @@ ZEND_METHOD(FFI_CType, getFuncParameterType) /* {{{ */ } /* }}} */ +static char *zend_ffi_skip_ws_and_comments(char *p, bool allow_standalone_newline) +{ + while (true) { + if (*p == ' ' || *p == '\t') { + p++; + } else if (allow_standalone_newline && (*p == '\r' || *p == '\n' || *p == '\f' || *p == '\v')) { + p++; + } else if (allow_standalone_newline && *p == '/' && p[1] == '/') { + p += 2; + while (*p && *p != '\r' && *p != '\n') { + p++; + } + } else if (*p == '/' && p[1] == '*') { + p += 2; + while (*p && (*p != '*' || p[1] != '/')) { + p++; + } + if (*p == '*') { + p++; + if (*p == '/') { + p++; + } + } + } else { + break; + } + } + + return p; +} + static char *zend_ffi_parse_directives(const char *filename, char *code_pos, char **scope_name, char **lib, bool preload) /* {{{ */ { char *p; + code_pos = zend_ffi_skip_ws_and_comments(code_pos, true); + *scope_name = NULL; *lib = NULL; while (*code_pos == '#') { - if (strncmp(code_pos, "#define FFI_SCOPE", sizeof("#define FFI_SCOPE") - 1) == 0 - && (code_pos[sizeof("#define FFI_SCOPE") - 1] == ' ' - || code_pos[sizeof("#define FFI_SCOPE") - 1] == '\t')) { - p = code_pos + sizeof("#define FFI_SCOPE"); - while (*p == ' ' || *p == '\t') { - p++; - } - if (*p != '"') { - if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_SCOPE define", filename); - } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_SCOPE define", filename); - } - return NULL; - } - p++; - if (*scope_name) { - if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', FFI_SCOPE defined twice", filename); - } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', FFI_SCOPE defined twice", filename); - } - return NULL; - } - *scope_name = p; - while (1) { - if (*p == '\"') { - *p = 0; + if (strncmp(code_pos, ZEND_STRL("#define")) == 0) { + p = zend_ffi_skip_ws_and_comments(code_pos + sizeof("#define") - 1, false); + + char **target = NULL; + const char *target_name = NULL; + if (strncmp(p, ZEND_STRL("FFI_SCOPE")) == 0) { + p = zend_ffi_skip_ws_and_comments(p + sizeof("FFI_SCOPE") - 1, false); + target = scope_name; + target_name = "FFI_SCOPE"; + } else if (strncmp(p, ZEND_STRL("FFI_LIB")) == 0) { + p = zend_ffi_skip_ws_and_comments(p + sizeof("FFI_LIB") - 1, false); + target = lib; + target_name = "FFI_LIB"; + } else { + while (*p && *p != '\n' && *p != '\r') { p++; - break; - } else if (*p <= ' ') { - if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_SCOPE define", filename); - } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_SCOPE define", filename); - } - return NULL; } - p++; - } - while (*p == ' ' || *p == '\t') { - p++; - } - while (*p == '\r' || *p == '\n') { - p++; - } - code_pos = p; - } else if (strncmp(code_pos, "#define FFI_LIB", sizeof("#define FFI_LIB") - 1) == 0 - && (code_pos[sizeof("#define FFI_LIB") - 1] == ' ' - || code_pos[sizeof("#define FFI_LIB") - 1] == '\t')) { - p = code_pos + sizeof("#define FFI_LIB"); - while (*p == ' ' || *p == '\t') { - p++; + code_pos = zend_ffi_skip_ws_and_comments(p, true); + continue; } + if (*p != '"') { if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_LIB define", filename); + zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad %s define", filename, target_name); } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_LIB define", filename); + zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad %s define", filename, target_name); } return NULL; } p++; - if (*lib) { + if (*target) { if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', FFI_LIB defined twice", filename); + zend_error(E_WARNING, "FFI: failed pre-loading '%s', %s defined twice", filename, target_name); } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', FFI_LIB defined twice", filename); + zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', %s defined twice", filename, target_name); } return NULL; } - *lib = p; + *target = p; while (1) { if (*p == '\"') { *p = 0; @@ -5044,21 +5044,16 @@ static char *zend_ffi_parse_directives(const char *filename, char *code_pos, cha break; } else if (*p <= ' ') { if (preload) { - zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad FFI_LIB define", filename); + zend_error(E_WARNING, "FFI: failed pre-loading '%s', bad %s define", filename, target_name); } else { - zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad FFI_LIB define", filename); + zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', bad %s define", filename, target_name); } return NULL; } p++; } - while (*p == ' ' || *p == '\t') { - p++; - } - while (*p == '\r' || *p == '\n') { - p++; - } - code_pos = p; + + code_pos = zend_ffi_skip_ws_and_comments(p, true); } else { break; } diff --git a/ext/ffi/tests/bug79075.h b/ext/ffi/tests/bug79075.h new file mode 100644 index 0000000000000..22fa6067a347a --- /dev/null +++ b/ext/ffi/tests/bug79075.h @@ -0,0 +1,12 @@ +/* + * Multiline comment + */ + // whitespace line + +#define ignore_this_line 1 + // +#define/* inline */FFI_SCOPE /* multi- +line */ "bug79075" /* end +*/ + +int printf(const char *format, ...); diff --git a/ext/ffi/tests/bug79075.inc b/ext/ffi/tests/bug79075.inc new file mode 100644 index 0000000000000..ab3daa93d4de3 --- /dev/null +++ b/ext/ffi/tests/bug79075.inc @@ -0,0 +1,3 @@ + +--INI-- +ffi.enable=1 +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/bug79075.inc +opcache.file_cache_only=0 +--FILE-- +printf("Hello World from %s!\n", "PHP"); +?> +--EXPECT-- +Hello World from PHP!