Add sub-controls for Hack array compat runtime checks
[hiphop-php.git] / hphp / runtime / base / request-injection-data.h
blob306478b0d8554a5595f050c4ca0be3c89876e4fc
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_REQUEST_INJECTION_DATA_H_
18 #define incl_HPHP_REQUEST_INJECTION_DATA_H_
20 #include "hphp/runtime/base/rds-header.h"
21 #include "hphp/runtime/base/surprise-flags.h"
22 #include "hphp/runtime/vm/async-flow-stepper.h"
23 #include "hphp/runtime/vm/pc-filter.h"
25 #include <atomic>
26 #include <cassert>
27 #include <cinttypes>
28 #include <cstddef>
29 #include <cstdlib>
30 #include <stack>
31 #include <string>
32 #include <vector>
34 #ifdef __APPLE__
35 # include <dispatch/dispatch.h>
36 #elif defined(_MSC_VER)
37 # include <agents.h>
38 # include <ppltasks.h>
39 #endif
41 namespace HPHP {
43 //////////////////////////////////////////////////////////////////////
45 struct RequestInjectionData;
47 //////////////////////////////////////////////////////////////////////
49 struct RequestTimer {
50 friend struct RequestInjectionData;
52 #if defined(__APPLE__) || defined(_MSC_VER)
53 RequestTimer(RequestInjectionData*);
54 #else
55 RequestTimer(RequestInjectionData*, clockid_t);
56 #endif
58 ~RequestTimer();
60 void setTimeout(int seconds);
61 void onTimeout();
62 int getRemainingTime() const;
64 private:
65 RequestInjectionData* m_reqInjectionData;
66 int m_timeoutSeconds{0};
68 #if defined(__APPLE__)
69 void cancelTimerSource();
70 dispatch_source_t m_timerSource{nullptr};
71 dispatch_group_t m_timerGroup;
72 #elif defined(_MSC_VER)
73 concurrency::task_completion_event<void>* m_tce{nullptr};
74 #else
75 clockid_t m_clockType;
76 timer_t m_timerId;
77 TYPE_SCAN_IGNORE_FIELD(m_timerId); // timer_t is void*
79 /* Whether we've created our timer yet. */
80 bool m_hasTimer{false};
82 /* Set true when we activate a timer, cleared when the signal handler runs. */
83 std::atomic<bool> m_timerActive{false};
84 #endif
87 //////////////////////////////////////////////////////////////////////
90 * General-purpose bag of data and options for a request.
92 * This class contains a lot of debugger data that must be accessed via getter
93 * and setter methods. Updating data like the "debugger attached" field
94 * dynamically affects whether the request will use the JIT or not.
96 * Refrain from adding more fields to this class if you can help it. It's a
97 * better idea to add request local data to whatever extension you're working
98 * on.
100 struct RequestInjectionData {
101 /* The state of the step out command. */
102 enum class StepOutState : int8_t {
103 /* Command is inactive. */
104 None,
105 /* Waiting for the corresponding function to exit. */
106 Stepping,
107 /* We have stepped out and will break on the next valid opcode. */
108 Out,
111 RequestInjectionData()
112 #if defined(__APPLE__) || defined(_MSC_VER)
113 : m_timer(this)
114 , m_cpuTimer(this)
115 #else
116 : m_timer(this, CLOCK_REALTIME)
117 , m_cpuTimer(this, CLOCK_THREAD_CPUTIME_ID)
118 #endif
121 ~RequestInjectionData() = default;
123 static constexpr uint32_t debuggerReadOnlyOffset() {
124 return offsetof(RequestInjectionData, m_debuggerAttached);
127 void reset();
129 void onSessionInit();
131 void threadInit();
133 int getTimeout() const;
134 void setTimeout(int seconds);
136 int getCPUTimeout() const;
137 void setCPUTimeout(int seconds);
139 int getRemainingTime() const;
140 int getRemainingCPUTime() const;
142 void resetTimer(int seconds = 0);
143 void resetCPUTimer(int seconds = 0);
145 void onTimeout(RequestTimer*);
148 * Intended to be used by threads other than the current thread. To get
149 * surprise flags for the current thread, use stackLimitAndSurprise() instead.
151 void clearFlag(SurpriseFlag);
152 void setFlag(SurpriseFlag);
155 * Whether the JIT is enabled.
157 bool getJit() const;
158 void updateJit();
161 * Whether the JIT is performing function folding.
163 bool getJitFolding() const;
164 void setJitFolding(bool);
167 * Whether to suppress the emission of Hack array compat notices.
169 bool getSuppressHackArrayCompatNotices() const;
170 void setSuppressHackArrayCompatNotices(bool);
173 * Whether coverage is being collected.
175 bool getCoverage() const;
176 void setCoverage(bool);
179 * Whether there is a debugger attached to the request. Controlled by
180 * DebuggerHook. This field gets read directly by JIT'd code.
182 bool getDebuggerAttached();
183 void setDebuggerAttached(bool);
186 * Returns true if the debugger should force interrupts due to any of the
187 * debugger interrupt conditions being true.
189 bool getDebuggerForceIntr() const;
192 * Indicating we should force interrupts for debuggers. This is intended to
193 * be used by debuggers for forcing onOpcode events.
195 bool getDebuggerIntr() const;
196 void setDebuggerIntr(bool);
199 * Whether the debugger is running a "step in" command.
201 bool getDebuggerStepIn() const;
202 void setDebuggerStepIn(bool);
205 * Whether the debugger is running a "next" command.
207 bool getDebuggerNext() const;
208 void setDebuggerNext(bool);
211 * Whether the debugger is running a "step out" command, and where it is in
212 * the process.
214 StepOutState getDebuggerStepOut() const;
215 void setDebuggerStepOut(StepOutState);
218 * The stack depth registered by the debugger's most recent flow command.
219 * (e.g. step, next, etc.)
221 int getDebuggerFlowDepth() const;
222 void setDebuggerFlowDepth(int);
225 * Set to a line number if the request has hit a line breakpoint on the line,
226 * and hasn't left that line yet. This tracks a single line per stack frame.
227 * If there's no tracked line, then it is treated as line number -1.
229 int getActiveLineBreak() const;
230 void clearActiveLineBreak();
231 void setActiveLineBreak(int);
234 * Adds a slot to the active line stack upon entering or leaving a function.
236 void popActiveLineBreak();
237 void pushActiveLineBreak();
240 * Uses the active line break stack to compute the size of the stack when in
241 * debug mode.
243 size_t getDebuggerStackDepth() const;
245 /* Getters and setters for user settable INI settings. */
247 const std::string& getDefaultMimeType() const;
249 std::string getDefaultIncludePath();
250 const std::vector<std::string>& getIncludePaths() const;
252 int64_t getErrorReportingLevel();
253 void setErrorReportingLevel(int64_t);
255 int64_t getMemoryLimitNumeric() const;
256 void setMemoryLimit(folly::StringPiece);
258 const std::string& getVariablesOrder() const;
259 void setVariablesOrder(const std::string&);
261 const std::string& getRequestOrder() const;
262 void setRequestOrder(const std::string&);
264 int64_t getSocketDefaultTimeout() const;
266 const std::string& getUserAgent() const;
267 void setUserAgent(const std::string&);
269 const std::string& getTimeZone() const;
270 void setTimeZone(const std::string&);
272 bool setAllowedDirectories(const std::string& value);
274 const std::vector<std::string>& getAllowedDirectoriesProcessed() const;
276 // When safe file access is enabled only whitelisted by setAllowedDirectories
277 // may be modified
278 void setSafeFileAccess(bool b);
279 bool hasSafeFileAccess() const;
280 bool hasTrackErrors() const;
281 bool hasHtmlErrors() const;
283 bool logFunctionCalls() const;
285 private:
286 RequestTimer m_timer;
287 RequestTimer m_cpuTimer;
289 bool m_debuggerAttached{false};
290 bool m_coverage{false};
291 bool m_jit{false};
292 bool m_jitFolding{false};
293 bool m_debuggerIntr{false};
294 bool m_suppressHackArrayCompatNotices{false};
296 bool m_debuggerStepIn{false};
297 bool m_debuggerNext{false};
298 StepOutState m_debuggerStepOut{StepOutState::None};
300 public:
301 PCFilter m_breakPointFilter;
302 PCFilter m_flowFilter;
303 PCFilter m_lineBreakPointFilter;
304 PCFilter m_callBreakPointFilter;
305 PCFilter m_retBreakPointFilter;
306 // Only allow one async stepper at a time.
307 AsyncFlowStepper m_asyncStepper;
309 private:
310 int m_debuggerFlowDepth{0};
312 /* INI settings. */
313 bool m_logErrors{false};
314 bool m_trackErrors{false};
315 bool m_htmlErrors{false};
316 bool m_safeFileAccess{false};
317 bool m_logFunctionCalls{false};
319 /* Pointer to surprise flags stored in RDS. */
320 std::atomic<size_t>* m_sflagsAndStkPtr{nullptr};
322 std::stack<int> m_activeLineBreaks;
324 /* Things corresponding to user settable INI settings. */
326 std::string m_maxMemory;
327 std::string m_argSeparatorOutput;
328 std::string m_argSeparatorInput;
329 std::string m_variablesOrder;
330 std::string m_requestOrder;
331 std::string m_defaultCharset;
332 std::string m_defaultMimeType;
333 std::string m_brotliEnabled;
334 std::string m_brotliChunkedEnabled;
335 std::string m_gzipCompressionLevel = "-1";
336 std::string m_gzipCompression;
337 std::string m_errorLog;
338 std::string m_userAgent;
339 std::string m_timezone;
340 std::vector<std::string> m_include_paths;
341 struct AllowedDirectoriesInfo {
342 AllowedDirectoriesInfo(std::vector<std::string>&& v,
343 std::string&& s) :
344 vec(std::move(v)), string(std::move(s)) {}
345 std::vector<std::string> vec;
346 std::string string;
348 std::unique_ptr<AllowedDirectoriesInfo> m_allowedDirectoriesInfo;
349 int64_t m_errorReportingLevel;
350 int64_t m_socketDefaultTimeout;
351 int64_t m_maxMemoryNumeric;
352 int64_t m_zendAssertions;
353 int64_t m_brotliLgWindowSize;
354 int64_t m_brotliQuality;
357 * Keep track of the open_basedir_separator that may be used so we can
358 * have backwards compatibility with our current ;.
359 * This is a simple fix with the caveat that we don't mix the characters
360 * in an ini file or ini_set().
361 * Moving forward we should just use s_PATH_SEPARATOR and support only that
363 std::string m_open_basedir_separator;
365 public:
366 /* CmdInterrupts this thread is handling. */
367 std::stack<void*> interrupts;
370 //////////////////////////////////////////////////////////////////////
374 #define incl_HPHP_REQUEST_INJECTION_DATA_INL_H_
375 #include "hphp/runtime/base/request-injection-data-inl.h"
376 #undef incl_HPHP_REQUEST_INJECTION_DATA_INL_H_
378 #endif