This commit is contained in:
Carlos Galindo 2019-12-05 09:04:15 +00:00
parent 19c27d6b88
commit f51bc215ea
2 changed files with 26 additions and 24 deletions

View file

@ -30,7 +30,7 @@ proposed \cite{Sil12}:
statically or dynamically.
\textsl{Static slicing} \cite{Wei81} produces slices which\josep{that} consider all
possible executions of the program: the slice will be correct regardless of the input supplied.
In contrast, \textsl{dynamic slicing} \cite{KorL88,} considers a single execution of the program, thus, limiting the slice to
In contrast, \textsl{dynamic slicing} \cite{KorL88,AgrH90b} considers a single execution of the program, thus, limiting the slice to
the statements present in an execution log. The slicing criterion is
expanded to include a position in the log\josep{execution history} that corresponds to one
instance of the selected statement, making it much more specific. It may

View file

@ -173,7 +173,9 @@ The most popular approach was proposed by Ball and Horwitz~\cite{BalH93}, classi
\item[Statement.] Any instruction that is not a conditional or unconditional jump. It has one outgoing edge in the CFG, to the next instruction that follows it in the program.
\item[Predicate.] Any conditional jump instruction, such as \texttt{while}, \texttt{until}, \texttt{do-while}, \texttt{if}, etc. It has two outgoing edges, labeled \textit{true} and \textit{false}; leading to the corresponding instructions.
\item[Pseudo--predicates.] Unconditional jumps (e.g. \texttt{break}, \texttt{goto}, \texttt{continue}, \texttt{return}); are like predicates, with the difference that the outgoing edge labeled \textit{false} is marked as non--executable, and there is no possible execution where such edge would be possible, according to the definition of the CFG (as seen in \sergio{definition o Definition?}definition~\ref{def:cfg}). Originally the edges had a specific reasoning backing them up: the \textit{true} edge leads to the jump's destination and the \textit{false} one, to the instruction that would be executed if the unconditional jump was removed, or converted into a \texttt{no op}\sergio{no op o no-op?} (a blank operation that performs no change to the program's state). \sergio{\{}This specific behavior is used with unconditional jumps, but no longer applies to pseudo--predicates, as more instructions have used this category as means of ``artificially'' \carlos{bad word choice} generating control dependencies.\sergio{\}No entrar en este jardin, cuando se definio esto no se contemplaba la creacion de nodos artificiales. -Quita el originally, ahora es originally.}
\end{description}
\end{description}
\carlos{Pseudo--statements now have been introduced and are used to generate all control edges (for now just the Start method to the End).}
As a consequence of this classification, every instruction after an unconditional jump $j$ is control--dependent (either directly or indirectly) on $j$ and the structure containing it (a conditional statement or a loop), as can be seen in the following example.
@ -255,14 +257,14 @@ The \texttt{try-catch} statement can be compared to a \texttt{switch} which comp
\subsection{\texttt{throw} statement}
The \texttt{throw} statement compounds two elements in one instruction: an
unconditional jump with a value attached and a switch to an ``exception mode'', in which the statement's execution order is disregarded. The first one has been extensively covered and solved; as it is equivalent to the \texttt{return} instruction, but the second one requires a small addition to the CFG: there must be an alternative control flow, where the path of the exception is shown. For now, without including \texttt{try-catch} structures, any exception thrown will exit its method with an error; so a new ``Error end'' node is needed. The preexisting ``End'' node is renamed ``Normal end'', but now the CFG has two distinct sink nodes; which is forbidden in most slicing algorithms. To solve that problem, a general ``End'' node is created, with both normal and exit ends connected to it; making it the only sink in the graph.
unconditional jump with a value attached and a switch to an ``exception mode'', in which the statement's execution order is disregarded. The first one has been extensively covered and solved; as it is equivalent to the \texttt{return} instruction, but the second one requires a small addition to the CFG: there must be an alternative control flow, where the path of the exception is shown. For now, without including \texttt{try-catch} structures, any exception thrown will exit its method with an error; so a new ``Error end'' node is needed. The pre-existing ``End'' node is renamed ``Normal end'', but now the CFG has two distinct sink nodes; which is forbidden in most slicing algorithms. To solve that problem, a general ``End'' node is created, with both normal and exit ends connected to it; making it the only sink in the graph.
In order to properly accomodate a method's output variables (global variables or parameters passed by reference that have been modified), variable unpacking is
In order to properly accommodate a method's output variables (global variables or parameters passed by reference that have been modified), variable unpacking is added to the ``Error exit'' node; same as the ``Exit'' node in previous examples. This change constitutes an increase in precision, as now the outputted variables are differentiated; for example a slice which only requires the error exit may include less variable modifications than one which includes both.
This treatment of \texttt{throw} statements only modifies the structure of the CFG, without altering the other graphs, the traversal algorithm, or the basic definitions for control and data dependencies. That fact makes it easy to incorporate to any existing program slicer that follows the general model described. Example~\ref{exa:throw} showcases the new exit nodes and the treatment of the \texttt{throw} as if it were an unconditional jump whose destination is the ``Error exit''.
\begin{example}[CFG of an uncaught \texttt{throw} statement]
Consider the simple Java method on the right of figure~\ref{fig:throw}; which performs a square root if the number is positive, throwing otherwise a \texttt{RuntimeError}. The CFG in the centre illustrates the treatment of \texttt{throw}, ``normal exit'' and ``error exit'' as pseudo--statements, and the PDG on the right describes the
Consider the simple Java method on the right of figure~\ref{fig:throw}; which performs a square root if the number is positive, throwing otherwise a \texttt{RuntimeError}. The CFG in the centre illustrates the treatment of \texttt{throw}, ``normal exit'' and ``error exit'' as pseudo--statements, and the PDG on the right describes the control dependencies generated from the \texttt{throw} statement to the following instructions and exit nodes.
\label{exa:throw}
\begin{figure}[h]
\begin{minipage}{0.3\linewidth}
@ -282,31 +284,31 @@ double f(int x) {
\end{figure}
\end{example}
\subsection{\texttt{try-catch} statement}
\subsection{\texttt{try-catch-finally} statement}
The \texttt{try-catch-finally} statement is the only way to stop an exception once \added{it is}\deleted{it's} thrown,
filtering by type, or otherwise letting it propagate further up the call stack. On top of that,
\texttt{finally} helps guarantee consistency, executing in any case (even when an exception is
left uncaught, the program returns or an exception occurs in a \texttt{catch} block). The main
problem with this construct is that \texttt{catch} blocks are not always necessary, but their
absence may make the compilation fail ---because a \texttt{try} block has no \texttt{catch} or
\texttt{finally} block---, or modify the execution in unexpected ways that are not always accounted
for in slicing software.
The \texttt{try-catch} statement is the only way to stop an exception once it is thrown.
It filters exception by its type; letting those which do not match any of the catch blocks propagate to another \texttt{try-catch} surrounding it or outside the method, to the previous one in the call stack.
On top of that, the \texttt{finally} block helps programmers guarantee code execution. It can be used replacing or in conjunction with \texttt{catch} blocks.
The code placed inside a \texttt{finally} block is guaranteed to run if the \texttt{try} block has been entered.
This holds true whether the \texttt{try} block exits correctly, an exception is caught, an exception is left uncaught or an exception is caught and another one is thrown while handling it (within its \texttt{catch} block).
For the \texttt{try} block, it is normally represented as a pseudo--predicate, connected to the
first statement inside it and to the end of the first instruction after the whole \texttt{try-catch-finally}
construct. Inside the \texttt{try} there can be four distinct sources of exceptions:
\carlos{This would be useful to explain that the new dependencies introduced by the non-executable edges are not ``normal'' control dependencies, but ``presence'' dependencies. Opposite to traditional control dependence, where $a \ctrldep b$ if and only if the number of times $b$ is executed is dependent on the \textit{execution} of $a$ (e.g. conditional blocks and loops); this new control dependencies exist if and only if the number of times $b$ is executed is dependent on the \textit{presence} or \textit{absence} of $a$; which introduces a meta-problem. In the case of exceptions, it is easy to grasp that the absence of a catch block alters the results of an execution. Same with unconditional jumps, the absence of breaks modifies the flow of the program, but its execution does not control anything. A differentiation seems appropriate, even if only as subcategories of control dependence: execution control dependence and presence control dependence.}
The main problem when including \texttt{try-catch} blocks in program slicing is that \texttt{catch} blocks are not always strictly necessary for the slice (less so for weak slices), but introduce new styles of control dependence; which must be properly mapped to the SDG. The absence of \texttt{catch} blocks may also be a problem for compilation, as Java requires at least one \texttt{catch} or \texttt{finally} block to accompany each \texttt{try} block; though that could be fixed after generating the slice, if it is required that the slice be executable.
A typical representation of the \texttt{try} block is as a pseudo-predicate, connected to the first statement inside it and to the instruction that follows the \texttt{try} block.
This generates control dependencies from the \texttt{try} node to each of the instructions it contains.
\carlos{This is not really a ``control'' dependency, could be replaced by the definition of structural dependence.}
Inside the \texttt{try} there can be four distinct sources of exceptions:
\begin{description}
\item[Method calls.] If an exception is thrown inside a method and it is not caught, it will
surface inside the \texttt{try} block. As \textit{checked} exceptions must be declared
explicitly, method declarations may be consulted to see if a method call may or may not
throw any exceptions. On this front, polymorphism and inheritance present no problem, as
inherited methods may not modify the signature ---which includes the exceptions that may
be thrown. If \textit{unchecked} exceptions are also considered, all method calls shall
be included, as any can trigger at the very least a \texttt{StackOverflowException}.
surface inside the \texttt{try} block.
As \textit{checked} exceptions must be declared explicitly, method declarations may be consulted to see if a method call may or may not throw any exceptions.
On this front, polymorphism and inheritance present no problem, as inherited methods must match the signature of the parent method ---including exceptions that may be thrown.
If \textit{unchecked} exceptions are also considered, method calls could be analysed to know which exceptions may be thrown, or the documentation be checked automatically for the comment annotation \texttt{@throws} to know which ones are thrown.
\item[\texttt{throw} statements.] The least common, but most simple, as it is treated as a
\texttt{throw} inside a method.
\texttt{throw} inside a method. The type of the exception may be obvious, as most \carlos{this is a weird claim to make without backup} exceptions are built and thrown in the same instruction; but it also may be hidden: e.g., \texttt{throw (Exception) o} where \texttt{o} is a variable of type Object.
\item[Implicit unchecked exceptions.] If \textit{unchecked} exceptions are considered, many
common expressions may throw an exception, with the most common ones being trying to call
a method or accessing a field of a \texttt{null} object (\texttt{NullPointerException}),