Abstract
Hyperproperties, such as noninterference and observational determinism, relate multiple computation traces with each other and are thus not monitorable by tools that consider computations in isolation. We present the monitoring approach implemented in the latest version of \(\text {RVHyper}\), a runtime verification tool for hyperproperties. The input to the tool are specifications given in the temporal logic \(\text {HyperLTL}\), which extends lineartime temporal logic (LTL) with trace quantifiers and trace variables. \(\text {RVHyper}\) processes execution traces sequentially until a violation of the specification is detected. In this case, a counterexample, in the form of a set of traces, is returned. \(\text {RVHyper}\) employs a range of optimizations: a preprocessing analysis of the specification and a procedure that minimizes the traces that need to be stored during the monitoring process. In this article, we introduce a novel trace storage technique that arranges the traces in a treelike structure to exploit partially equal traces. We evaluate \(\text {RVHyper}\) on existing benchmarks on secure information flow control, error correcting codes, and symmetry in hardware designs. As an example application outside of security, we show how \(\text {RVHyper}\) can be used to detect spurious dependencies in hardware designs.
Similar content being viewed by others
1 Introduction
Hyperproperties [10] are widely studied in (but not limited to) the context of secure information flow control. They generalize trace properties in that they not only check the correctness of individual computation traces in isolation, but relate multiple computation traces to each other. Examples include information flow policies, such as observational determinism [33, 34, 42], (quantitative) noninterference [33, 36, 41] as well as symmetry [26] and spurious dependencies in hardware designs [23], error correcting codes [26], and antidoping of automotive software [14].
In this article, we present the monitoring approach implemented in the latest version of \(\text {RVHyper}\), an automatabased monitoring tool for hyperproperties [24]. In dynamic verification of hyperproperties, efficient and lightweight monitoring techniques are instrumented in systems, which are usually far beyond the scope of static verification approaches. By doing so, countermeasures are enacted before, for example, irreparable information leaks happen. A runtime verification tool for hyperproperties is in particular useful if the implementation of a security critical system is not available. Even without access to the source code, monitoring the observable execution traces still detects insecure information flow. \(\text {RVHyper}\) also supports the verification workflow by providing a method to test and develop specifications: Specifications can be checked on sample traces without the need for a complete model. Based on the feedback of \(\text {RVHyper}\), the specification can be refined until it matches the intended meaning.
The input of \(\text {RVHyper}\) is given in the temporal logic \(\text {HyperLTL}\) [9], which expresses temporal hyperproperties by extending lineartime temporal logic with explicit trace quantification (see [11] for a recent study of hyperlogics). HyperLTL has been used extensively to specify hyperproperties of practical interest (e.g. [14, 21, 23,24,25,26]). For example, observational determinism is expressed as the following formula:
stating that every trace pair \(\pi ,\pi '\) has to agree on the output as long as it agrees on the inputs as well. When detecting a violation, \(\text {RVHyper}\) outputs a counterexample, which is a set of traces that does not satisfy the input formula.
Efficient model checking, synthesis, and satisfiability checking tools for HyperLTL already exist [12, 19,20,21,22, 25, 26]. Implementing an efficient runtime verification tool for HyperLTL specifications is, despite recent theoretical progress [1, 5,6,7, 24, 28, 29, 37], difficult: In principle, the monitor not only needs to process every observed trace, but must also store every trace observed so far, so that future traces can be compared with the traces seen so far.
The previous version of \(\text {RVHyper}\) tackles this challenging problem by implementing two optimizations [23, 24]: a specification analysis to detect exploitable properties of a hyperproperty, such as symmetry and a trace analysis, which detects all redundant traces that can be omitted during the monitoring process. A limitation of the trace analysis, which is based on a language inclusion check, is that only entire traces can be analyzed and pruned. For example, consider the traces \(t_1 = \{a\}\{a\}\{\}\) and \(t_2 = \{a\}\{\}\{a\}\) of length 3 and the HyperLTL formula \(\forall \pi . \forall \pi '. \square ( a_\pi \rightarrow \lnot b_{\pi '} )\). Neither \(t_1\) nor \(t_2\) is dominated by the other trace, in the sense of the trace analysis, i.e., that one of the traces poses strictly less requirements on future traces [24]. The traces, however, are equal on the first position. This provides an opportunity for optimization, which our new approach exploits. We introduce a novel trace storage technique (that also has massive impact on the running time), such that \(\text {RVHyper}\) can also handle partially equal traces by storing them in a tree structure.
We evaluate \(\text {RVHyper}\) on existing benchmarks such as classical information flow security by checking for violations of noninterference or monitoring errorresistant encoder. \(\text {HyperLTL}\) is, however, not limited to security policies. As an example of such an application beyond security, we show how \(\text {RVHyper}\) can be used to detect spurious dependencies in hardware designs.
Structure of this article The remainder of this article is structured as follows. We begin by giving preliminaries on \(\text {HyperLTL}\), its finite trace semantics and notation in Sect. 2. In Sect. 3, we present automatabased monitoring approach implemented in \(\text {RVHyper}\), before discussing optimizations in Sect. 4 that make the monitoring feasible in practice. In Sect. 5, we evaluate \(\text {RVHyper}\) with a focus on the novel storage optimization technique using our tree data structure.
This is a revised and extended version of a paper that appeared at TACAS 2018 [23]. Our contribution and extension compared to [23] is the inclusion of a new trace storage optimization technique presented in Sect. 4.2 and an extended evaluation in Sect. 5.
Related work The temporal logic \(\text {HyperLTL}\) was introduced to model check security properties of reactive systems [9, 26]. For one of its predecessors, \(\text {SecLTL}\) [16], there has been a proposal for a whitebox monitoring approach [17] based on alternating automata. A recent survey on algorithms for monitoring hyperproperties is given in [28]. Agrawal and Bonakdarpour [1] were the first to study the monitoring problem of HyperLTL for the sequential model. They give a syntactic characterization of monitorable \(\text {HyperLTL}\) formulas. They present a first monitoring algorithm based on a progression logic expressing trace interdependencies and the composition of an LTL\(_3\) monitor. A first constraintbased approach has been outlined in [7], which works for a subclass of HyperLTL specifications. The idea is to identify a set of propositions of interest and store corresponding constraints. A constraintbased algorithm for the complete fragment of \(\forall ^2\) HyperLTL formulas has been proposed in [29]. The algorithms rewrite a HyperLTL formula and an incoming event into a constraint composed of a plain LTL requirement as well as a HyperLTL requirement. An constraint system is built incrementally: The HyperLTL part is encoded with variables, which will be incrementally defined with more incoming events of a trace. Like with our monitoring algorithm, they do not have access to the implementation (black box), but in contrast to our work, they do not provide witnessing traces as a monitor verdict.
In [5], the authors study the complexity of monitoring hyperproperties. They show that the form and size of the input as well as the formula have a significant impact on the feasibility of the monitoring process. They differentiate between several input forms and study their complexity: a set of linear traces, treeshaped Kripke structures, and acyclic Kripke structures. For acyclic structures and alternationfree HyperLTL formulas, the problems complexity gets as low as NC.In [6, 37], the authors study where static analysis can be combined with runtime verification techniques to monitor HyperLTL formulas beyond the alternationfree fragment.
For certain information flow policies, like noninterference and some extensions, dynamic enforcement mechanisms have been proposed. Techniques for the enforcement of information flow policies include tracking dependencies at the hardware level [38], languagebased monitors [2,3,4, 35, 40], and abstractionbased dependency tracking [8, 27, 30]. Secure multiexecution [15] is a technique that can enforce noninterference by executing a program multiple times in different security levels. To enforce noninterference, the inputs are replaced by default values whenever a program tries to read from a higher security level.
2 Preliminaries
Let AP be a finite set of atomic propositions, and let \(\Sigma = 2^\text {AP}\) be the corresponding alphabet. An infinite trace \(t \in \Sigma ^\omega \) is an infinite sequence over the alphabet. A subset \(T \subseteq \Sigma ^\omega \) is called a trace property. A hyperproperty \(H \subseteq 2^{(\Sigma ^\omega )}\) is a generalization of a trace property. A finite trace \(t \in \Sigma ^+\) is a finite sequence over \(\Sigma \). In the case of finite traces, t denotes the length of a trace. We use the following notation to access and manipulate traces: Let t be a trace and i be a natural number. t[i] denotes the ith element of t. Therefore, t[0] represents the first element of the trace. Let j be natural number. If \(j \ge i\) and \(i\le t\), then t[i, j] denotes the sequence \(t[i] t[i+1] \cdots t[\mathrm{min}(j,t1)]\). Otherwise, it denotes the empty trace \(\epsilon \). \(t[i\rangle \) denotes the suffix of t starting at position i. For two finite traces s and t, we denote their concatenation by \(s \cdot t\).
HyperLTL syntax HyperLTL [9] extends LTL with trace variables and trace quantifiers. Let \({\mathcal {V}}\) be a finite set of trace variables. The syntax of HyperLTL is given by the grammar
where \(a \in \text {AP}\) is an atomic proposition and \(\pi \in {\mathcal {V}}\) is a trace variable. Atomic propositions are indexed by trace variables. The explicit trace quantification enables us to express properties like “on all traces \(\varphi \) must hold,” expressed by \(\forall \pi \mathpunct {.}\varphi \). Dually, we can express “there exists a trace such that \(\varphi \) holds,” expressed by \(\exists \pi \mathpunct {.}\varphi \). We use the standard derived operators release \(\varphi {\mathcal {R}} \psi :=\lnot (\lnot \varphi {\mathcal {U}} \lnot \psi )\), eventually \(\diamondsuit \varphi :=\text {true} {\mathcal {U}} \varphi \), globally \(\square \varphi :=\lnot \diamondsuit \lnot \varphi \), and weak until \(\varphi _1 {\mathcal {W}} \varphi _2 :=(\varphi _1 {\mathcal {U}} \varphi _2) \vee \square \varphi _1\). As we use the finite trace semantics, \(\bigcirc \varphi \) denotes the strong version of the next operator, i.e., if a trace ends before the satisfaction of \(\varphi \) can be determined, the satisfaction relation, defined below, evaluates to false. To enable duality in the finite trace setting, we additionally use the weak next operator \(\tilde{\bigcirc }\varphi \) which evaluates to true if a trace ends before the satisfaction of \(\varphi \) can be determined and is defined as \(\tilde{\bigcirc }\varphi :=\lnot \bigcirc \lnot \varphi \). We call \(\psi \) of a HyperLTL formula \(\mathbf {Q}. \psi \), with an arbitrary quantifier prefix \(\mathbf {Q}\), the body of the formula. A HyperLTL formula \(\mathbf {Q}. \psi \) is in the alternationfree fragment if either \(\mathbf {Q}\) consists solely of universal quantifiers or solely of existential quantifiers. We also denote the respective alternationfree fragments as the \(\forall ^n\) fragment and the \(\exists ^n\) fragment, with n being the number of quantifiers in the prefix.
Finite trace semantics We recap the finite trace semantics for HyperLTL [7], which is itself based on the finite trace semantics of \(\text {LTL}\) [32]. Let \(\Pi _\text {fin}: {\mathcal {V}}\rightarrow \Sigma ^+\) be a partial function mapping trace variables to finite traces. We define \(\epsilon [0]\) as the empty set. \(\Pi _\text {fin}[i\rangle \) denotes the trace assignment that is equal to \(\Pi _\text {fin}(\pi )[i\rangle \) for all \(\pi \in \mathrm{dom}(\Pi _\text {fin})\). By slight abuse of notation, we write \(t \in \Pi _\text {fin}\) to access traces t in the image of \(\Pi _\text {fin}\). The satisfaction of a HyperLTL formula \(\varphi \) over a finite trace assignment \(\Pi _\text {fin}\) and a set of finite traces T, denoted by \(\Pi _\text {fin}\vDash _T \varphi \), is defined as follows:
The hyperproperty represented by a \(\text {HyperLTL}\) formula \(\varphi \), denoted by \(\mathcal {H}(\varphi )\), is the set \(\{{ T \subseteq \Sigma ^\omega \mid T \vDash \varphi }\}\).
3 Runtime verification of hyperproperties with \(\text {RVHyper}\)
In this section, we present an overview over \(\text {RVHyper}\), before describing the implementation setup, present the monitoring algorithm, and discuss our optimization techniques.
The input of \(\text {RVHyper}\) is given as a universally quantified HyperLTL formula and, in addition, the observed behavior of the system under consideration. The observed behavior is represented as a trace set T, where each \(t \in T\) represents a previously observed execution of the system to monitor. \(\text {RVHyper}\) can therefore detect violations of every monitorable ksafety hyperproperty (see [24] for an extensive study of monitorability of hyperproperties). If \(\text {RVHyper}\) detects that the system violates the hyperproperty, it outputs a counterexample, i.e., a kary tuple of traces, where k is the number of quantifiers in the HyperLTL formula.
3.1 Implementation details
\(\text {RVHyper}\)^{Footnote 1} is written in C++. We use spot [18] for building the deterministic monitor automata and the Buddy BDD library for handling symbolic constraints. We use the \(\text {HyperLTL}\) satisfiability solver \(\text {EAHyper}\) [19, 22] to determine whether the input formula is reflexive, symmetric, or transitive. Depending on those results, we omit redundant tuples in the monitoring algorithm.
3.2 Online monitoring algorithm
For the online algorithm, we use standard techniques for building LTL monitoring automata and use this to instantiate this monitor by the traces as specified by the \(\text {HyperLTL}\) formula. Let \(\text {AP}\) be a set of atomic propositions and \({\mathcal {V}}= \{\pi _1, \ldots , \pi _n\}\) a set of trace variables. A deterministic monitor template \(\mathcal {M}= (\Sigma , Q, \delta , q_0, F)\) is a tuple of a finite alphabet \(\Sigma = 2^{(\text {AP}\times {\mathcal {V}})}\), a nonempty set of states Q, a partial transition function \(\delta : Q \times \Sigma \hookrightarrow Q\), a designated initial state \(q_0 \in Q\), and a set of accepting states \(F \subseteq Q\). The instantiated automaton runs in parallel over traces in \((2^\text {AP})^*\), and thus, we define a run with respect to a nary tuple \(N \in ((2^\text {AP})^*)^n\) of finite traces. A run of N is a sequence of states \(q_0 q_1 \cdots q_m \in Q^*\), where m is the length of the smallest trace in N, starting in the initial state \(q_0\) such that for all i with \(0 \le i < m\), it holds that
A tuple N is accepted if there is a run on \(\mathcal {M}\) that ends in an accepting state. For LTL, such a deterministic monitor can be constructed in doubly exponential time in the size of the formula [13, 39].
Example 1
As an example formula, consider again the observational determinism formula introduced in the introduction:
The corresponding monitor template is depicted in Fig. 1.
The algorithm for monitoring \(\text {HyperLTL}\) formulas when traces are given sequentially to the monitor is presented as Algorithm 1. After building the deterministic monitoring automaton \(\mathcal {M}_\varphi \), the algorithm accepts new traces and afterward proceeds with the pace of the incoming stream. We have a variable S that maps tuples of traces to states of the deterministic monitor. Whenever the current trace t progresses, we progress every tuple \((t_1,\ldots ,t_n)\) that contains t with one of the following outcomes:

1.
One of the traces \(t_1,\ldots ,t_n\) may have ended, and thus, we check if the monitor is in an accepting state and report a violation if this is not the case.

2.
There is a successor state in the monitor, and thus, we update S.

3.
There is no successor state, and hence, we report a violation.
When a new trace t starts, only new tuples are considered for S that are tuples \(\mathbf {t} \in (T \cup \{{t}\})^n\) containing the new trace t.
Example 2
We continue Example 1 by showing how the algorithm progresses on the given formula. Assume for the sake of readability that we have a single input proposition i and a single output proposition o. Furthermore, assume that we have already seen the trace \(t_0 = \{{i}\}\{{i,o}\}\{{o}\}\), that is, \(T = \{{t_0}\}\) and \(S(t_0,t_0) = q_0\). We now show how the algorithm continues with a fresh trace \(t_1\). In lines 6–8, we add the pairs \((t_0,t_1)\), \((t_0,t_1)\), and \((t_1,t_1)\) with the initial state \(q_0\) to S. Let \(p = \{{i}\}\) be the first input proposition; thus, \(t_1 = \{{i}\}\). Since \(t_0[0] = t_1[0]\), the monitor remains in \(q_0\) for every tuple. Let \(p = \{{i}\}\) be the next input proposition; thus, \(t_1 = \{{i}\}\{{i}\}\). Consider the tuple \((t_0,t_1)\). As \(t_0[1]\) and \(t_1[1]\) are equal with respect to i but differ in o, the monitor progresses to the rejecting state \(q_\bot \) and the algorithm terminates by reporting the violation. If the previous input proposition is \(p = \{{}\}\), both tuples \((t_0,t_1)\) and \((t_1,t_0)\) would progress to the accepting sink state \(q_\top \) as the input proposition is different to \(t_0[1]\). Assume two more inputs, e.g., \(t_1 = \{{i}\}\{{i}\}\{{}\}\{{}\}\); then the pairs \((t_0,t_0)\), \((t_0,t_1)\), and \((t_1,t_0)\) are removed from S as \(t_1\) is strict longer than \(t_0\).
4 Optimizations
In this section, we present three optimizations implemented in \(\text {RVHyper}\), which, as we will see in the evaluation section, are necessary to make the automatabased monitoring approach feasible in practice. We begin by explaining a specification analysis, which is a preprocessing step that exploits properties of the specification to reduce the algorithmic workload. In the subsequent section, we show how \(\text {RVHyper}\) tackles the problem of potentially unbounded memory consumption: We recap the trace analysis, which was so far the only storage optimization implemented in \(\text {RVHyper}\). We then provide a novel storage optimization technique based on prefix trees, socalled tries, to exploit partial equality of the given traces.
4.1 Specification analysis
In the example execution in Example 2, we have seen that the algorithm had to do more work than necessary to monitor observational determinism. For example, a tuple (t, t) for some trace t cannot violate observational determinism as the traces are equal. Further, from the pairs \((t,t')\) and \((t',t)\) for some traces t and \(t'\), we only need to check one of them as a violation in one of them implies the violation in the other pair. We can automatically check for such conditions and, thus, omit unnecessary work.
\(\text {RVHyper}\) implements the specification analysis with the HyperLTL satisfiability solver EAHyper [19, 22]. The specification analysis is a preprocessing step that analyzes the HyperLTL formula under consideration. EAHyper can detect whether a formula is (1) symmetric, i.e., we halve the number of instantiated monitors, (2) transitive, i.e., we reduce the number of instantiated monitors to two, or (3) reflexive, i.e., we can omit the selfcomparison of traces.
Definition 1
[24] Let \(\psi \) be the quantifierfree part of some \(\text {HyperLTL}\) formula \(\varphi \) over trace variables \({\mathcal {V}}\). We say \(\varphi \) is invariant under trace variable permutation \(\sigma : {\mathcal {V}}\rightarrow {\mathcal {V}}\), if for any set of traces \(T \subseteq \Sigma ^{\omega }\) and any assignment \(\Pi : {\mathcal {V}}\rightarrow T\), \((\emptyset , \Pi , 0) \vDash \psi \Leftrightarrow (\emptyset , \Pi \circ \sigma , 0) \vDash \psi \). We say \(\varphi \) is symmetric, if it is invariant under every trace variable permutation in \({\mathcal {V}}\).
Symmetry is particularly interesting since many information flow policies satisfy this property. Consider, for example, observational determinism: \( \forall \pi \mathpunct {.}\forall \pi '\mathpunct {.}(o_\pi = o_{\pi '}) {\mathcal {W}}(i_\pi \ne i_{\pi '})\). \(\text {RVHyper}\) detects symmetry by translating this formula to a formula that is unsatisfiable if there exists no set of traces for which every trace pair violates the symmetry condition: \( \exists \pi \mathpunct {.}\exists \pi '\mathpunct {.}\big ((o_\pi = o_{\pi '}) {\mathcal {W}}(i_\pi \ne i_{\pi '})\big ) \nleftrightarrow \big ((o_\pi = o_{\pi '}) {\mathcal {W}}(i_\pi \ne i_{\pi '})\big ) \). If the resulting formula turns out to be unsatisfiable, \(\text {RVHyper}\) omits the symmetric instantiations of the monitor automaton.
Definition 2
[24] Let \(\psi \) be the quantifierfree part of some \(\text {HyperLTL}\) formula \(\varphi \) over trace variables \(\{{\pi _1, \pi _2}\}\). Let \(T = \{{t_1, t_2, t_3}\} \in \Sigma ^{\omega }\) be a threeelemented set of traces. We define the assignment \(\Pi _{i,j} : {\mathcal {V}}\rightarrow \Sigma ^{\omega }\) by \(\Pi _{i,j} :=\{\pi _1 \mapsto t_i, \pi _2 \mapsto t_j\}\). We say \(\varphi \) is transitive, if for all threeelemented sets T it holds that \((\emptyset , \Pi _{1,2}, 0) \vDash \psi \wedge (\emptyset , \Pi _{2,3}, 0) \vDash \psi \rightarrow (\emptyset , \Pi _{1,3}, 0) \vDash \psi \).
While symmetric HyperLTL formulas allow us to prune half of the monitor instances, transitivity of a HyperLTL formula has an even larger impact on the required memory. Equality, i.e., \(\forall \pi . \forall \pi ' \mathpunct {.}\square (a_\pi \leftrightarrow a_{\pi '})\), for example, is transitive and symmetric and allows us to reduce the number of monitor instances to one, since we can check equality against any reference trace.
Definition 3
[24] Let \(\psi \) be the quantifierfree part of some \(\text {HyperLTL}\) formula \(\varphi \) over trace variables \({\mathcal {V}}\). We say \(\varphi \) is reflexive, if for any trace \(t \in \Sigma ^{\omega }\) and the corresponding assignment \(\Pi : {\mathcal {V}}\rightarrow \{t\}\), \((\emptyset , \Pi , 0) \vDash \psi \).
Lastly, if a formula is reflexive, \(\text {RVHyper}\) omits the composition of a trace with itself during the monitoring process. For example, equality and observational determinism have reflexive HyperLTL formulas.
Example 3
Consider again the observational determinism formula from Example 1. We have seen that this formula is both, reflexive and symmetric; thus, we can omit those instances in the algorithm.
4.2 Optimizing trace storage
The main obstacle in monitoring hyperproperties is the potentially unbounded space consumption. Previously, RVHyper employed a trace analysis technique to detect redundant traces, with respect to a given HyperLTL formula, i.e., traces that can be safely discarded without losing any information and without losing the ability to return a counterexample.
Definition 4
[24] Given a HyperLTL formula \(\varphi \), a trace set T, and an arbitrary \(t \in \textit{TR}\), we say that t is \((T,\varphi )\)redundant if T is a model of \(\varphi \) if and only if \(T \cup \{{t}\}\) is a model of \(\varphi \) as well, formally
Definition 5
[24] Given \(t,t' \in \Sigma ^\omega \), we say t dominates \(t'\) with respect to \(\varphi \) (or simply t dominates \(t'\) if it is clear from the context) if \(t'\) is (\(\{t\},\varphi \))redundant.
Example 4
For observational determinism, a trace t is dominated by a trace \(t'\) if \({{t}} < {{t'}}\) and both traces agree on the input propositions.
This is efficiently implemented in \(\text {RVHyper}\) (cf. Algorithm 2) and is guaranteed to catch all redundant traces. In our experiments [23, 24], we made the observation that traces often share the same prefixes, leading to a lot of redundant monitor automaton instantiations, repetitive computations, and duplicated information when those traces get stored.
The trace analysis, as it is based on a language inclusion check of the entire traces, cannot handle partial redundancy, for example, in the case that traces have redundant prefix requirements. This leaves room for optimization, which we address by implementing a trie data structure for managing the storage of incoming traces.
Tries, also known as prefix trees, are a tree data structure, which can represent a set of words over an alphabet in a compact manner. The root of a trie is identified with the empty word \(\epsilon \); additionally, each node can have several child nodes, each of which corresponds to a unique letter getting appended to the representing word of the parent node. So the set of words of a trie is identified with the set of words the leaf nodes represent.
Definition 6
A trie is a four tuple \((\Sigma , \mathcal {T}, \longrightarrow , \tau _0)\) consisting of

A finite alphabet \(\Sigma \),

A nonempty set of states \(\mathcal {T}\),

A transition function \(\longrightarrow : \mathcal {T}\times \Sigma \rightarrow \mathcal {T}\),

And a designated initial state \(\tau _0 \in \mathcal {T}\) called the root.
Instead of \(((\tau ,a),\tau ') \in \longrightarrow \), we will write \(\tau \overset{a}{\longrightarrow } \tau '\) in the following. For a trie to be of valid form, we restrict \(\longrightarrow \) such that, \(\forall \tau ,\tau ' \in \mathcal {T}. \{\tau \overset{a}{\longrightarrow } \tau ' a \in \Sigma \} \le 1\).
In our case, the alphabet would be the set of propositions used in the specification, and the word built by the trie represents the traces. Instead of storing each trace individually, we store all of them in one trie structure, branching only in case of deviation. This means equal prefixes only have to be stored once. Besides the obvious benefits for memory, we also can make use of the maintained trie data structure to improve the runtime of our monitoring algorithms. As traces with same prefixes end up corresponding to the same path in the trie, we only have to instantiate the monitor automaton as much as the trie contains branches.
Example 5
Consider the following traces of length 6 over the alphabet \(2^{\{i,o\}}\):

\(t_1: \{\{{i}\},\{{i,o}\},\{{i}\},\{{i}\},\{{i}\},\{{i,o}\} \}\)

\(t_2: \{\{{i}\}, \{{i,o}\}, \{{i}\}, \{{i}\} , \{{i}\}, \{{i}\}\}\)

\(t_3: \{\{{i}\}, \{{i}\}, \{{i}\}, \{{i}\} , \{{i}\}, \{{i}\}\}\)

\(t_4: \{\{{i}\}, \{{i}\}, \{{}\}, \{{}\} , \{{}\}, \{{}\}\}\)
After processing the traces sequentially, the resulting trie looks as follows:
4.3 Triebased monitoring algorithm
We depict a triebased offline monitoring algorithm in Fig. 3. For the sake of readability, we assume that there are as many traces as universal quantifiers that we progress through all traces in parallel, and that all traces have the same length. This is merely a simplification in the presentation, and one can build the trie in a sequential fashion for online monitoring by a slight modification of the presented algorithm.
Without using tries, our monitoring algorithm was based on instantiating the deterministic monitor template \(\mathcal {M}_\varphi \) with tuples of traces. Now, we instantiate \(\mathcal {M}_\varphi \) with tuples of tries. Initially, we only have to create the single instance having the root of our trie.
The triebased algorithm has much in common with its previously discussed tracebased counterpart. Initially, we have to build the deterministic monitor automaton \(\mathcal {M}_\varphi = (\Sigma _{\mathcal {V}}, Q, q_0, \delta , F)\). We instantiate the monitor with a fresh trie root \(\tau _0\). A mapping from trie instantiations to a state in \(\mathcal {M}_\varphi \) \(S: \mathcal {T}^n \rightarrow Q\) stores the current state of every active branch of the trie, stored in the set I. For each of the incoming traces, we provide an entry in a tuple of tries \({\tau }\), and each entry gets initialized to \(\tau _0\). During the run of our algorithm, these entries are updated such that they always correspond to the word built by the traces up to this point. For as long as there are traces left, which have not yet ended, and we have not yet detected a violation, we will proceed updating the entries in \(\mathbf {i}\) as follows. Having entry \(\tau \) and the correspond trace sequence proceeds with a, if \(\exists \tau ' \in \mathcal {T}. \tau \overset{a}{\longrightarrow } \tau '\), we update the entry to \(\tau '\); otherwise, we create such a child node of \(\tau \) (add_child in line 8). Creating a new node in the trie always occurs when the prefix of the incoming trace starts to differ from already seen prefixes. After having moved one step in our traces sequences, we have to reflect this step in our trie structure, in order for the trieinstantiated automata to correctly monitor the new propositions. As a trie node can branch to multiple child nodes, each monitor instantiation is replaced by the set of instantiations, where all possible child combinations of the different assigned tries are existent (update of I in line 11). Afterward, we update S in the same way as in Algorithm 2; thus, we omit algorithmic details here. If a violation is detected here, that is, there is no transition in the monitor corresponding to \(\mathbf {i}\), we will return the corresponding counterexample as a tuple of traces, as those can get reconstructed by stepping upwards in the tries of \(\mathbf {i}\). If the traces end, we check if every open branch \(\mathbf {i} \in I\) is in an accepting state.
5 Evaluation
In the following, we evaluate the new version of \(\text {RVHyper}\), especially the novel trace storage optimization. We use several benchmarks: an encoder that guarantees a Hamming distance of 2, violations of noninterference on randomly generated traces, and a symmetry property on an implementation of the Bakery protocol. As an example how \(\text {RVHyper}\) can be used outside security runtime verification, we give a case study on detecting spurious dependencies in hardware designs.
5.1 Error correcting codes
We monitored whether an encoder preserves a Hamming distance of 2. We randomly built traces of length 50. In each position of the trace, the corresponding bit had a 1% chance to be flipped. The specification can be encoded as the following \(\text {HyperLTL}\) formula [26]:
The right plot of Fig. 2 shows the results of our experiments. We compared the naive monitoring approach to different combinations of \(\text {RVHyper}\)’s optimizations. The specification analysis returns in under one second with the result that the formula is symmetric and reflexive. Hence, as expected, this preprocessing step has a major impact on the running time of the monitoring process as more than half of the, in general necessary, monitor instantiations can be omitted. A combination of the specification and trace analysis performs nearly equally well as naively storing the traces in our trie data structure. Combining the trie data structure with the specification analysis performs best and results in a tremendous speedup compared to the naive approach.
5.2 Checking noninterference
Noninterference [33] is an important information flow policy demanding that an observer of a system cannot infer any high security input of a system by observing only low security input and output. Formally, we specify that all low security outputs \(\mathbf {o}^{\mathrm{low}}\) have to be equal on all system executions as long as the low security inputs \(\mathbf {i}^{\mathrm{low}}\) of those executions are the same: \(\forall \pi , \pi ' \mathpunct {.}({\mathbf {o}^{\mathrm{low}}_\pi } \leftrightarrow {\mathbf {o}^{\mathrm{low}}_{\pi '}}) {\mathcal {W}} ({\mathbf {i}^{\mathrm{low}}_\pi } \nleftrightarrow {\mathbf {i}^{\mathrm{low}}_{\pi '}}).\) This class of benchmarks has previously been used to evaluate RVHyper [23]. We repeated the experiments, to show that using the trie data structure is a valid optimization. The results are depicted in Table 1. We chose a trace length of 50 and monitored noninterference on 2000 randomly generated traces, where we distinguish between an input range of 8 to 64 bits. The results show that the trie optimization has an enormous impact compared to a naive approach that solely relies on the specification analysis. As expected, the difference in runtime is especially high on experiments where traces collapse heavily in the trie data structure, i.e., producing almost no instances that must be considered during the monitoring process.
5.3 Symmetry in mutual exclusion protocols
In this benchmark (introduced as a case study in [26]), we monitor whether a Verilog implementation of the Bakery protocol [31] from the VIS verification benchmark satisfies a symmetry property. Symmetry violations indicate that certain clients are privileged. The Bakery protocol is a classical protocol implementing mutual exclusion, working as follows: Every process that wishes to access a critical resource draws a ticket, which is consecutively numbered. The process with the smallest number may access the resource first. If two processes draw a ticket concurrently, i.e., obtaining the same number, the process with the smaller process ID may access the resource first. We monitored the following HyperLTL formula [26]:
where \(\text {select}\) indicates the process ID that runs in the next step and \(\text {pause}\) indicates whether the step is stuttering. Each process i has a program counter \(\text {pc}(i)\) and when process i is selected, \(\text {pc}(i)\) is executed. \(\text {sym}(\text {select}_\pi ,\text {select}_{\pi '})\) states that process 0 is selected on trace \(\pi \) and process 1 is selected on trace \(\pi '\). Unsurprisingly, the implementation violates the specification, as it is provably impossible to implement a mutual exclusion protocol that is entirely symmetric [32]. Figure 3 shows the results of our experiment. In this benchmark, we can observe that the language inclusion check, on which the trace optimization is based on, produces an overhead during the monitoring. Since the traces differ a lot, the trace analysis cannot prune enough traces to be valuable. As there are only a few instances (in this case 4), the trie optimization outperforms the previous version of \(\text {RVHyper}\) massively on such a low instance count. The specification analysis, however, is always a valuable optimization.
5.4 Case study: detecting spurious dependencies in hardware designs
While HyperLTL has been applied to a range of domains, including security and information flow properties, we focus in the following on a classical verification problem, the independence of signals in hardware designs. We demonstrate how \(\text {RVHyper}\) can automatically detect such dependencies from traces generated from hardware designs.
Input and output The input to \(\text {RVHyper}\) is a set of traces and a \(\text {HyperLTL}\) formula. For the following experiments, we generate a set of traces from the Verilog description of several example circuits by random simulation. If a set of traces violates the specification, \(\text {RVHyper}\) returns a counterexample.
Specification We consider the problem of detecting whether input signals influence output signals in hardware designs. We write \(\mathbf {i} \not \leadsto \mathbf {o}\) to denote that the inputs \(\mathbf {i}\) do not influence the outputs \(\mathbf {o}\). Formally, we specify this property as the following \(\text {HyperLTL}\) formula:
where \(\overline{\mathbf {i}}\) denotes all inputs except \(\mathbf {i}\). Intuitively, the formula asserts that for every two pairs of execution traces \((\pi _1,\pi _2)\), the value of \(\mathbf {o}\) has to be the same until there is a difference between \(\pi _1\) and \(\pi _2\) in the input vector \(\overline{\mathbf {i}}\), i.e., the inputs on which \(\mathbf {o}\) may depend.
Sample hardware designs We apply \(\text {RVHyper}\) to traces generated from the following hardware designs. Note that, since \(\text {RVHyper}\) observes traces and treats the system that generates the traces as a black box, the performance of \(\text {RVHyper}\) does not depend on the size of the circuit.
Example 6
(xor) As a first example, consider the xor function \(\mathbf {o} = \mathbf {i} \oplus \mathbf {i}'\). In the corresponding circuit, every jth output bit \(o_j\) is only influenced by the jth input bits \(i_j\) and \(i'_j\).
Example 7
(mux) This example circuit is depicted in Fig. 4. There is a black box combinatorial circuit, guarded by a multiplexer that selects between the two input vectors \(\mathbf {i}\) and \(\mathbf {i}'\) and an inverse multiplexer that forwards the output of the black box either toward \(\mathbf {o}\) or \(\mathbf {o}'\). Despite there being a syntactic dependency between \(\mathbf {o}\) and \(\mathbf {i}'\), there is no semantic dependency, i.e., the output \(\mathbf {o}\) does solely depend on \(\mathbf {i}\) and the selector signal.
When using the same example, but with a sequential circuit as black box, there may be information flow from the input vector \(\mathbf {i}'\) to the output vector \(\mathbf {o}\) because the state of the latches may depend on it. We construct such a circuit that leaks information about \(\mathbf {i}'\) via its internal state.
The left part of Fig. 2 shows the total runtime of \(\text {RVHyper}\) with the different optimizations and a combination thereof. As observed in our previous experiments, the specification analysis, if applicable as in this case, is a valuable optimization consistently reducing the runtime and does so also when combined with the trace analysis. As expected, the runtime is halved by exploiting symmetry and reflexivity in the formula. From the plot, we can also infer that the trace analysis is effective in a context with a majority of redundant traces. For such a highly redundant setup, the trace analysis reduces the overall runtime of the monitoring algorithm by several magnitudes. With a decrease in similarity and redundancy in the traces, the positive effect of the trace analysis steadily decreases up until the overhead of the trace analysis itself gets noticeable. The decrease in runtime for configurations without trace analysis, which comes with reduced traces similarity, is explained by the fact that the more the input of the monitored traces is different, the earlier trace tuples can get pruned as they satisfy the specification and thereby reduce the computational burden of the algorithm. This is also the reason why the configurations with trace analysis show decreasing runtime behavior again as soon as the aforementioned effects dominate the runtime characteristics of the monitoring approach. In contrast to that, the trie optimization provides a stable improvement on the running time.
Example 8
(counter) Our last example is a binary counter with two input control bits \(\text {incr}\) and \(\text {decr}\) that increments and decrements the counter. The corresponding Verilog design is shown in Fig. 5. The counter has a single output, namely a signal that is set to one when the counter value overflows. Both inputs influence the output, but timing of the overflow depends on the number of counter bits.
Results The results of multiple random simulations are given in Table 2. Even the previous version of \(\text {RVHyper}\) was able to scale up to thousands of input traces with millions of monitor instantiations. The novel implemented optimization of \(\text {RVHyper}\), i.e., storing the traces in a prefix tree data structure combined with our specification analysis, results in a remarkable speedup. Particularly interesting is the reduction in the number of instances in the counterexample. As there is only one input, the traces collapse in our trie data structure. For the two instances, where the property is satisfied (xor and mux), \(\text {RVHyper}\) has not found a violation for any of the runs. For instance, where the property is violated, \(\text {RVHyper}\) was able to find counterexamples.
6 Conclusion
\(\text {RVHyper}\) monitors a running system for violations of a HyperLTL specification. We have introduced a novel trace storage optimization, based on a prefix tree data structure, to existing optimizations implemented in \(\text {RVHyper}\).
We demonstrated the impact of the optimizations on \(\text {RVHyper}\)s performance on several benchmarks of runtime verification problems. By providing a use case on how \(\text {RVHyper}\) can be used to detect spurious dependencies in hardware design, we showed how \(\text {RVHyper}\) can be used outside of classical security monitoring problems. The functionality of \(\text {RVHyper}\) thus complements model checking tools for HyperLTL, like MCHyper [26], tools for satisfiability checking, like EAHyper [22], and tools for synthesis, like BoSyHyper [21].
\(\text {RVHyper}\) is in particular useful during the development of a \(\text {HyperLTL}\) specification, where it can be used to check the HyperLTL formula on sample traces without the need for a complete model. Based on the feedback of the tool, the user can refine the HyperLTL formula until it captures the intended policy.
In our current approach, the trace analysis and the trie representation are separate optimizations that cannot be applied at the same time. The integration of the two optimization is an interesting challenge for future work.
Notes
The implementation is available at https://react.unisaarland.de/tools/rvhyper/.
References
Agrawal, S., Bonakdarpour, B.: Runtime verification of ksafety hyperproperties in HyperLTL. In: Proceedings of CSF, pp. 239–252. IEEE Computer Society (2016). https://doi.org/10.1109/CSF.2016.24
Askarov, A., Sabelfeld, A.: Tight enforcement of informationrelease policies for dynamic languages. In: Proceedings of CSF, pp. 43–59. IEEE Computer Society (2009). https://doi.org/10.1109/CSF.2009.22
Austin, T.H., Flanagan, C.: Permissive dynamic information flow analysis. In: Proceedings of PLAS, p. 3. ACM (2010). https://doi.org/10.1145/1814217.1814220
Bichhawat, A., Rajani, V., Garg, D., Hammer, C.: Information flow control in WebKit’s JavaScript bytecode. In: Proceedings of POST. LNCS, vol. 8414, pp. 159–178. Springer (2014). https://doi.org/10.1007/9783642547928_9
Bonakdarpour, B., Finkbeiner, B.: The complexity of monitoring hyperproperties. In: Proceedings of CSF, pp. 162–174. IEEE Computer Society (2018). https://doi.org/10.1109/CSF.2018.00019
Bonakdarpour, B., Sánchez, C., Schneider, G.: Monitoring hyperproperties by combining static analysis and runtime verification. In: Proceedings of ISoLA. LNCS, vol. 11245, pp. 8–27. Springer (2018). https://doi.org/10.1007/9783030034214_2
Brett, N., Siddique, U., Bonakdarpour, B.: Rewritingbased runtime verification for alternationfree HyperLTL. In: Proceedings of TACAS. LNCS, vol. 10206, pp. 77–93 (2017). https://doi.org/10.1007/9783662545805_5
Chudnov, A., Kuan, G., Naumann, D.A.: Information flow monitoring as abstract interpretation for relational logic. In: Proceedings of CSF, pp. 48–62. IEEE Computer Society (2014). https://doi.org/10.1109/CSF.2014.12
Clarkson, M.R., Finkbeiner, B., Koleini, M., Micinski, K.K., Rabe, M.N., Sánchez, C.: Temporal logics for hyperproperties. In: Proceedings of POST. LNCS, vol. 8414, pp. 265–284. Springer (2014). https://doi.org/10.1007/9783642547928_15
Clarkson, M.R., Schneider, F.B.: Hyperproperties. J. Comput. Secur. 18(6), 1157–1210 (2010). https://doi.org/10.3233/JCS20090393
Coenen, N., Finkbeiner, B., Hahn, C., Hofmann, J.: The hierarchy of hyperlogics. In: Proceedings of LICS, pp. 1–13. IEEE (2019). https://doi.org/10.1109/LICS.2019.8785713
Coenen, N., Finkbeiner, B., Sánchez, C., Tentrup, L.: Verifying hyperliveness. In: Proceedings of CAV. LNCS, vol. 11561, pp. 121–139. Springer (2019). https://doi.org/10.1007/9783030255404_7
d’Amorim, M., Rosu, G.: Efficient monitoring of omegalanguages. In: Proceedings of CAV. LNCS, vol. 3576, pp. 364–378. Springer (2005). https://doi.org/10.1007/11513988_36
D’Argenio, P.R., Barthe, G., Biewer, S., Finkbeiner, B., Hermanns, H.: Is your software on dope? Formal analysis of surreptitiously “enhanced” programs. In: Proceedings of ESOP. LNCS, vol. 10201, pp. 83–110. Springer (2017). https://doi.org/10.1007/9783662544341_4
Devriese, D., Piessens, F.: Noninterference through secure multiexecution. In: Proceedings of SP, pp. 109–124. IEEE Computer Society (2010). https://doi.org/10.1109/SP.2010.15
Dimitrova, R., Finkbeiner, B., Kovács, M., Rabe, M.N., Seidl, H.: Model checking information flow in reactive systems. In: Proceedings of VMCAI. LNCS, vol. 7148, pp. 169–185. Springer (2012). https://doi.org/10.1007/9783642279409_12
Dimitrova, R., Finkbeiner, B., Rabe, M.N.: Monitoring temporal information flow. In: Proceedings of ISoLA. LNCS, vol. 7609, pp. 342–357. Springer (2012). https://doi.org/10.1007/9783642340260_26
DuretLutz, A., Lewkowicz, A., Fauchille, A., Michaud, T., Renault, E., Xu, L.: Spot 2.0—a framework for LTL and \(\omega \)automata manipulation. In: Proceedings of ATVA. LNCS, vol. 9938, pp. 122–129 (2016). https://doi.org/10.1007/9783319465203_8
Finkbeiner, B., Hahn, C.: Deciding hyperproperties. In: Proceedings of CONCUR. LIPIcs, vol. 59, pp. 13:1–13:14. Schloss Dagstuhl—LeibnizZentrum fuer Informatik (2016). https://doi.org/10.4230/LIPIcs.CONCUR.2016.13
Finkbeiner, B., Hahn, C., Hans, T.: MGHyper: Checking satisfiability of HyperLTL formulas beyond the \(\exists ^* \forall ^*\) fragment. In: Proceedings of ATVA. LNCS, vol. 11138, pp. 521–527. Springer (2018). https://doi.org/10.1007/9783030010904_31
Finkbeiner, B., Hahn, C., Lukert, P., Stenger, M., Tentrup, L.: Synthesizing reactive systems from hyperproperties. In: Proceedings of CAV. LNCS, vol. 10981, pp. 289–306. Springer (2018). https://doi.org/10.1007/9783319961453_16
Finkbeiner, B., Hahn, C., Stenger, M.: EAHyper: satisfiability, implication, and equivalence checking of hyperproperties. In: Proceedings of CAV. LNCS, vol. 10427, pp. 564–570. Springer (2017). https://doi.org/10.1007/9783319633909_29
Finkbeiner, B., Hahn, C., Stenger, M., Tentrup, L.: RVHyper: A runtime verification tool for temporal hyperproperties. In: Proceedings of TACAS. LNCS, vol. 10806, pp. 194–200. Springer (2018). https://doi.org/10.1007/9783319899633_11
Finkbeiner, B., Hahn, C., Stenger, M., Tentrup, L.: Monitoring hyperproperties. Form. Methods Syst. Des. (2019). https://doi.org/10.1007/s1070301900334z
Finkbeiner, B., Hahn, C., Torfah, H.: Model checking quantitative hyperproperties. In: Proceedings of CAV. LNCS, vol. 10981, pp. 144–163. Springer (2018). https://doi.org/10.1007/9783319961453_8
Finkbeiner, B., Rabe, M.N., Sánchez, C.: Algorithms for model checking HyperLTL and HyperCTL*. In: Proceedings of CAV. LNCS, vol. 9206, pp. 30–48. Springer (2015). https://doi.org/10.1007/9783319216904_3
Guernic, G.L., Banerjee, A., Jensen, T.P., Schmidt, D.A.: Automatabased confidentiality monitoring. In: Proceedings of ASIAN. LNCS, vol. 4435, pp. 75–89. Springer (2006). https://doi.org/10.1007/9783540775058_7
Hahn, C.: Algorithms for monitoring hyperproperties. In: Proceedings of Runtime Verification—19th International Conference, pp. 70–90. RV 2019, Porto, 8–11 Oct (2019). https://doi.org/10.1007/9783030320799_5
Hahn, C., Stenger, M., Tentrup, L.: Constraintbased monitoring of hyperproperties. In: Proceedings of TACAS. LNCS, vol. 11428, pp. 115–131. Springer (2019). https://doi.org/10.1007/9783030174651_7
Kovács, M., Seidl, H.: Runtime enforcement of information flow security in tree manipulating processes. In: Proceedings of ESSoS. LNCS, vol. 7159, pp. 46–59. Springer (2012). https://doi.org/10.1007/9783642281662_6
Lamport, L.: A new solution of Dijkstra’s concurrent programming problem. Commun. ACM 17(8), 453–455 (1974). https://doi.org/10.1145/361082.361093
Manna, Z., Pnueli, A.: Temporal Verification of Reactive Systems: Safety. Springer, New York (1995)
McLean, J.: Proving noninterference and functional correctness using traces. J. Comput. Secur. 1(1), 37–58 (1992). https://doi.org/10.3233/JCS19921103
Roscoe, A.W.: CSP and determinism in security modelling. In: Proceedings of SP, pp. 114–127. IEEE Computer Society (1995). https://doi.org/10.1109/SECPRI.1995.398927
Sabelfeld, A., Myers, A.C.: Languagebased informationflow security. IEEE J. Sel. Areas Commun. 21(1), 5–19 (2003). https://doi.org/10.1109/JSAC.2002.806121
Smith, G.: On the foundations of quantitative information flow. In: Proceedings of FOSSACS. LNCS, vol. 5504, pp. 288–302. Springer (2009). https://doi.org/10.1007/9783642005961_21
Stucki, S., Sánchez, C., Schneider, G., Bonakdarpour, B.: Graybox monitoring of hyperproperties. In: Proceedings of Formal Methods—the Next 30 Years—Third World Congress, pp. 406–424. FM 2019, Porto, 7–11 Oct (2019). https://doi.org/10.1007/9783030309428_25
Suh, G.E., Lee, J.W., Zhang, D., Devadas, S.: Secure program execution via dynamic information flow tracking. In: Proceedings of ASPLOS, pp. 85–96. ACM (2004). https://doi.org/10.1145/1024393.1024404
Tabakov, D., Rozier, K.Y., Vardi, M.Y.: Optimized temporal monitors for systemC. Form. Methods Syst. Des. 41(3), 236–268 (2012). https://doi.org/10.1007/s1070301101398
Vanhoef, M., Groef, W.D., Devriese, D., Piessens, F., Rezk, T.: Stateful declassification policies for eventdriven programs. In: Proceedings of CSF, pp. 293–307. IEEE Computer Society (2014). https://doi.org/10.1109/CSF.2014.28
Yasuoka, H., Terauchi, T.: On bounding problems of quantitative information flow. In: Proceedings of ESORICS. LNCS, vol. 6345, pp. 357–372. Springer (2010). https://doi.org/10.1007/9783642154973_22
Zdancewic, S., Myers, A.C.: Observational determinism for concurrent program security. In: Proceedings of CSF, p. 29. IEEE Computer Society (2003). https://doi.org/10.1109/CSFW.2003.1212703
Acknowledgements
Open Access funding provided by Projekt DEAL.
Author information
Authors and Affiliations
Corresponding author
Additional information
Publisher's Note
Springer Nature remains neutral with regard to jurisdictional claims in published maps and institutional affiliations.
This work was partially supported by the German Research Foundation (DFG) as part of the Collaborative Research Center “Methods and Tools for Understanding and Controlling Privacy” (CRC 1223) and the Collaborative Research Center “Foundations of Perspicuous Software Systems” (TRR 248, 389792660), and by the European Research Council (ERC) Grant OSARES (No. 683300).
Rights and permissions
Open Access This article is licensed under a Creative Commons Attribution 4.0 International License, which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons licence, and indicate if changes were made. The images or other third party material in this article are included in the article’s Creative Commons licence, unless indicated otherwise in a credit line to the material. If material is not included in the article’s Creative Commons licence and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder. To view a copy of this licence, visit http://creativecommons.org/licenses/by/4.0/.
About this article
Cite this article
Finkbeiner, B., Hahn, C., Stenger, M. et al. Efficient monitoring of hyperproperties using prefix trees. Int J Softw Tools Technol Transfer 22, 729–740 (2020). https://doi.org/10.1007/s10009020005525
Published:
Issue Date:
DOI: https://doi.org/10.1007/s10009020005525