12 Commits

Autor SHA1 Mensagem Data
ptarjan e8141ac49d Revert "Update folly"
This reverts commit 4cf537888b.
2014-01-14 14:50:32 -08:00
Sara Golemon 4cf537888b Update folly
Conflicts:
	CMake/HPHPSetup.cmake
2014-01-14 14:35:31 -08:00
ptarjan 2752b5bbb1 bump version to 2.3.3 2014-01-14 14:21:24 -08:00
Paul Tarjan cc6cbf3852 fix fastcgi segfaults a better way
I think this is what julk originally wanted. He has a `m_keepConn` boolean that is set by `ConnectionFlags::KEEP_CONN` and if that is false, he calls this callback in both the error and the success case.

This doesn't segfault when the connection is abruptly closed by the requestor.

Closes #1522

Reviewed By: @scannell

Differential Revision: D1124995
2014-01-14 14:17:54 -08:00
Antony Puckey 1a4fac8a25 add getRemoteAddr to transport which defaults to empty string. add getRemoteAddr to fastcgi transport to return the proper header. fi no remoteAddr set it to the remoteHost ( libevent ) only set REMOTE_HOST if there is something in it as per php-src
Differential Revision: D1126545
2014-01-14 14:14:39 -08:00
Antony Puckey ae6443500e Set HTTPS header appropriately in fastcgi
Check passed header values for HTTPS.

IIS sets this header to "off" so check for that and empty value before
using transport->setSSL().

Only change to lower case if the value is not empty for performance.

Closes #1546

Reviewed By: @ptarjan

Differential Revision: D1125440

Pulled By: @scannell
2014-01-13 18:37:49 -08:00
Antony Puckey e42452e4f2 Allow transport to override SERVER_ headers
Uses the following headers from the transport (for fastcgi)
instead of the local config if they exist:

SERVER_NAME
SERVER_ADDR
SERVER_PORT

Closes #1445

Reviewed By: @ptarjan

Differential Revision: D1114969

Pulled By: @scannell
2014-01-13 18:37:16 -08:00
Antony Puckey 1dd7e6165e Populate fastcgi (transport-specific) headers
Added new function CopyServerParams in http-protocol which uses the new transport function getServerParams that adds any transport specific SERVER variables ie: FASTCGI_PARAMS to the _SERVER array

Closes #1437
Closes #1511

Reviewed By: @sgolemon

Differential Revision: D1120838

Pulled By: @scannell
2014-01-13 18:36:41 -08:00
Paul Tarjan 01ef59346e Support mod_fastcgi
when using mod_fastcgi SCRIPT_NAME is the Action instead of the actual document you want
this commit uses PATH_TRANSLATED - DOCUMENT_ROOT

tested with:
apache+mod_fastcgi
apache+mod_proxy_fcgi
nginx with no PATH_TRANSLATED header
nginx with this as PATH_TRANSLATED: fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

Reviewed By: @scannell

Differential Revision: D1114124
2014-01-13 18:36:22 -08:00
Paul Tarjan 9380a44469 delete FastCGIConnection object
This was a leak appearing in @apuckey's valgrind dump. @simpkins said the object should delete itself since either the success or error callbacks will for sure be called for each connection.

Closes #1252

Reviewed By: @scannell

Differential Revision: D1115399
2014-01-13 13:32:58 -08:00
Paul Tarjan 3f859af167 stop emitting regex debugging message
This message is breaking composer installing things with enormous regexes. I tried to change the default error level but @markw65 didn't like that and we need to do something, so I guess lets not emit this if EHHS is off.

Closes #1347

Reviewed By: @markw65

Differential Revision: D1118365
2014-01-13 13:27:01 -08:00
Scott MacVicar 55ecfbdbb6 Fix libxml_disable_entity_loader()
This wasn't calling requestInit and setting the libxml handler no null.
So the first time an error came along it would reset the handler from
no-op to reading again.

This is a much better fix, we set our custom handler in requestInit and
when libxml_disable_entity_loader we store that state as a member bool
ensuring requestInit is always called to set our own handler.

If the handler isn't inserted then the behavious is as before. The only
time this could go pear shaped is say we wanted to make the default be
off. In that case we'd need a global requestInit that is always called
since there are libxml references everywhere.

Reviewed By: @jdelong

Differential Revision: D1116686
2014-01-13 13:20:25 -08:00
15 arquivos alterados com 216 adições e 34 exclusões
+3
Ver Arquivo
@@ -443,6 +443,9 @@ static void pcre_log_error(const char *func, int line, int pcre_code,
const char *repl, int repl_size,
int arg1 = 0, int arg2 = 0,
int arg3 = 0, int arg4 = 0) {
if (!RuntimeOption::EnableHipHopSyntax) {
return;
}
const char *escapedPattern;
const char *escapedSubject;
const char *escapedRepl;
+15 -10
Ver Arquivo
@@ -1244,6 +1244,9 @@ void c_LibXMLError::t___construct() {
///////////////////////////////////////////////////////////////////////////////
// libxml
static xmlParserInputBufferPtr
hphp_libxml_input_buffer(const char *URI, xmlCharEncoding enc);
class xmlErrorVec : public std::vector<xmlError> {
public:
~xmlErrorVec() {
@@ -1263,13 +1266,15 @@ public:
virtual void requestInit() {
m_use_error = false;
m_errors.reset();
xmlParserInputBufferCreateFilenameDefault(nullptr);
m_entity_loader_disabled = false;
xmlParserInputBufferCreateFilenameDefault(hphp_libxml_input_buffer);
}
virtual void requestShutdown() {
m_use_error = false;
m_errors.reset();
}
bool m_entity_loader_disabled;
bool m_use_error;
xmlErrorVec m_errors;
};
@@ -1376,19 +1381,19 @@ void f_libxml_set_streams_context(CResRef streams_context) {
}
static xmlParserInputBufferPtr
hphp_libxml_input_buffer_noload(const char *URI, xmlCharEncoding enc) {
return nullptr;
hphp_libxml_input_buffer(const char *URI, xmlCharEncoding enc) {
if (s_libxml_errors->m_entity_loader_disabled) {
return nullptr;
}
return __xmlParserInputBufferCreateFilename(URI, enc);
}
bool f_libxml_disable_entity_loader(bool disable /* = true */) {
xmlParserInputBufferCreateFilenameFunc old;
bool old = s_libxml_errors->m_entity_loader_disabled;
if (disable) {
old = xmlParserInputBufferCreateFilenameDefault(hphp_libxml_input_buffer_noload);
} else {
old = xmlParserInputBufferCreateFilenameDefault(nullptr);
}
return (old == hphp_libxml_input_buffer_noload);
s_libxml_errors->m_entity_loader_disabled = disable;
return old;
}
///////////////////////////////////////////////////////////////////////////////
+3 -1
Ver Arquivo
@@ -62,7 +62,8 @@ void FastCGIAcceptor::onNewConnection(
localAddress = s_unknownSocketAddress;
}
FastCGIConnection* conn = new FastCGIConnection(
// Will delete itself when it gets a closing callback
auto conn = new FastCGIConnection(
m_server,
std::move(sock),
localAddress,
@@ -145,6 +146,7 @@ void FastCGIConnection::onSessionError() {
void FastCGIConnection::onSessionClose() {
shutdownTransport();
delete this;
}
void FastCGIConnection::setMaxConns(int max_conns) {
+1 -1
Ver Arquivo
@@ -527,8 +527,8 @@ void FastCGISession::handleStdErr(RequestId request_id,
}
void FastCGISession::handleComplete(RequestId request_id) {
writeEndRequest(request_id, 0, ProtoStatus::REQUEST_COMPLETE);
endTransaction(request_id);
writeEndRequest(request_id, 0, ProtoStatus::REQUEST_COMPLETE);
if (!m_keepConn) {
handleClose();
}
@@ -28,6 +28,7 @@
#include "hphp/util/timer.h"
#include "folly/MoveWrapper.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
using folly::IOBuf;
@@ -42,9 +43,14 @@ namespace HPHP {
FastCGITransport::FastCGITransport(FastCGIConnection* connection, int id)
: m_connection(connection),
m_id(id),
m_remotePort(0), m_method(Method::Unknown), m_requestSize(0),
m_headersSent(false), m_readMore(false),
m_waiting(0), m_readComplete(false) {}
m_remotePort(0),
m_serverPort(0),
m_method(Method::Unknown),
m_requestSize(0),
m_headersSent(false),
m_readMore(false),
m_waiting(0),
m_readComplete(false) {}
const char *FastCGITransport::getUrl() {
return m_requestURI.c_str();
@@ -58,10 +64,27 @@ const char *FastCGITransport::getRemoteHost() {
return m_remoteHost.c_str();
}
const char *FastCGITransport::getRemoteAddr() {
return m_remoteAddr.c_str();
}
uint16_t FastCGITransport::getRemotePort() {
return m_remotePort;
}
const char *FastCGITransport::getServerName() {
return m_serverName.c_str();
}
const char *FastCGITransport::getServerAddr() {
return (!m_serverAddr.empty()) ? m_serverAddr.c_str() :
Transport::getServerAddr();
}
uint16_t FastCGITransport::getServerPort() {
return (m_serverPort != 0) ? m_serverPort : Transport::getServerPort();
}
const void *FastCGITransport::getPostData(int &size) {
DCHECK(!m_readMore);
return getPostDataImpl(size, false);
@@ -192,9 +215,14 @@ void FastCGITransport::getHeaders(HeaderMap &headers) {
}
}
void FastCGITransport::getTransportParams(HeaderMap &serverParams) {
for (auto& pair : m_requestHeaders) {
serverParams[pair.first] = pair.second;
}
}
void FastCGITransport::addHeaderImpl(const char *name, const char *value) {
CHECK(!m_headersSent);
if (!m_responseHeaders.count(name)) {
m_responseHeaders.insert(std::make_pair(name,
std::vector<std::string>()));
@@ -274,11 +302,16 @@ void FastCGITransport::onBodyComplete() {
const std::string FastCGITransport::k_requestURIKey = "REQUEST_URI";
const std::string FastCGITransport::k_remoteHostKey = "REMOTE_HOST";
const std::string FastCGITransport::k_remoteAddrKey = "REMOTE_ADDR";
const std::string FastCGITransport::k_remotePortKey = "REMOTE_PORT";
const std::string FastCGITransport::k_methodKey = "REQUEST_METHOD";
const std::string FastCGITransport::k_httpVersionKey = "HTTP_VERSION";
const std::string FastCGITransport::k_contentLengthKey = "CONTENT_LENGTH";
const std::string FastCGITransport::k_documentRoot = "DOCUMENT_ROOT";
const std::string FastCGITransport::k_serverNameKey = "SERVER_NAME";
const std::string FastCGITransport::k_serverPortKey = "SERVER_PORT";
const std::string FastCGITransport::k_serverAddrKey = "SERVER_ADDR";
const std::string FastCGITransport::k_httpsKey = "HTTPS";
void FastCGITransport::onHeader(std::unique_ptr<folly::IOBuf> key_chain,
std::unique_ptr<folly::IOBuf> value_chain) {
@@ -308,6 +341,8 @@ void FastCGITransport::handleHeader(const std::string& key,
m_requestURI = value;
} else if (compareKeys(key, k_remoteHostKey)) {
m_remoteHost = value;
} else if (compareKeys(key, k_remoteAddrKey)) {
m_remoteAddr = value;
} else if (compareKeys(key, k_remotePortKey)) {
try {
int remote_port = std::stoi(value);
@@ -321,6 +356,27 @@ void FastCGITransport::handleHeader(const std::string& key,
} catch (std::out_of_range&) {
m_remotePort = 0;
}
} else if (compareKeys(key, k_serverNameKey)) {
m_serverName = value;
} else if (compareKeys(key, k_httpsKey)) {
if (!value.empty()) {
std::string lValue(value);
boost::to_lower(lValue);
// IIS sets this value but sets it to off when SSL is off.
if (lValue.compare("off") != 0) {
setSSL();
}
}
} else if (compareKeys(key, k_serverAddrKey)) {
m_serverAddr = value;
} else if (compareKeys(key, k_serverPortKey)) {
try {
m_serverPort = std::stoi(value);
} catch (std::invalid_argument&) {
m_serverPort = 0;
} catch (std::out_of_range&) {
m_serverPort = 0;
}
} else if (compareKeys(key, k_methodKey)) {
m_extendedMethod = value;
if (compareValues(value, "GET")) {
@@ -348,7 +404,16 @@ void FastCGITransport::handleHeader(const std::string& key,
}
void FastCGITransport::onHeadersComplete() {
m_serverObject = getRawHeader("SCRIPT_NAME");
std::string pathTranslated = getRawHeader("PATH_TRANSLATED");
std::string documentRoot = getRawHeader("DOCUMENT_ROOT");
// use PATH_TRANSLATED - DOCUMENT_ROOT if it is valid instead of SCRIPT_NAME
// for mod_fastcgi support
if (!pathTranslated.empty() && !documentRoot.empty() &&
pathTranslated.find(documentRoot) == 0) {
m_serverObject = pathTranslated.substr(documentRoot.length());
} else {
m_serverObject = getRawHeader("SCRIPT_NAME");
}
std::string queryString = getRawHeader("QUERY_STRING");
if (!queryString.empty()) {
m_serverObject += "?" + queryString;
@@ -48,8 +48,12 @@ public:
virtual const char *getUrl() override;
virtual const char *getRemoteHost() override;
virtual const char *getRemoteAddr() override;
virtual uint16_t getRemotePort() override;
virtual const std::string getDocumentRoot() override;
virtual const char *getServerName() override;
virtual const char *getServerAddr() override;
virtual uint16_t getServerPort() override;
virtual const void *getPostData(int &size) override;
virtual bool hasMorePostData() override;
@@ -66,6 +70,7 @@ public:
virtual std::string getHeader(const char *name) override;
virtual void getHeaders(HeaderMap &headers) override;
virtual void getTransportParams(HeaderMap &serverParams) override;
virtual void addHeaderImpl(const char *name, const char *value) override;
virtual void removeHeaderImpl(const char *name) override;
@@ -107,11 +112,16 @@ private:
static const std::string k_requestURIKey;
static const std::string k_remoteHostKey;
static const std::string k_remoteAddrKey;
static const std::string k_remotePortKey;
static const std::string k_methodKey;
static const std::string k_httpVersionKey;
static const std::string k_contentLengthKey;
static const std::string k_documentRoot;
static const std::string k_serverNameKey;
static const std::string k_serverPortKey;
static const std::string k_serverAddrKey;
static const std::string k_httpsKey;
FastCGIConnection* m_connection;
int m_id;
@@ -121,7 +131,11 @@ private:
std::string m_requestURI;
std::string m_documentRoot;
std::string m_remoteHost;
std::string m_remoteAddr;
uint16_t m_remotePort;
std::string m_serverName;
std::string m_serverAddr;
uint16_t m_serverPort;
Method m_method;
std::string m_extendedMethod;
std::string m_httpVersion;
+51 -10
Ver Arquivo
@@ -377,12 +377,35 @@ void HttpProtocol::CopyHeaderVariables(Variant& server,
}
}
void HttpProtocol::CopyTransportParams(Variant& server,
Transport *transport) {
HeaderMap transportParams;
// Get additional server params from the transport if it has any. In the case
// of fastcgi this is basically a full header list from apache/nginx.
transport->getTransportParams(transportParams);
for (auto const& header : transportParams) {
auto const& key = header.first;
auto const& values = header.second;
auto normalizedKey = string_replace(f_strtoupper(key), s_dash,
s_underscore);
// Be careful here to not overwrite any _SERVER variable
// that has already been set elsewhere and make sure it has a value.
if (!values.empty() && !server.asArrRef().exists(normalizedKey)) {
// When a header has multiple values, we always take the last one.
server.set(normalizedKey, String(values.back()));
}
}
}
void HttpProtocol::CopyServerInfo(Variant& server,
Transport *transport,
const VirtualHost *vhost) {
string hostHeader = transport->getHeader("Host");
String hostName(vhost->serverName(hostHeader));
String serverNameHeader(transport->getServerName());
if (hostHeader.empty()) {
server.set(s_HTTP_HOST, hostName);
@@ -390,19 +413,26 @@ void HttpProtocol::CopyServerInfo(Variant& server,
} else {
StackTraceNoHeap::AddExtraLogging("Server", hostHeader.c_str());
}
if (hostName.empty() || RuntimeOption::ForceServerNameToHeader) {
// Use the header from the transport if it is available
if (!serverNameHeader.empty()) {
hostName = serverNameHeader;
} else if (hostName.empty() || RuntimeOption::ForceServerNameToHeader) {
hostName = hostHeader;
// _SERVER['SERVER_NAME'] shouldn't contain the port number
int colonPos = hostName.find(':');
if (colonPos != String::npos) {
hostName = hostName.substr(0, colonPos);
}
}
// _SERVER['SERVER_NAME'] shouldn't contain the port number
int colonPos = hostName.find(':');
if (colonPos != String::npos) {
hostName = hostName.substr(0, colonPos);
}
StackTraceNoHeap::AddExtraLogging("Server_SERVER_NAME", hostName.data());
server.set(s_GATEWAY_INTERFACE, s_CGI_1_1);
server.set(s_SERVER_ADDR, String(RuntimeOption::ServerPrimaryIP));
server.set(s_SERVER_ADDR, transport->getServerAddr());
server.set(s_SERVER_NAME, hostName);
server.set(s_SERVER_PORT, RuntimeOption::ServerPort);
server.set(s_SERVER_PORT, transport->getServerPort());
server.set(s_SERVER_SOFTWARE, s_HPHP);
server.set(s_SERVER_PROTOCOL, "HTTP/" + transport->getHTTPVersion());
server.set(s_SERVER_ADMIN, empty_string);
@@ -411,8 +441,17 @@ void HttpProtocol::CopyServerInfo(Variant& server,
void HttpProtocol::CopyRemoteInfo(Variant& server,
Transport *transport) {
server.set(s_REMOTE_ADDR, String(transport->getRemoteHost(), CopyString));
server.set(s_REMOTE_HOST, empty_string); // I don't think we need to nslookup
String remoteAddr(transport->getRemoteAddr(), CopyString);
String remoteHost(transport->getRemoteHost(), CopyString);
if(remoteAddr.empty()) {
remoteAddr = remoteHost;
}
server.set(s_REMOTE_ADDR, remoteAddr);
if(!remoteHost.empty()) {
server.set(s_REMOTE_HOST, remoteHost);
}
server.set(s_REMOTE_PORT, transport->getRemotePort());
}
@@ -601,6 +640,8 @@ void HttpProtocol::PrepareServerVariable(Variant& server,
iter != vServerVars.end(); ++iter) {
server.set(String(iter->first), String(iter->second));
}
// Do this last as to not overwrite any existing server variables.
CopyTransportParams(server, transport);
sri.setServerVariables(server);
const char *threadType = transport->getThreadTypeName();
+2
Ver Arquivo
@@ -60,6 +60,8 @@ public:
const VirtualHost *vhost);
static void CopyHeaderVariables(Variant& server,
const HeaderMap& headers);
static void CopyTransportParams(Variant& server,
Transport *transport);
static void CopyServerInfo(Variant& server,
Transport *transport,
const VirtualHost *vhost);
+20 -4
Ver Arquivo
@@ -84,10 +84,10 @@ public:
virtual ~Transport();
void onRequestStart(const timespec &queueTime);
const timespec &getQueueTime() const { return m_queueTime;}
const timespec &getWallTime() const { return m_wallTime;}
const timespec &getCpuTime() const { return m_cpuTime;}
const int64_t &getInstructions() const { return m_instructions;}
const timespec &getQueueTime() const { return m_queueTime; }
const timespec &getWallTime() const { return m_wallTime; }
const timespec &getCpuTime() const { return m_cpuTime; }
const int64_t &getInstructions() const { return m_instructions; }
const int64_t &getSleepTime() const { return m_sleepTime; }
void incSleepTime(unsigned int seconds) { m_sleepTime += seconds; }
const int64_t &getuSleepTime() const { return m_usleepTime; }
@@ -109,9 +109,24 @@ public:
virtual const char *getUrl() = 0;
virtual const char *getRemoteHost() = 0;
virtual uint16_t getRemotePort() = 0;
// The transport can override REMOTE_ADDR if it has one
virtual const char *getRemoteAddr() { return ""; }
// The transport can override the virtualhosts' docroot
virtual const std::string getDocumentRoot() { return ""; }
/**
* Server Headers
*/
virtual const char *getServerName() {
return "";
};
virtual const char *getServerAddr() {
return RuntimeOption::ServerPrimaryIP.c_str();
};
virtual uint16_t getServerPort() {
return RuntimeOption::ServerPort;
};
/**
* POST request's data.
*/
@@ -141,6 +156,7 @@ public:
*/
virtual std::string getHeader(const char *name) = 0;
virtual void getHeaders(HeaderMap &headers) = 0;
virtual void getTransportParams(HeaderMap &serverParams) {};
/**
+2 -2
Ver Arquivo
@@ -1817,11 +1817,11 @@
},
{
"name": "HPHP_VERSION",
"value": "2.3.2"
"value": "2.3.3"
},
{
"name": "HHVM_VERSION",
"value": "2.3.2"
"value": "2.3.3"
},
{
"name": "HTML_ENTITIES",
@@ -0,0 +1,25 @@
<?php
$xml = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "XXE_URI">]>
<foo>&xxe;</foo>
EOT;
$xml = str_replace('XXE_URI', __DIR__ . '/libxml_disable_entity_loader_payload.txt', $xml);
function parseXML($xml) {
$doc = new DOMDocument();
$doc->resolveExternals = true;
$doc->substituteEntities = true;
$doc->validateOnParse = false;
$doc->loadXML($xml, 0);
return $doc->saveXML();
}
var_dump(strpos(parseXML($xml), 'SECRET_DATA') !== false);
var_dump(libxml_disable_entity_loader(true));
var_dump(strpos(parseXML($xml), 'SECRET_DATA') === false);
echo "Done\n";
?>
@@ -0,0 +1,7 @@
bool(true)
bool(false)
I/O warning : failed to load external entity "%s"
HipHop Warning: %s
HipHop Warning: %s
bool(true)
Done
@@ -0,0 +1 @@
<?php if (!extension_loaded('simplexml') || !extension_loaded('dom') || defined('PHP_WINDOWS_VERSION_MAJOR')) die('skip'); ?>
@@ -0,0 +1 @@
SECRET_DATA
+1 -1
Ver Arquivo
@@ -1 +1 @@
HHVM_VERSION(2.3.2)
HHVM_VERSION(2.3.3)