Skip to content

Instantly share code, notes, and snippets.

@ptarjan
Created March 26, 2014 06:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptarjan/9777593 to your computer and use it in GitHub Desktop.
Save ptarjan/9777593 to your computer and use it in GitHub Desktop.
From 810e4b11822df901a4a8169c0c26a6a29e1e92e5 Mon Sep 17 00:00:00 2001
From: Tim Starling <tstarling@wikimedia.org>
Date: Fri, 14 Mar 2014 09:33:52 +1100
Subject: [PATCH] EZC: Implement TSRM globals
Summary:
* Implement TSRM globals properly, i.e. have different globals for
different threads.
* Enable the ZTS macro. This is generally used by Zend extensions to
know if they need to be thread-safe, so for HHVM best answer is yes,
please do be thread-safe.
* Move ZendExtension to a separate header file, plus another for inline
functions, to allow circular declarations. Having it in zend_modules.h
didn't fit the recommended coding style in README.md.
* Implement functions in zend_virtual_cwd.cpp which are now used due to
ZTS being defined. This is necessary to link the new version, and fixes
some bugs due to HHVM's virtual CWD system not previously being used.
* Move zend_wrap_func() to the .cpp file so that TSRM.h can be included
without giving duplicate macro definitions throughout the non-EZC
codebase.
* Tested VCWD_REALPATH() by adding a wrapper ezc_realpath(), which has
exactly the implementation of realpath() from PHP PHP. Copied in the
realpath() tests, replacing realpath() with ezc_realpath().
* expand_filepath_with_mode() was naively copied from Zend and had a few
problems with it. Reimplemented.
The major implementation difficulty is ensuring that the existing
macros can transmit relevant data to the implementation, and ensuring
that the extern macro does actually give access to the globals. I would
have liked to put each module's globals in its own __thread variable,
but there was no way to supply the name of it to the constructor's
caller. Obviously you can't take the address of a __thread variable in
the zend_module_entry static initializer.
The implementation here is quite close to the Zend implementation,
except with an HPHP::ThreadLocal used for underlying storage. TSRMLS_CC
etc. is used as it is in Zend ZTS mode, and should provide a slight
speedup over TLS, especially with dynamic linking.
Closes #2063
Github Author: Tim Starling <tstarling@wikimedia.org>
Facebook: Made by hphp/tools/facebook/pull.php from https://github.com/facebook/hhvm/pull/2063
Test Plan: author tested, contbuild, flib
Reviewers: fredemmott, sgolemon
CC: dmitrys, smith, ps, hphp-diffs@lists
Differential Revision: https://phabricator.fb.com/D1240880
---
hphp/runtime/TARGETS | 1 -
hphp/runtime/ext_hhvm/ext_zend_compat.cpp | 50 -----
hphp/runtime/ext_zend_compat/TARGETS | 2 +
hphp/runtime/ext_zend_compat/ezc_test/ezc_test.cpp | 42 ++++-
hphp/runtime/ext_zend_compat/hhvm/TARGETS | 1 +
.../ext_zend_compat/hhvm/ZendObjectData.cpp | 5 +-
.../ext_zend_compat/hhvm/zend-extension-inline.h | 65 +++++++
.../ext_zend_compat/hhvm/zend-extension.cpp | 1 +
hphp/runtime/ext_zend_compat/hhvm/zend-extension.h | 22 +++
.../hhvm/zend-wrap-func.cpp} | 73 ++++----
hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h | 69 +++++++
hphp/runtime/ext_zend_compat/mongo/io_stream.cpp | 2 +-
hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.cpp | 126 +++++++++++++
hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h | 58 +++++-
hphp/runtime/ext_zend_compat/php-src/Zend/zend.cpp | 1 +
.../ext_zend_compat/php-src/Zend/zend_API.cpp | 4 +-
.../ext_zend_compat/php-src/Zend/zend_API.h | 3 +-
.../ext_zend_compat/php-src/Zend/zend_hash.cpp | 6 +-
.../ext_zend_compat/php-src/Zend/zend_ini.cpp | 3 +-
.../ext_zend_compat/php-src/Zend/zend_list.cpp | 8 +-
.../ext_zend_compat/php-src/Zend/zend_modules.h | 44 +----
.../php-src/Zend/zend_objects_API.cpp | 2 +-
.../php-src/Zend/zend_virtual_cwd.cpp | 208 +++++++++++++++++++++
.../php-src/ext/standard/basic_functions.cpp | 49 +++++
.../ext_zend_compat/php-src/ext/standard/lcg.cpp | 17 ++
.../php-src/main/fopen_wrappers.cpp | 71 ++-----
hphp/runtime/ext_zend_compat/php-src/main/main.cpp | 2 +-
.../ext_zend_compat/php-src/main/php_config.h | 4 +-
.../ext_zend_compat/php-src/main/php_globals.cpp | 2 +-
hphp/system/idl/ezc_test.idl.json | 18 +-
hphp/test/slow/ext_ezc_test/realpath_basic2.php | 7 +
.../slow/ext_ezc_test/realpath_basic2.php.expectf | 2 +
.../slow/ext_ezc_test/realpath_basic2.php.skipif | 1 +
hphp/test/slow/ext_ezc_test/realpath_basic3.php | 56 ++++++
.../slow/ext_ezc_test/realpath_basic3.php.expectf | 25 +++
.../slow/ext_ezc_test/realpath_basic3.php.skipif | 1 +
.../test/slow/ext_ezc_test/realpath_variation2.php | 28 +++
.../ext_ezc_test/realpath_variation2.php.expectf | 35 ++++
.../ext_ezc_test/realpath_variation2.php.skipif | 1 +
hphp/tools/bootstrap/gen-infotabs.cpp | 4 +-
40 files changed, 907 insertions(+), 212 deletions(-)
delete mode 100644 hphp/runtime/ext_hhvm/ext_zend_compat.cpp
create mode 100644 hphp/runtime/ext_zend_compat/hhvm/zend-extension-inline.h
create mode 100644 hphp/runtime/ext_zend_compat/hhvm/zend-extension.h
rename hphp/runtime/{ext_hhvm/ext_zend_compat.h => ext_zend_compat/hhvm/zend-wrap-func.cpp} (65%)
create mode 100644 hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h
create mode 100644 hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.cpp
create mode 100644 hphp/runtime/ext_zend_compat/php-src/Zend/zend_virtual_cwd.cpp
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic2.php
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic2.php.expectf
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic2.php.skipif
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic3.php
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic3.php.expectf
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_basic3.php.skipif
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_variation2.php
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_variation2.php.expectf
create mode 100644 hphp/test/slow/ext_ezc_test/realpath_variation2.php.skipif
diff --git a/hphp/runtime/TARGETS b/hphp/runtime/TARGETS
index 40d806c..9844596 100644
--- a/hphp/runtime/TARGETS
+++ b/hphp/runtime/TARGETS
@@ -188,7 +188,6 @@ cpp_library(
'ext/filter/sanitizing_filters.cpp',
'ext/zip/ext_zip.cpp',
'ext/odbc/ext_odbc.cpp',
- 'ext_hhvm/ext_zend_compat.cpp',
'ext/fileinfo/ext_fileinfo.cpp',
'ext/fileinfo/libmagic/apprentice.cpp',
diff --git a/hphp/runtime/ext_hhvm/ext_zend_compat.cpp b/hphp/runtime/ext_hhvm/ext_zend_compat.cpp
deleted file mode 100644
index a8f65b0..0000000
--- a/hphp/runtime/ext_hhvm/ext_zend_compat.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | HipHop for PHP |
- +----------------------------------------------------------------------+
- | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
-*/
-
-#include "hphp/runtime/ext_hhvm/ext_zend_compat.h"
-#include <algorithm>
-#include "hphp/runtime/base/proxy-array.h"
-
-namespace HPHP {
-///////////////////////////////////////////////////////////////////////////////
-
-// TODO zPrepArgs needs to be updated so take care of
-// boxing varargs
-void zPrepArgs(ActRec* ar) {
- // If you call a function with too few params, zend_parse_parameters will
- // reject it, but we don't want this function boxing random slots from the
- // stack
- int32_t numArgs = std::min(ar->numArgs(), ar->m_func->numParams());
- TypedValue* args = (TypedValue*)ar - 1;
- for (int32_t i = 0; i < numArgs; ++i) {
- TypedValue* arg = args-i;
- zBoxAndProxy(arg);
- }
-}
-
-void zBoxAndProxy(TypedValue* arg) {
- if (arg->m_type != KindOfRef) {
- tvBox(arg);
- }
- auto inner = arg->m_data.pref->tv();
- if (inner->m_type == KindOfArray) {
- inner->m_data.parr = ProxyArray::Make(inner->m_data.parr);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-}
-
diff --git a/hphp/runtime/ext_zend_compat/TARGETS b/hphp/runtime/ext_zend_compat/TARGETS
index f2bd4ed..8cbabfb 100644
--- a/hphp/runtime/ext_zend_compat/TARGETS
+++ b/hphp/runtime/ext_zend_compat/TARGETS
@@ -18,6 +18,7 @@ cpp_library(
warp=True,
name='ext_zend_compat_lib',
srcs=[
+ 'php-src/TSRM/TSRM.cpp',
'php-src/TSRM/tsrm_virtual_cwd.cpp',
'php-src/Zend/zend.cpp',
'php-src/Zend/zend_API.cpp',
@@ -39,6 +40,7 @@ cpp_library(
'php-src/Zend/zend_qsort.cpp',
'php-src/Zend/zend_strtod.cpp',
'php-src/Zend/zend_variables.cpp',
+ 'php-src/Zend/zend_virtual_cwd.cpp',
'php-src/ext/pcre/php_pcre.cpp',
'php-src/ext/standard/base64.cpp',
'php-src/ext/standard/basic_functions.cpp',
diff --git a/hphp/runtime/ext_zend_compat/ezc_test/ezc_test.cpp b/hphp/runtime/ext_zend_compat/ezc_test/ezc_test.cpp
index 3afacfd..7402b13 100644
--- a/hphp/runtime/ext_zend_compat/ezc_test/ezc_test.cpp
+++ b/hphp/runtime/ext_zend_compat/ezc_test/ezc_test.cpp
@@ -205,13 +205,13 @@ PHP_FUNCTION(ezc_throw)
}
ce = zend_fetch_class_by_name(
- class_name, class_name_length, NULL, ZEND_FETCH_CLASS_SILENT);
+ class_name, class_name_length, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC);
if (!ce) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no such class \"%s\"",
class_name);
RETURN_FALSE;
}
- zend_throw_exception(ce, "ezc_throw", 0);
+ zend_throw_exception(ce, "ezc_throw", 0 TSRMLS_CC);
}
/* }}} */
@@ -239,6 +239,35 @@ PHP_FUNCTION(ezc_throw_nonstd)
}
/* }}} */
+/* {{{ proto ezc_realpath(string path)
+ * Return the resolved path
+ */
+PHP_FUNCTION(ezc_realpath)
+{
+ char *filename;
+ int filename_len;
+ char resolved_path_buff[MAXPATHLEN];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+ return;
+ }
+
+ if (VCWD_REALPATH(filename, resolved_path_buff)) {
+ if (php_check_open_basedir(resolved_path_buff TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+#ifdef ZTS
+ if (VCWD_ACCESS(resolved_path_buff, F_OK)) {
+ RETURN_FALSE;
+ }
+#endif
+ RETURN_STRING(resolved_path_buff, 1);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_ezc_fetch_global, 0)
ZEND_END_ARG_INFO()
@@ -269,6 +298,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_ezc_throw_nonstd, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_ezc_realpath, 0)
+ ZEND_ARG_INFO(0, path)
+ZEND_END_ARG_INFO()
+
/* }}} */
/* {{{ ezc_test_functions[]
@@ -279,8 +312,9 @@ const zend_function_entry ezc_test_functions[] = {
PHP_FE(ezc_call, arginfo_ezc_call)
PHP_FE(ezc_try_call, arginfo_ezc_try_call)
PHP_FE(ezc_throw, arginfo_ezc_throw)
- PHP_FE(ezc_throw, arginfo_ezc_throw_std)
- PHP_FE(ezc_throw, arginfo_ezc_throw_nonstd)
+ PHP_FE(ezc_throw_std, arginfo_ezc_throw_std)
+ PHP_FE(ezc_throw_nonstd, arginfo_ezc_throw_nonstd)
+ PHP_FE(ezc_realpath, arginfo_ezc_realpath)
PHP_FE_END
};
/* }}} */
diff --git a/hphp/runtime/ext_zend_compat/hhvm/TARGETS b/hphp/runtime/ext_zend_compat/hhvm/TARGETS
index 20237ea..468962cb 100644
--- a/hphp/runtime/ext_zend_compat/hhvm/TARGETS
+++ b/hphp/runtime/ext_zend_compat/hhvm/TARGETS
@@ -10,6 +10,7 @@ cpp_library(
'zend-class-entry.cpp',
'zend-property-info.cpp',
'zend-extension.cpp',
+ 'zend-wrap-func.cpp',
],
deps=[
'@/hphp/runtime:hphp_runtime',
diff --git a/hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.cpp b/hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.cpp
index 8a807bc..3e97b9b 100644
--- a/hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.cpp
+++ b/hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.cpp
@@ -32,6 +32,7 @@ c_ZendObjectData::c_ZendObjectData(Class* cls)
}
ObjectData* new_ZendObjectData_Instance(Class* cls) {
+ TSRMLS_FETCH();
size_t nProps = cls->numDeclProperties();
size_t builtinObjSize = sizeof(c_ZendObjectData) - sizeof(ObjectData);
size_t size = ObjectData::sizeForNProps(nProps) + builtinObjSize;
@@ -52,10 +53,10 @@ ObjectData* new_ZendObjectData_Instance(Class* cls) {
zend_object_value ov;
if (create_func) {
- ov = create_func(ce);
+ ov = create_func(ce TSRMLS_CC);
} else {
zend_object *object;
- ov = zend_objects_new(&object, ce);
+ ov = zend_objects_new(&object, ce TSRMLS_CC);
}
obj->setHandle(ov.handle);
diff --git a/hphp/runtime/ext_zend_compat/hhvm/zend-extension-inline.h b/hphp/runtime/ext_zend_compat/hhvm/zend-extension-inline.h
new file mode 100644
index 0000000..d045d5b
--- /dev/null
+++ b/hphp/runtime/ext_zend_compat/hhvm/zend-extension-inline.h
@@ -0,0 +1,65 @@
+#ifndef incl_ZEND_EXTENSION_INLINE_H_
+#define incl_ZEND_EXTENSION_INLINE_H_
+
+inline void ZendExtension::moduleInit() {
+ if (!HPHP::RuntimeOption::EnableZendCompat) {
+ return;
+ }
+ zend_module_entry* entry = getEntry();
+ if (entry->globals_size) {
+ ts_allocate_id(entry->globals_id_ptr, entry->globals_size,
+ (ts_allocate_ctor) entry->globals_ctor, (ts_allocate_dtor) entry->globals_dtor);
+ }
+ if (entry->module_startup_func) {
+ TSRMLS_FETCH();
+ entry->module_startup_func(1, entry->module_number TSRMLS_CC);
+ }
+}
+inline void ZendExtension::moduleShutdown() {
+ if (!HPHP::RuntimeOption::EnableZendCompat) {
+ return;
+ }
+ zend_module_entry* entry = getEntry();
+ if (entry->module_shutdown_func) {
+ TSRMLS_FETCH();
+ entry->module_shutdown_func(1, 1 TSRMLS_CC);
+ }
+}
+inline void ZendExtension::threadShutdown() {
+ if (!HPHP::RuntimeOption::EnableZendCompat) {
+ return;
+ }
+ zend_module_entry* entry = getEntry();
+ if (entry->globals_size) {
+ ts_free_id(*entry->globals_id_ptr);
+ }
+}
+inline void ZendExtension::requestInit() {
+ if (!HPHP::RuntimeOption::EnableZendCompat) {
+ return;
+ }
+ zend_module_entry* entry = getEntry();
+ if (entry->request_startup_func) {
+ TSRMLS_FETCH();
+ entry->request_startup_func(0, entry->module_number TSRMLS_CC);
+ }
+}
+inline void ZendExtension::requestShutdown() {
+ if (!HPHP::RuntimeOption::EnableZendCompat) {
+ return;
+ }
+ zend_module_entry* entry = getEntry();
+ if (entry->request_shutdown_func) {
+ TSRMLS_FETCH();
+ entry->request_shutdown_func(0, entry->module_number TSRMLS_CC);
+ }
+ // TODO: call these after all RSHUTDOWN functions from other modules have been called
+ if (entry->post_deactivate_func) {
+ entry->post_deactivate_func();
+ }
+}
+inline zend_module_entry *ZendExtension::getEntry() {
+ enum { offset = offsetof(struct _zend_module_entry, name) };
+ return (zend_module_entry*)(((char*)this) - offset);
+}
+#endif
diff --git a/hphp/runtime/ext_zend_compat/hhvm/zend-extension.cpp b/hphp/runtime/ext_zend_compat/hhvm/zend-extension.cpp
index 1aa11e3..1c52c11 100644
--- a/hphp/runtime/ext_zend_compat/hhvm/zend-extension.cpp
+++ b/hphp/runtime/ext_zend_compat/hhvm/zend-extension.cpp
@@ -15,6 +15,7 @@
+----------------------------------------------------------------------+
*/
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-extension.h"
#include "folly/AtomicHashMap.h"
#include "hphp/runtime/ext_zend_compat/php-src/Zend/zend_modules.h"
diff --git a/hphp/runtime/ext_zend_compat/hhvm/zend-extension.h b/hphp/runtime/ext_zend_compat/hhvm/zend-extension.h
new file mode 100644
index 0000000..ebf5916
--- /dev/null
+++ b/hphp/runtime/ext_zend_compat/hhvm/zend-extension.h
@@ -0,0 +1,22 @@
+#ifndef incl_ZEND_EXTENSION_H_
+#define incl_ZEND_EXTENSION_H_
+
+#include "hphp/runtime/ext/extension.h"
+
+typedef struct _zend_module_entry zend_module_entry;
+struct _zend_module_entry;
+
+class ZendExtension : public HPHP::Extension {
+private:
+ zend_module_entry *getEntry();
+public:
+ /* implicit */ ZendExtension(const char* name);
+ virtual void moduleInit() override;
+ virtual void moduleShutdown() override;
+ virtual void threadShutdown() override;
+ virtual void requestInit() override;
+ virtual void requestShutdown() override;
+ static ZendExtension* GetByModuleNumber(int module_number);
+};
+
+#endif
diff --git a/hphp/runtime/ext_hhvm/ext_zend_compat.h b/hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.cpp
similarity index 65%
rename from hphp/runtime/ext_hhvm/ext_zend_compat.h
rename to hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.cpp
index 9b91f53..337b6c5 100644
--- a/hphp/runtime/ext_hhvm/ext_zend_compat.h
+++ b/hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.cpp
@@ -14,54 +14,44 @@
+----------------------------------------------------------------------+
*/
-#ifndef incl_HPHP_EXT_ZEND_COMPAT_H_
-#define incl_HPHP_EXT_ZEND_COMPAT_H_
-
-#include "hphp/runtime/vm/bytecode.h"
-#include "hphp/runtime/vm/runtime.h"
-#include "hphp/runtime/base/macros.h"
-#include "hphp/runtime/base/execution-context.h"
-#include "hphp/runtime/base/ini-setting.h"
-#include "hphp/runtime/ext_zend_compat/hhvm/ZendExceptionStore.h"
-#include "hphp/runtime/ext_zend_compat/hhvm/ZendExecutionStack.h"
-#include "hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.h"
-#include "hphp/runtime/ext_zend_compat/hhvm/zval-helpers.h"
-
-// zend.h is way to big to include here
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h"
+#include <algorithm>
+#include "hphp/runtime/base/proxy-array.h"
+#include "hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
-class RefData;
-
-void zPrepArgs(ActRec* ar);
-
-typedef void (*zend_ext_func)(
- // The number of args passed to this function.
- // Usually accessed with ARG_COUNT() or ZEND_NUM_ARGS.
- int ht,
- // The return value. Written to with RETURN_* macros.
- RefData* return_value,
- // The same as the previous arg but a **. This is provided so that the callee
- // can set the caller's zval* to point to a different zval. This is needed if
- // a builtin function wants to return by reference.
- RefData** return_value_ptr,
- // The $this in the method. Accessed with getThis().
- RefData* this_ptr,
- // An optimization that extensions can use (but I haven't seen one use it
- // yet). If we can detect that the return value isn't used, we could pass in 0
- // here and the ext wouldn't set it.
- int return_value_used
-);
-
-void zBoxAndProxy(TypedValue* arg);
-void zBoxAndProxy(const TypedValue* arg);
-
-inline TypedValue* zend_wrap_func(
+// TODO zPrepArgs needs to be updated so take care of
+// boxing varargs
+void zPrepArgs(ActRec* ar) {
+ // If you call a function with too few params, zend_parse_parameters will
+ // reject it, but we don't want this function boxing random slots from the
+ // stack
+ int32_t numArgs = std::min(ar->numArgs(), ar->m_func->numParams());
+ TypedValue* args = (TypedValue*)ar - 1;
+ for (int32_t i = 0; i < numArgs; ++i) {
+ TypedValue* arg = args-i;
+ zBoxAndProxy(arg);
+ }
+}
+
+void zBoxAndProxy(TypedValue* arg) {
+ if (arg->m_type != KindOfRef) {
+ tvBox(arg);
+ }
+ auto inner = arg->m_data.pref->tv();
+ if (inner->m_type == KindOfArray) {
+ inner->m_data.parr = ProxyArray::Make(inner->m_data.parr);
+ }
+}
+
+TypedValue* zend_wrap_func(
ActRec* ar,
zend_ext_func builtin_func,
int numParams,
bool isReturnRef) {
+ TSRMLS_FETCH();
// Prepare the arguments and return value before they are
// exposed to the PHP extension
@@ -98,6 +88,7 @@ inline TypedValue* zend_wrap_func(
return_value_ptr,
this_ptr_var.isNull() ? nullptr : this_ptr->m_data.pref,
1
+ TSRMLS_CC
);
} catch (...) {
ZendExecutionStack::popHHVMStack();
@@ -126,7 +117,7 @@ inline TypedValue* zend_wrap_func(
return &ar->m_r;
}
+
///////////////////////////////////////////////////////////////////////////////
}
-#endif // incl_HPHP_EXT_ZEND_COMPAT_H_
diff --git a/hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h b/hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h
new file mode 100644
index 0000000..35739eb
--- /dev/null
+++ b/hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h
@@ -0,0 +1,69 @@
+/*
+ +----------------------------------------------------------------------+
+ | HipHop for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef incl_HPHP_EXT_ZEND_COMPAT_H_
+#define incl_HPHP_EXT_ZEND_COMPAT_H_
+
+#include "hphp/runtime/vm/bytecode.h"
+#include "hphp/runtime/vm/runtime.h"
+#include "hphp/runtime/base/macros.h"
+#include "hphp/runtime/base/execution-context.h"
+#include "hphp/runtime/base/ini-setting.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/ZendExceptionStore.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/ZendExecutionStack.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/ZendObjectData.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/zval-helpers.h"
+// zend.h is way to big to include here
+
+namespace HPHP {
+///////////////////////////////////////////////////////////////////////////////
+
+class RefData;
+
+void zPrepArgs(ActRec* ar);
+
+typedef void (*zend_ext_func)(
+ // The number of args passed to this function.
+ // Usually accessed with ARG_COUNT() or ZEND_NUM_ARGS.
+ int ht,
+ // The return value. Written to with RETURN_* macros.
+ RefData* return_value,
+ // The same as the previous arg but a **. This is provided so that the callee
+ // can set the caller's zval* to point to a different zval. This is needed if
+ // a builtin function wants to return by reference.
+ RefData** return_value_ptr,
+ // The $this in the method. Accessed with getThis().
+ RefData* this_ptr,
+ // An optimization that extensions can use (but I haven't seen one use it
+ // yet). If we can detect that the return value isn't used, we could pass in 0
+ // here and the ext wouldn't set it.
+ int return_value_used,
+ // TSRMLS_DC
+ void *** tsrm_ls
+);
+
+void zBoxAndProxy(TypedValue* arg);
+void zBoxAndProxy(const TypedValue* arg);
+TypedValue* zend_wrap_func(
+ ActRec* ar,
+ zend_ext_func builtin_func,
+ int numParams,
+ bool isReturnRef);
+
+///////////////////////////////////////////////////////////////////////////////
+}
+
+#endif // incl_HPHP_EXT_ZEND_COMPAT_H_
diff --git a/hphp/runtime/ext_zend_compat/mongo/io_stream.cpp b/hphp/runtime/ext_zend_compat/mongo/io_stream.cpp
index 7679e96..e0fb085 100644
--- a/hphp/runtime/ext_zend_compat/mongo/io_stream.cpp
+++ b/hphp/runtime/ext_zend_compat/mongo/io_stream.cpp
@@ -218,7 +218,7 @@ void php_mongo_io_stream_close(mongo_connection *con, int why)
void php_mongo_io_stream_forget(mongo_con_manager *manager, mongo_connection *con)
{
zend_rsrc_list_entry *le;
- TSRMLS_FETCH();
+ // TSRMLS_FETCH();
/* When we fork we need to unregister the parents hash so we don't
* accidentally destroy it */
diff --git a/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.cpp b/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.cpp
new file mode 100644
index 0000000..183aa27
--- /dev/null
+++ b/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.cpp
@@ -0,0 +1,126 @@
+/*
+ +----------------------------------------------------------------------+
+ | Thread Safe Resource Manager |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1999-2011, Andi Gutmans, Sascha Schumann, Zeev Suraski |
+ | This source file is subject to the TSRM license, that is bundled |
+ | with this package in the file LICENSE |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+#include <stdlib.h>
+#include <pthread.h>
+#include "TSRM.h"
+
+struct tsrm_resource_type {
+ tsrm_resource_type() {}
+
+ size_t size;
+ ts_allocate_ctor ctor;
+ ts_allocate_dtor dtor;
+ int done;
+};
+
+static std::vector<tsrm_resource_type> resource_types_table;
+
+HPHP::ThreadLocal<TSRMStorageVector> tsrm_thread_resources;
+
+#define TSRM_ERROR(args)
+
+TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
+{
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
+
+ /* obtain a resource id */
+ resource_types_table.resize(resource_types_table.size() + 1);
+ *rsrc_id = TSRM_SHUFFLE_RSRC_ID(resource_types_table.size() - 1);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
+
+ /* store the new resource type in the resource sizes table */
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
+
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
+ return *rsrc_id;
+}
+
+void * ts_init_resource(int id)
+{
+ assert(id != 0);
+ TSRMLS_FETCH();
+ TSRMStorageVector & vec = *tsrm_thread_resources;
+ if (vec.size() <= TSRM_UNSHUFFLE_RSRC_ID(id)) {
+ vec.resize(TSRM_UNSHUFFLE_RSRC_ID(id) + 1);
+ }
+ tsrm_resource_type & type = resource_types_table.at(TSRM_UNSHUFFLE_RSRC_ID(id));
+ if (vec[TSRM_UNSHUFFLE_RSRC_ID(id)] == nullptr) {
+ vec[TSRM_UNSHUFFLE_RSRC_ID(id)] = malloc(type.size);
+ if (type.ctor) {
+ type.ctor(vec[TSRM_UNSHUFFLE_RSRC_ID(id)] TSRMLS_CC);
+ }
+ }
+ return vec[TSRM_UNSHUFFLE_RSRC_ID(id)];
+}
+
+void ts_free_id(ts_rsrc_id id)
+{
+ TSRMStorageVector & vec = *tsrm_thread_resources;
+ int j = TSRM_UNSHUFFLE_RSRC_ID(id);
+ assert(id != 0);
+ TSRMLS_FETCH();
+ if (vec.size() <= j && vec[j] != nullptr) {
+ if (resource_types_table[j].dtor) {
+ resource_types_table[j].dtor(vec[j] TSRMLS_CC);
+ }
+ free(vec[j]);
+ }
+}
+
+// [HHVM] We implement a few utility functions here, using the same
+// implementation as in PHP, except with the non-pthread implementations
+// removed.
+
+/* Obtain the current thread id */
+TSRM_API THREAD_T tsrm_thread_id(void)
+{
+ return pthread_self();
+}
+
+/* Allocate a mutex */
+TSRM_API MUTEX_T tsrm_mutex_alloc(void)
+{
+ MUTEX_T mutexp;
+ mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(mutexp,NULL);
+ return( mutexp );
+}
+
+/* Free a mutex */
+TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
+{
+ if (mutexp) {
+ pthread_mutex_destroy(mutexp);
+ free(mutexp);
+ }
+}
+
+/*
+ Lock a mutex.
+ A return value of 0 indicates success
+*/
+TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
+{
+ return pthread_mutex_lock(mutexp);
+}
+
+/*
+ Unlock a mutex.
+ A return value of 0 indicates success
+*/
+TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
+{
+ return pthread_mutex_unlock(mutexp);
+}
diff --git a/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h b/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h
index c0e1423..1a30a99 100644
--- a/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h
+++ b/hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h
@@ -99,9 +99,11 @@ typedef void (*ts_allocate_dtor)(void *, void ***);
#define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
+#ifndef HHVM
#ifdef __cplusplus
extern "C" {
#endif
+#endif
/* startup/shutdown */
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename);
@@ -110,8 +112,49 @@ TSRM_API void tsrm_shutdown(void);
/* allocates a new thread-safe-resource id */
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
+#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
+#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
+
+#ifdef HHVM
+
+#include <vector>
+#include <string>
+#include <assert.h>
+#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
+# define TSRM_UNEXPECTED(condition) __builtin_expect(condition, 0)
+#else
+# define TSRM_UNEXPECTED(condition) (condition)
+#endif
+
+#include "hphp/util/thread-local.h"
+typedef std::vector<void*> TSRMStorageVector;
+extern HPHP::ThreadLocal<TSRMStorageVector> tsrm_thread_resources;
+void * ts_init_resource(int id);
+
+static inline void * ts_resource_from_vector(const TSRMStorageVector & vec, ts_rsrc_id id) {
+ void * ret;
+ assert(id != 0);
+ if (TSRM_UNEXPECTED(vec.size() <= TSRM_UNSHUFFLE_RSRC_ID(id))) {
+ return ts_init_resource(id);
+ } else {
+ ret = vec[TSRM_UNSHUFFLE_RSRC_ID(id)];
+ if (TSRM_UNEXPECTED(ret == nullptr)) {
+ return ts_init_resource(id);
+ } else {
+ return ret;
+ }
+ }
+}
+
+static inline void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id) {
+ assert(th_id == NULL); // unimplemented
+ return ts_resource_from_vector(*tsrm_thread_resources, id);
+}
+
+#else
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
+#endif
#define ts_resource(id) ts_resource_ex(id, NULL)
/* frees all resources allocated for the current thread */
@@ -155,21 +198,32 @@ TSRM_API void *tsrm_new_interpreter_context(void);
TSRM_API void *tsrm_set_interpreter_context(void *new_ctx);
TSRM_API void tsrm_free_interpreter_context(void *context);
-#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
-#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
+#ifdef HHVM
+
+#define TSRMLS_FETCH() void ***tsrm_ls = reinterpret_cast<void***>(tsrm_thread_resources.get())
+#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
+#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
+#define TSRMG(id, type, element) \
+ (static_cast<type>(ts_resource_from_vector(*reinterpret_cast<TSRMStorageVector*>(tsrm_ls), id))->element)
+#else /*non-HHVM*/
#define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)
#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
+
+#endif
+
#define TSRMLS_D void ***tsrm_ls
#define TSRMLS_DC , TSRMLS_D
#define TSRMLS_C tsrm_ls
#define TSRMLS_CC , TSRMLS_C
+#ifndef HHVM
#ifdef __cplusplus
}
#endif
+#endif
#else /* non ZTS */
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend.cpp
index ffbd660..b073774 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend.cpp
@@ -51,6 +51,7 @@ ZEND_API zend_class_entry *zend_standard_class_def = NULL;
/* This probably should be initialized somewhere, but I didn't find a suitable
* place so it's wrapped in a function for now */
zend_class_entry *get_zend_standard_class_def() {
+ TSRMLS_FETCH();
if (!zend_standard_class_def) {
zend_class_entry class_entry;
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.cpp
index 2b1ab91..d8890e8 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.cpp
@@ -1235,7 +1235,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) {
/* returns 1 if you need to copy result, 0 if it's already a copy */
ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC) {
- zend_class_entry* clazz = zend_get_class_entry(object);
+ zend_class_entry* clazz = zend_get_class_entry(object TSRMLS_CC);
auto* name = clazz->hphp_class->name();
*class_name_len = name->size();
*class_name = estrndup(name->data(), *class_name_len);
@@ -1567,7 +1567,7 @@ ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *na
}
ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) {
- auto ret = zend_register_internal_class(class_entry);
+ auto ret = zend_register_internal_class(class_entry TSRMLS_CC);
if (parent_ce) {
ret->create_object = parent_ce->create_object;
assert(ret->hphp_class->parent() == parent_ce->hphp_class);
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.h b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.h
index c607322..7afb2f6 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.h
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_API.h
@@ -577,8 +577,9 @@ END_EXTERN_C()
#ifdef HHVM
#define ZVAL_RESOURCE(z, l) do { \
+ TSRMLS_FETCH(); \
zval *__z = (z); \
- zval_follow_ref(*__z).m_data.pres = zend_list_id_to_resource_data(l); \
+ zval_follow_ref(*__z).m_data.pres = zend_list_id_to_resource_data(l TSRMLS_CC); \
Z_TYPE_P(__z) = IS_RESOURCE;\
} while (0)
#else
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_hash.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_hash.cpp
index c84697e..75851e7 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_hash.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_hash.cpp
@@ -25,7 +25,7 @@
#include "hphp/runtime/base/type-conversions.h"
#include "hphp/runtime/ext_zend_compat/php-src/Zend/zend_qsort.h"
#include "hphp/runtime/ext_zend_compat/hhvm/zval-helpers.h"
-#include "hphp/runtime/ext_hhvm/ext_zend_compat.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h"
#include "hphp/util/safesort.h"
#include "hphp/util/assertions.h"
@@ -70,7 +70,7 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void * arg TSRMLS_DC) {
for (HPHP::ArrayIter it(ht); it; ++it) {
zval* data = it.zSecond();
- int result = apply_func(&data, arg);
+ int result = apply_func(&data, arg TSRMLS_CC);
if (result & ZEND_HASH_APPLY_REMOVE) {
not_implemented();
@@ -99,7 +99,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
hash_key.h = 0;
}
zval* data = it.zSecond();
- result = apply_func(&data, num_args, args, &hash_key);
+ result = apply_func(&data TSRMLS_CC, num_args, args, &hash_key);
if (result & ZEND_HASH_APPLY_REMOVE) {
not_implemented();
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_ini.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_ini.cpp
index 09704d6..f90281f 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_ini.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_ini.cpp
@@ -40,11 +40,12 @@ ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int modu
while (p->name) {
auto updateCallback = [p](const std::string& value) -> bool {
+ TSRMLS_FETCH();
// TODO Who is supposed to free this?
char* data = estrndup(value.data(), value.size());
auto ret = p->on_modify(
const_cast<zend_ini_entry*>(p), data, value.size(),
- p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP
+ p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC
);
return ret;
};
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_list.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_list.cpp
index 3f13a8a..6debc44 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_list.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_list.cpp
@@ -75,7 +75,7 @@ ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC) {
}
ZEND_API int _zend_list_delete(int id TSRMLS_DC) {
- zend_rsrc_list_entry* le = zend_list_id_to_entry(id);
+ zend_rsrc_list_entry* le = zend_list_id_to_entry(id TSRMLS_CC);
if (le) {
int refcount = le->getCount();
decRefRes(le);
@@ -91,7 +91,7 @@ ZEND_API int _zend_list_delete(int id TSRMLS_DC) {
}
ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC) {
- zend_rsrc_list_entry* le = zend_list_id_to_entry(id);
+ zend_rsrc_list_entry* le = zend_list_id_to_entry(id TSRMLS_CC);
HPHP::ZendNormalResourceDataHolder* holder =
dynamic_cast<HPHP::ZendNormalResourceDataHolder*>(le);
if (holder) {
@@ -107,7 +107,7 @@ ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC) {
}
ZEND_API int _zend_list_addref(int id TSRMLS_DC) {
- zend_rsrc_list_entry* le = zend_list_id_to_entry(id);
+ zend_rsrc_list_entry* le = zend_list_id_to_entry(id TSRMLS_CC);
if (le) {
le->incRefCount();
return SUCCESS;
@@ -230,7 +230,7 @@ int zval_get_resource_id(const zval &z) {
}
HPHP::ResourceData *zend_list_id_to_resource_data(int id TSRMLS_DC) {
- zend_rsrc_list_entry* le = zend_list_id_to_entry(id);
+ zend_rsrc_list_entry* le = zend_list_id_to_entry(id TSRMLS_CC);
HPHP::ZendNormalResourceDataHolder* holder =
dynamic_cast<HPHP::ZendNormalResourceDataHolder*>(le);
return holder ? holder->getResourceData() : le;
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_modules.h b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_modules.h
index ee7b27c..a93a83d 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_modules.h
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_modules.h
@@ -26,9 +26,6 @@
#include "zend_compile.h"
#include "zend_build.h"
-#ifdef HHVM
-#include "hphp/runtime/ext/extension.h"
-#endif
#define INIT_FUNC_ARGS int type, int module_number TSRMLS_DC
#define INIT_FUNC_ARGS_PASSTHRU type, module_number TSRMLS_CC
@@ -75,15 +72,7 @@ typedef struct _zend_module_entry zend_module_entry;
typedef struct _zend_module_dep zend_module_dep;
#ifdef HHVM
-class ZendExtension : public HPHP::Extension {
-private:
- zend_module_entry *getEntry();
-public:
- /* implicit */ ZendExtension(const char* name);
- virtual void moduleInit() override;
- virtual void moduleShutdown() override;
- static ZendExtension* GetByModuleNumber(int module_number);
-};
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-extension.h"
#endif
struct _zend_module_entry {
@@ -122,34 +111,7 @@ struct _zend_module_entry {
};
#ifdef HHVM
-inline void ZendExtension::moduleInit() {
- if (!HPHP::RuntimeOption::EnableZendCompat) {
- return;
- }
- zend_module_entry* entry = getEntry();
- if (entry->globals_ctor) {
- entry->globals_ctor(entry->globals_ptr);
- }
- if (entry->module_startup_func) {
- entry->module_startup_func(1, entry->module_number);
- }
-}
-inline void ZendExtension::moduleShutdown() {
- if (!HPHP::RuntimeOption::EnableZendCompat) {
- return;
- }
- zend_module_entry* entry = getEntry();
- if (entry->module_shutdown_func) {
- entry->module_shutdown_func(1, 1);
- }
- if (entry->globals_dtor) {
- entry->globals_dtor(entry->globals_ptr);
- }
-}
-inline zend_module_entry *ZendExtension::getEntry() {
- enum { offset = offsetof(struct _zend_module_entry, name) };
- return (zend_module_entry*)(((char*)this) - offset);
-}
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-extension-inline.h"
#endif
#define MODULE_DEP_REQUIRED 1
@@ -181,6 +143,8 @@ int module_registry_request_startup(zend_module_entry *module TSRMLS_DC);
int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC);
#define ZEND_MODULE_DTOR (void (*)(void *)) module_destructor
+
+
#endif
/*
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_objects_API.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_objects_API.cpp
index d852f96..cae4291 100644
--- a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_objects_API.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_objects_API.cpp
@@ -40,7 +40,7 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) {
ZEND_API void *zend_object_store_get_object(const zval *zobject TSRMLS_DC) {
const auto& zod = static_cast<HPHP::c_ZendObjectData*>(Z_OBJVAL_P(zobject));
- return zend_object_store_get_object_by_handle(zod->getHandle());
+ return zend_object_store_get_object_by_handle(zod->getHandle() TSRMLS_CC);
}
ZEND_REQUEST_LOCAL_LIST(void*, s_object_store);
diff --git a/hphp/runtime/ext_zend_compat/php-src/Zend/zend_virtual_cwd.cpp b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_virtual_cwd.cpp
new file mode 100644
index 0000000..42eefa5
--- /dev/null
+++ b/hphp/runtime/ext_zend_compat/php-src/Zend/zend_virtual_cwd.cpp
@@ -0,0 +1,208 @@
+/*
+ +----------------------------------------------------------------------+
+ | HipHop for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+*/
+#include "hphp/runtime/ext_zend_compat/php-src/Zend/zend.h"
+#include "hphp/runtime/ext_zend_compat/php-src/TSRM/tsrm_virtual_cwd.h"
+#include "hphp/runtime/ext_zend_compat/php-src/TSRM/TSRM.h"
+
+#include "hphp/runtime/base/execution-context.h"
+#include "hphp/runtime/ext/ext_file.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+// Unimplemented:
+// CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath TSRMLS_DC)
+// CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC)
+// CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC)
+// CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC)
+// CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
+
+CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC) /* {{{ */
+{
+ *length = HPHP::g_context->getCwd().size();
+ return estrdup(HPHP::g_context->getCwd().c_str());
+}
+/* }}} */
+
+CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC) /* {{{ */
+{
+ int cwd_size = HPHP::g_context->getCwd().size();
+ if (cwd_size >= size) {
+ errno = ERANGE;
+ return NULL;
+ } else {
+ memcpy(buf, HPHP::g_context->getCwd().data(), cwd_size);
+ buf[cwd_size] = '\0';
+ return buf;
+ }
+}
+/* }}} */
+
+CWD_API int virtual_chdir(const char *path TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ struct stat s;
+ if (stat(translated.c_str(), &s) != 0) {
+ return -1; // failure
+ }
+ if (!S_ISDIR(s.st_mode)) {
+ errno = ENOTDIR;
+ return -1; // failure
+ }
+ HPHP::g_context->setCwd(translated);
+ return 0;
+}
+/* }}} */
+CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ if (translated.empty()) {
+ return NULL;
+ }
+ if (!realpath(translated.c_str(), real_path)) {
+ return NULL;
+ }
+ return real_path;
+}
+/* }}} */
+
+CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC) /* {{{ */
+{
+ if (path[0] == '\0') { /* Fail to open empty path */
+ return NULL;
+ }
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ return fopen(translated.c_str(), mode);
+}
+/* }}} */
+
+CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(pathname, HPHP::CopyString));
+ return access(translated.c_str(), mode);
+}
+/* }}} */
+
+CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(filename, HPHP::CopyString));
+ return utime(translated.c_str(), buf);
+}
+/* }}} */
+
+CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(filename, HPHP::CopyString));
+ return chmod(translated.c_str(), mode);
+}
+/* }}} */
+
+CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(filename, HPHP::CopyString));
+ int ret;
+ if (link) {
+#if HAVE_LCHOWN
+ ret = lchown(translated.c_str(), owner, group);
+#else
+ ret = -1;
+#endif
+ } else {
+ ret = chown(translated.c_str(), owner, group);
+ }
+ return ret;
+}
+/* }}} */
+
+
+CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...) /* {{{ */
+{
+ int f;
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ if (flags & O_CREAT) {
+ mode_t mode;
+ va_list arg;
+
+ va_start(arg, flags);
+ mode = (mode_t) va_arg(arg, int);
+ va_end(arg);
+
+ f = open(translated.c_str(), flags, mode);
+ } else {
+ f = open(translated.c_str(), flags);
+ }
+ return f;
+}
+/* }}} */
+
+CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ return creat(translated.c_str(), mode);
+}
+/* }}} */
+
+CWD_API int virtual_rename(const char *oldname, const char *newname TSRMLS_DC) /* {{{ */
+{
+ HPHP::String oldTrans = HPHP::File::TranslatePath(HPHP::String(oldname, HPHP::CopyString));
+ HPHP::String newTrans = HPHP::File::TranslatePath(HPHP::String(newname, HPHP::CopyString));
+ return rename(oldTrans.c_str(), newTrans.c_str());
+}
+/* }}} */
+
+CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ return stat(translated.c_str(), buf);
+}
+/* }}} */
+
+CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ return lstat(translated.c_str(), buf);
+}
+/* }}} */
+
+CWD_API int virtual_unlink(const char *path TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(path, HPHP::CopyString));
+ return unlink(translated.c_str());
+}
+/* }}} */
+
+CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(pathname, HPHP::CopyString));
+ return mkdir(translated.c_str(), mode);
+}
+/* }}} */
+CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(pathname, HPHP::CopyString));
+ return rmdir(translated.c_str());
+}
+/* }}} */
+
+CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC) /* {{{ */
+{
+ HPHP::String translated = HPHP::File::TranslatePath(HPHP::String(pathname, HPHP::CopyString));
+ return opendir(translated.c_str());
+}
+/* }}} */
diff --git a/hphp/runtime/ext_zend_compat/php-src/ext/standard/basic_functions.cpp b/hphp/runtime/ext_zend_compat/php-src/ext/standard/basic_functions.cpp
index 1e6e182..67e0dba 100644
--- a/hphp/runtime/ext_zend_compat/php-src/ext/standard/basic_functions.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/ext/standard/basic_functions.cpp
@@ -26,6 +26,7 @@
#include "php_ini.h"
#include "basic_functions.h"
#include "zend_operators.h"
+#include "ext/standard/php_lcg.h"
#include "zend.h"
@@ -42,3 +43,51 @@ PHPAPI double php_get_nan(void) {
PHPAPI double php_get_inf(void) {
return HPHP::k_INF;
}
+
+PHP_MINIT_FUNCTION(basic) /* {{{ */
+{
+ PHP_MINIT(lcg)(INIT_FUNC_ARGS_PASSTHRU);
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
+{
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_RINIT_FUNCTION(basic) /* {{{ */
+{
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
+{
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_MINFO_FUNCTION(basic) /* {{{ */
+{
+}
+/* }}} */
+
+const zend_function_entry basic_functions[] = { /* {{{ */
+ PHP_FE_END
+};
+/* }}} */
+
+zend_module_entry basic_functions_module = { /* {{{ */
+ STANDARD_MODULE_HEADER,
+ "standard_zend_compat", /* extension name */
+ basic_functions, /* function list */
+ PHP_MINIT(basic), /* process startup */
+ PHP_MSHUTDOWN(basic), /* process shutdown */
+ PHP_RINIT(basic), /* request startup */
+ PHP_RSHUTDOWN(basic), /* request shutdown */
+ PHP_MINFO(basic), /* extension info */
+ PHP_VERSION, /* extension version */
+ STANDARD_MODULE_PROPERTIES
+};
diff --git a/hphp/runtime/ext_zend_compat/php-src/ext/standard/lcg.cpp b/hphp/runtime/ext_zend_compat/php-src/ext/standard/lcg.cpp
index fb32659..8c0e5db 100644
--- a/hphp/runtime/ext_zend_compat/php-src/ext/standard/lcg.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/ext/standard/lcg.cpp
@@ -95,3 +95,20 @@ static void lcg_seed(TSRMLS_D) /* {{{ */
LCG(seeded) = 1;
}
/* }}} */
+
+static void lcg_init_globals(php_lcg_globals *lcg_globals_p TSRMLS_DC) /* {{{ */
+{
+ LCG(seeded) = 0;
+}
+/* }}} */
+
+PHP_MINIT_FUNCTION(lcg) /* {{{ */
+{
+#ifdef ZTS
+ ts_allocate_id(&lcg_globals_id, sizeof(php_lcg_globals), (ts_allocate_ctor) lcg_init_globals, NULL);
+#else
+ lcg_init_globals(&lcg_globals);
+#endif
+ return SUCCESS;
+}
+/* }}} */
diff --git a/hphp/runtime/ext_zend_compat/php-src/main/fopen_wrappers.cpp b/hphp/runtime/ext_zend_compat/php-src/main/fopen_wrappers.cpp
index 017593b..6d7702e 100644
--- a/hphp/runtime/ext_zend_compat/php-src/main/fopen_wrappers.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/main/fopen_wrappers.cpp
@@ -77,6 +77,8 @@
#endif
/* }}} */
+#include "hphp/util/file-util.cpp"
+
PHPAPI int php_check_open_basedir(const char *path TSRMLS_DC) {
// we don't support openbasedir so you can access anything
return SUCCESS;
@@ -100,68 +102,33 @@ PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const cha
PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode TSRMLS_DC)
{
- cwd_state new_state;
- char cwd[MAXPATHLEN];
- int copy_len;
-
+ // This part is basically the same as File::TranslatePath(), except relative_to is
+ // optionally a parameter instead of coming from g_context
+ assert(realpath_mode != CWD_FILEPATH); // not implemented
+ if (realpath_mode == CWD_FILEPATH) {
+ realpath_mode = CWD_REALPATH;
+ }
if (!filepath[0]) {
return NULL;
- } else if (IS_ABSOLUTE_PATH(filepath, strlen(filepath))) {
- cwd[0] = '\0';
- } else {
- const char *iam = SG(request_info).path_translated;
- const char *result;
+ }
+
+ HPHP::String canonicalized(HPHP::FileUtil::canonicalize(filepath, strlen(filepath)), HPHP::AttachString);
+ if (canonicalized.charAt(0) != '/') {
if (relative_to) {
- if (relative_to_len > MAXPATHLEN-1U) {
- return NULL;
- }
- result = relative_to;
- memcpy(cwd, relative_to, relative_to_len+1U);
+ canonicalized = HPHP::String(relative_to, HPHP::CopyString) + "/" + canonicalized;
} else {
- result = VCWD_GETCWD(cwd, MAXPATHLEN);
+ canonicalized = HPHP::g_context->getCwd() + "/" + canonicalized;
}
-
- if (!result && (iam != filepath)) {
- int fdtest = -1;
-
- fdtest = VCWD_OPEN(filepath, O_RDONLY);
- if (fdtest != -1) {
- /* return a relative file path if for any reason
- * we cannot cannot getcwd() and the requested,
- * relatively referenced file is accessible */
- copy_len = strlen(filepath) > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : strlen(filepath);
- if (real_path) {
- memcpy(real_path, filepath, copy_len);
- real_path[copy_len] = '\0';
- } else {
- real_path = estrndup(filepath, copy_len);
- }
- close(fdtest);
- return real_path;
- } else {
- cwd[0] = '\0';
- }
- } else if (!result) {
- cwd[0] = '\0';
- }
- }
-
- new_state.cwd = strdup(cwd);
- new_state.cwd_length = strlen(cwd);
-
- if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode TSRMLS_CC)) {
- free(new_state.cwd);
- return NULL;
}
-
+
if (real_path) {
- copy_len = new_state.cwd_length > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : new_state.cwd_length;
- memcpy(real_path, new_state.cwd, copy_len);
+ int copy_len;
+ copy_len = canonicalized.size() > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : canonicalized.size();
+ memcpy(real_path, canonicalized.data(), copy_len);
real_path[copy_len] = '\0';
} else {
- real_path = estrndup(new_state.cwd, new_state.cwd_length);
+ real_path = estrndup(canonicalized.data(), canonicalized.size());
}
- free(new_state.cwd);
return real_path;
}
diff --git a/hphp/runtime/ext_zend_compat/php-src/main/main.cpp b/hphp/runtime/ext_zend_compat/php-src/main/main.cpp
index 4576817..b2a0dd7 100644
--- a/hphp/runtime/ext_zend_compat/php-src/main/main.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/main/main.cpp
@@ -90,7 +90,7 @@ PHPAPI void php_error_docref0(const char *docref TSRMLS_DC, int type, const char
std::string msg;
const char* space;
const char* class_name = get_active_class_name(&space TSRMLS_CC);
- HPHP::string_printf(msg, "%s%s%s(): ", class_name, space, get_active_function_name());
+ HPHP::string_printf(msg, "%s%s%s(): ", class_name, space, get_active_function_name(TSRMLS_C));
msg += format;
auto mode = static_cast<HPHP::ErrorConstants::ErrorModes>(type);
diff --git a/hphp/runtime/ext_zend_compat/php-src/main/php_config.h b/hphp/runtime/ext_zend_compat/php-src/main/php_config.h
index d463c6e..1b2afc5 100644
--- a/hphp/runtime/ext_zend_compat/php-src/main/php_config.h
+++ b/hphp/runtime/ext_zend_compat/php-src/main/php_config.h
@@ -2367,7 +2367,7 @@
#define ZEND_VM_KIND ZEND_VM_KIND_CALL
/* */
-/* #undef ZTS */
+#define ZTS 1
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
@@ -2486,5 +2486,5 @@ int zend_sprintf(char *buffer, const char *format, ...);
#endif
#endif
-/* #undef PTHREADS */
+#define PTHREADS 1
diff --git a/hphp/runtime/ext_zend_compat/php-src/main/php_globals.cpp b/hphp/runtime/ext_zend_compat/php-src/main/php_globals.cpp
index a2c23ab..e3f5d59 100644
--- a/hphp/runtime/ext_zend_compat/php-src/main/php_globals.cpp
+++ b/hphp/runtime/ext_zend_compat/php-src/main/php_globals.cpp
@@ -2,7 +2,7 @@
// Zend has a very specific include order, so I can't do this class' header
// before zend.h sadly
#include "hphp/runtime/ext_zend_compat/php-src/main/php_globals.h"
-#include "hphp/runtime/ext_hhvm/ext_zend_compat.h"
+#include "hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h"
static IMPLEMENT_THREAD_LOCAL(_php_core_globals, s_php_core_globals);
diff --git a/hphp/system/idl/ezc_test.idl.json b/hphp/system/idl/ezc_test.idl.json
index 842fc87..0b77f05 100644
--- a/hphp/system/idl/ezc_test.idl.json
+++ b/hphp/system/idl/ezc_test.idl.json
@@ -108,8 +108,24 @@
"type": "Variant"
},
"args": []
+ },
+ {
+ "name": "ezc_realpath",
+ "desc": "Return the resolved path",
+ "flags": [
+ "ZendCompat",
+ "NoFCallBuiltin"
+ ],
+ "return": {
+ "type": "Variant"
+ },
+ "args": [
+ {
+ "name": "path",
+ "type": "Variant"
+ }
+ ]
}
-
],
"classes": [
]
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic2.php b/hphp/test/slow/ext_ezc_test/realpath_basic2.php
new file mode 100644
index 0000000..509c167
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic2.php
@@ -0,0 +1,7 @@
+<?php
+
+var_dump(ezc_realpath('.') == ezc_realpath(getcwd()));
+chdir('..');
+var_dump(ezc_realpath('.') == ezc_realpath(getcwd()));
+
+?>
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic2.php.expectf b/hphp/test/slow/ext_ezc_test/realpath_basic2.php.expectf
new file mode 100644
index 0000000..890dda8
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic2.php.expectf
@@ -0,0 +1,2 @@
+bool(true)
+bool(true)
\ No newline at end of file
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic2.php.skipif b/hphp/test/slow/ext_ezc_test/realpath_basic2.php.skipif
new file mode 100644
index 0000000..78d8128
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic2.php.skipif
@@ -0,0 +1 @@
+<?php if (!extension_loaded("ezc_test")) print "skip"; ?>
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic3.php b/hphp/test/slow/ext_ezc_test/realpath_basic3.php
new file mode 100644
index 0000000..8830fb5
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic3.php
@@ -0,0 +1,56 @@
+<?php
+/* Prototype: string ezc_realpath ( string $path );
+ Description: Returns canonicalized absolute pathname
+*/
+
+echo "\n*** Testing basic functions of ezc_realpath() with files ***\n";
+
+/* creating directories and files */
+$file_path = dirname(__FILE__);
+mkdir("$file_path/realpath_basic/home/test/", 0777, true);
+
+$file_handle1 = fopen("$file_path/realpath_basic/home/test/realpath_basic.tmp", "w");
+$file_handle2 = fopen("$file_path/realpath_basic/home/realpath_basic.tmp", "w");
+$file_handle3 = fopen("$file_path/realpath_basic/realpath_basic.tmp", "w");
+fclose($file_handle1);
+fclose($file_handle2);
+fclose($file_handle3);
+
+echo "\n*** Testing ezc_realpath() on filenames ***\n";
+$filenames = array (
+ /* filenames resulting in valid paths */
+ "./realpath_basic/home/realpath_basic.tmp",
+ "./realpath_basic/realpath_basic.tmp",
+ "./realpath_basic//home/test//../test/./realpath_basic.tmp",
+ "./realpath_basic/home//../././realpath_basic.tmp",
+
+ /* filenames with invalid path */
+ // checking for binary safe
+ "./realpath_basicx000/home/realpath_basic.tmp",
+
+ ".///realpath_basic/home//..//././test//realpath_basic.tmp",
+ "./realpath_basic/home/../home/../test/..realpath_basic.tmp"
+);
+
+chdir("$file_path/..");
+chdir($file_path);
+
+$counter = 1;
+/* loop through $files to read the filepath of $file in the above array */
+foreach($filenames as $file) {
+ echo "\n-- Iteration $counter --\n";
+ var_dump( ezc_realpath($file) );
+ $counter++;
+}
+
+echo "Done\n";
+?>
+<?php
+$name_prefix = dirname(__FILE__)."/realpath_basic";
+unlink("$name_prefix/home/test/realpath_basic.tmp");
+unlink("$name_prefix/home/realpath_basic.tmp");
+unlink("$name_prefix/realpath_basic.tmp");
+rmdir("$name_prefix/home/test/");
+rmdir("$name_prefix/home/");
+rmdir("$name_prefix/");
+?>
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic3.php.expectf b/hphp/test/slow/ext_ezc_test/realpath_basic3.php.expectf
new file mode 100644
index 0000000..7469fed
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic3.php.expectf
@@ -0,0 +1,25 @@
+*** Testing basic functions of ezc_realpath() with files ***
+
+*** Testing ezc_realpath() on filenames ***
+
+-- Iteration 1 --
+string(%d) "%srealpath_basic%shome%srealpath_basic.tmp"
+
+-- Iteration 2 --
+string(%d) "%srealpath_basic%srealpath_basic.tmp"
+
+-- Iteration 3 --
+string(%d) "%srealpath_basic%shome%stest%srealpath_basic.tmp"
+
+-- Iteration 4 --
+string(%d) "%srealpath_basic%srealpath_basic.tmp"
+
+-- Iteration 5 --
+bool(false)
+
+-- Iteration 6 --
+bool(false)
+
+-- Iteration 7 --
+bool(false)
+Done
diff --git a/hphp/test/slow/ext_ezc_test/realpath_basic3.php.skipif b/hphp/test/slow/ext_ezc_test/realpath_basic3.php.skipif
new file mode 100644
index 0000000..78d8128
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_basic3.php.skipif
@@ -0,0 +1 @@
+<?php if (!extension_loaded("ezc_test")) print "skip"; ?>
diff --git a/hphp/test/slow/ext_ezc_test/realpath_variation2.php b/hphp/test/slow/ext_ezc_test/realpath_variation2.php
new file mode 100644
index 0000000..a9152cb
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_variation2.php
@@ -0,0 +1,28 @@
+<?php
+/* Prototype : string ezc_realpath(string path)
+ * Description: Return the resolved path
+ * Source code: ext/standard/file.c
+ * Alias to functions:
+ */
+
+echo "*** Testing ezc_realpath() : variation ***\n";
+
+$paths = array('c:\\',
+ 'c:',
+ 'c' ,
+ '\\' ,
+ '/',
+ 'c:temp',
+ 'c:\\/',
+ '/tmp/',
+ '/tmp/\\',
+ '\\tmp',
+ '\\tmp\\');
+
+foreach($paths as $path) {
+ echo "\n--$path--\n";
+ var_dump( ezc_realpath($path) );
+};
+
+?>
+===DONE===
diff --git a/hphp/test/slow/ext_ezc_test/realpath_variation2.php.expectf b/hphp/test/slow/ext_ezc_test/realpath_variation2.php.expectf
new file mode 100644
index 0000000..244c53e
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_variation2.php.expectf
@@ -0,0 +1,35 @@
+*** Testing ezc_realpath() : variation ***
+
+--c:\--
+bool(false)
+
+--c:--
+bool(false)
+
+--c--
+bool(false)
+
+--\--
+bool(false)
+
+--/--
+string(1) "/"
+
+--c:temp--
+bool(false)
+
+--c:\/--
+bool(false)
+
+--/tmp/--
+string(%d) %s/tmp"
+
+--/tmp/\--
+bool(false)
+
+--\tmp--
+bool(false)
+
+--\tmp\--
+bool(false)
+===DONE===
diff --git a/hphp/test/slow/ext_ezc_test/realpath_variation2.php.skipif b/hphp/test/slow/ext_ezc_test/realpath_variation2.php.skipif
new file mode 100644
index 0000000..78d8128
--- /dev/null
+++ b/hphp/test/slow/ext_ezc_test/realpath_variation2.php.skipif
@@ -0,0 +1 @@
+<?php if (!extension_loaded("ezc_test")) print "skip"; ?>
diff --git a/hphp/tools/bootstrap/gen-infotabs.cpp b/hphp/tools/bootstrap/gen-infotabs.cpp
index 7a771cc..c504471 100644
--- a/hphp/tools/bootstrap/gen-infotabs.cpp
+++ b/hphp/tools/bootstrap/gen-infotabs.cpp
@@ -39,7 +39,7 @@ void write_zend_func_stub(std::ofstream& cpp, PhpFunc func,
cpp << folly::format(R"(
}} // End namespace
void {0}{1}{2}(
- int, HPHP::RefData*, HPHP::RefData**, HPHP::RefData*, int
+ int, HPHP::RefData*, HPHP::RefData**, HPHP::RefData*, int, void***
);
namespace HPHP {{
TypedValue* {3}{1}{2}(ActRec* ar) {{
@@ -70,7 +70,7 @@ int main(int argc, const char* argv[]) {
std::ofstream cpp(argv[1]);
cpp << "#include \"hphp/runtime/ext_hhvm/ext_hhvm.h\"\n"
- << "#include \"hphp/runtime/ext_hhvm/ext_zend_compat.h\"\n"
+ << "#include \"hphp/runtime/ext_zend_compat/hhvm/zend-wrap-func.h\"\n"
<< "#include \"hphp/runtime/ext/ext.h\"\n"
<< "#include \"hphp/runtime/vm/runtime.h\"\n"
<< "#include \"ext_hhvm_infotabs.h\"\n"
--
1.8.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment