__lvalProxy needs to be request local
But it was recently made thread local. If the value left in it at the end of one request was smart allocated, the next request would try to free it - but after its already been swept. We could make this RequestLocal, but that seems to add even more overhead. We could probably make it a __thread TypedValue, and just set it to uninit at the start of each request (and then tvAsVariant() where its used). This just puts it back to how it was, since global_variables() is already being dealt with appropriately.
Esse commit está contido em:
@@ -2257,8 +2257,6 @@ public:
|
||||
static const bool CheckParams = true;
|
||||
};
|
||||
|
||||
DECLARE_THREAD_LOCAL(Variant, __lvalProxy);
|
||||
|
||||
template<typename T>
|
||||
Variant& Variant::LvalAtImpl0(
|
||||
Variant *self, T key, Variant *tmp, bool blackHole, ACCESSPARAMS_IMPL) {
|
||||
@@ -2304,7 +2302,7 @@ head:
|
||||
*tmp = self->getArrayAccess()->offsetGet(key);
|
||||
return *tmp;
|
||||
}
|
||||
Variant& retv = *(__lvalProxy.get());
|
||||
Variant& retv = get_global_variables()->__lvalProxy;
|
||||
retv = self->getArrayAccess()->offsetGet(key);
|
||||
return retv;
|
||||
}
|
||||
@@ -2430,7 +2428,7 @@ Variant &Variant::lvalInvalid() {
|
||||
}
|
||||
|
||||
Variant &Variant::lvalBlackHole() {
|
||||
Variant &bh = *(__lvalProxy.get());
|
||||
Variant &bh = get_global_variables()->__lvalProxy;
|
||||
bh.unset();
|
||||
return bh;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ class GlobalNameValueTableWrapper : public NameValueTableWrapper {
|
||||
Variant gvm_http_response_header;
|
||||
|
||||
Variant __realPropProxy;
|
||||
Variant __lvalProxy;
|
||||
|
||||
Variant stgv_Variant[1];
|
||||
#define k_SID stgv_Variant[0]
|
||||
|
||||
@@ -6,7 +6,7 @@ Log {
|
||||
Server {
|
||||
Port = 8080
|
||||
SourceRoot != echo $(pwd)/runtime/tmp
|
||||
|
||||
ThreadCount = 1
|
||||
AllowedFiles {
|
||||
0 = string
|
||||
}
|
||||
|
||||
+55
-33
@@ -45,8 +45,9 @@ static int s_admin_port = 0;
|
||||
static int s_rpc_port = 0;
|
||||
static int inherit_fd = -1;
|
||||
|
||||
bool TestServer::VerifyServerResponse(const char *input, const char *output,
|
||||
const char *url, const char *method,
|
||||
bool TestServer::VerifyServerResponse(const char *input, const char **outputs,
|
||||
const char **urls, int nUrls,
|
||||
const char *method,
|
||||
const char *header, const char *postdata,
|
||||
bool responseHeader,
|
||||
const char *file /* = "" */,
|
||||
@@ -70,44 +71,54 @@ bool TestServer::VerifyServerResponse(const char *input, const char *output,
|
||||
AsyncFunc<TestServer> func(this, &TestServer::RunServer);
|
||||
func.start();
|
||||
|
||||
String server = "http://";
|
||||
server += f_php_uname("n");
|
||||
server += ":" + lexical_cast<string>(port) + "/";
|
||||
server += url;
|
||||
string actual, err;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Variant c = f_curl_init();
|
||||
f_curl_setopt(c, k_CURLOPT_URL, server);
|
||||
f_curl_setopt(c, k_CURLOPT_RETURNTRANSFER, true);
|
||||
if (postdata) {
|
||||
f_curl_setopt(c, k_CURLOPT_POSTFIELDS, postdata);
|
||||
f_curl_setopt(c, k_CURLOPT_POST, true);
|
||||
}
|
||||
if (header) {
|
||||
f_curl_setopt(c, k_CURLOPT_HTTPHEADER, CREATE_VECTOR1(header));
|
||||
}
|
||||
if (responseHeader) {
|
||||
f_curl_setopt(c, k_CURLOPT_HEADER, 1);
|
||||
}
|
||||
bool passed = true;
|
||||
|
||||
Variant res = f_curl_exec(c);
|
||||
if (!same(res, false)) {
|
||||
actual = res.toString();
|
||||
break;
|
||||
string actual;
|
||||
|
||||
int url = 0;
|
||||
for (url = 0; url < nUrls; url++) {
|
||||
String server = "http://";
|
||||
server += f_php_uname("n");
|
||||
server += ":" + lexical_cast<string>(port) + "/";
|
||||
server += urls[url];
|
||||
actual = "<No response from server>";
|
||||
string err;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Variant c = f_curl_init();
|
||||
f_curl_setopt(c, k_CURLOPT_URL, server);
|
||||
f_curl_setopt(c, k_CURLOPT_RETURNTRANSFER, true);
|
||||
if (postdata) {
|
||||
f_curl_setopt(c, k_CURLOPT_POSTFIELDS, postdata);
|
||||
f_curl_setopt(c, k_CURLOPT_POST, true);
|
||||
}
|
||||
if (header) {
|
||||
f_curl_setopt(c, k_CURLOPT_HTTPHEADER, CREATE_VECTOR1(header));
|
||||
}
|
||||
if (responseHeader) {
|
||||
f_curl_setopt(c, k_CURLOPT_HEADER, 1);
|
||||
}
|
||||
|
||||
Variant res = f_curl_exec(c);
|
||||
if (!same(res, false)) {
|
||||
actual = res.toString();
|
||||
break;
|
||||
}
|
||||
sleep(1); // wait until HTTP server is up and running
|
||||
}
|
||||
if (actual != outputs[url]) {
|
||||
if (!responseHeader ||
|
||||
actual.find(outputs[url]) == string::npos) {
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sleep(1); // wait until HTTP server is up and running
|
||||
}
|
||||
|
||||
AsyncFunc<TestServer>(this, &TestServer::StopServer).run();
|
||||
func.waitForEnd();
|
||||
|
||||
bool passed = (actual == output);
|
||||
if (responseHeader) {
|
||||
passed = (actual.find(output) != string::npos);
|
||||
}
|
||||
|
||||
if (!passed) {
|
||||
printf("%s:%d\nParsing: [%s]\nBet %d:\n"
|
||||
printf("%s:%d\nParsing: [%s] (req %d)\nBet %d:\n"
|
||||
"--------------------------------------\n"
|
||||
"%s"
|
||||
"--------------------------------------\n"
|
||||
@@ -115,7 +126,7 @@ bool TestServer::VerifyServerResponse(const char *input, const char *output,
|
||||
"--------------------------------------\n"
|
||||
"%s"
|
||||
"--------------------------------------\n",
|
||||
file, line, input, (int)strlen(output), output,
|
||||
file, line, input, url + 1, (int)strlen(outputs[url]), outputs[url],
|
||||
(int)actual.length(), actual.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -204,6 +215,7 @@ bool TestServer::RunTests(const std::string &which) {
|
||||
RUN_TEST(TestInheritFdServer);
|
||||
RUN_TEST(TestSanity);
|
||||
RUN_TEST(TestServerVariables);
|
||||
RUN_TEST(TestInteraction);
|
||||
RUN_TEST(TestGet);
|
||||
RUN_TEST(TestPost);
|
||||
RUN_TEST(TestCookie);
|
||||
@@ -274,6 +286,16 @@ bool TestServer::TestServerVariables() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestServer::TestInteraction() {
|
||||
// run this twice to test lvalBlackHole
|
||||
VSR2("<?php "
|
||||
"$a[] = new stdclass;"
|
||||
"var_dump(count(array_combine($a, $a)));",
|
||||
"int(0)\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestServer::TestGet() {
|
||||
VSGET("<?php var_dump($_GET['name']);",
|
||||
"string(0) \"\"\n", "string?name");
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
|
||||
// test $_ variables
|
||||
bool TestServerVariables();
|
||||
// test things that need more than one request
|
||||
bool TestInteraction();
|
||||
bool TestGet();
|
||||
bool TestPost();
|
||||
bool TestCookie();
|
||||
@@ -71,6 +73,17 @@ protected:
|
||||
const char *header, const char *postdata,
|
||||
bool responseHeader,
|
||||
const char *file = "", int line = 0,
|
||||
int port = 0) {
|
||||
return VerifyServerResponse(input, &output, &url, 1,
|
||||
method, header, postdata, responseHeader,
|
||||
file, line, port);
|
||||
}
|
||||
|
||||
bool VerifyServerResponse(const char *input, const char **outputs,
|
||||
const char **urls, int nUrl, const char *method,
|
||||
const char *header, const char *postdata,
|
||||
bool responseHeader,
|
||||
const char *file = "", int line = 0,
|
||||
int port = 0);
|
||||
bool PreBindSocket();
|
||||
void CleanupPreBoundSocket();
|
||||
@@ -81,9 +94,18 @@ protected:
|
||||
|
||||
#define VSR(input, output) \
|
||||
if (!Count(VerifyServerResponse(input, output, "string", "GET", nullptr, \
|
||||
nullptr, false, __FILE__,__LINE__))) \
|
||||
nullptr, false, __FILE__,__LINE__))) \
|
||||
return false;
|
||||
|
||||
#define VSR2(input, output) do { \
|
||||
const char* urls[2] = { "string", "string" }; \
|
||||
const char* outputs[2] = { output, output }; \
|
||||
if (!Count(VerifyServerResponse(input, outputs, urls, 2, "GET", \
|
||||
nullptr, nullptr, false, \
|
||||
__FILE__,__LINE__))) \
|
||||
return false; \
|
||||
} while (false)
|
||||
|
||||
#define VSRES(input, output) \
|
||||
if (!Count(VerifyServerResponse(input, output, "string", "GET", nullptr, \
|
||||
nullptr, true, __FILE__,__LINE__))) \
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário