
\chapter{Manipulating Function Calls}\label{ch:manipulating-function-calls}

This chapter discusses how to manipulate function calls and how this may be used to test programs.
How function calls may be intercepted at all has been discussed in Chapter~\ref{ch:intercepting-function-calls}.
This chapter builds on the basis of the previous one and expands its functions.
In this context, ``manipulation'' means changing the arguments of a function before calling it with the modified arguments, or skipping the execution of the real function completely and simply returning a given value (``mocking'').
These techniques allow in-depth testing of programs.

In contrast to simply recording and logging function calls, which may be controlled via environment variables, manipulation of such function calls requires some other process to indicate how to handle each call.
This work uses simple Unix domain sockets to communicate between the process of the program to be tested, and a ``server'', which decides what action to perform for each function call.
Currently, only communication over Unix domain sockets is implemented, but communication over TCP sockets is also easily possible.
This approach is similar to the one used in \cite{ostia} to communicate with the \textit{agent}.

Figure~\ref{fig:control-flow} illustrates the control flow for manipulating function calls.

\begin{figure}
  \begin{sequencediagram}
    \newthread{p}{:Program}
    \newinst{l}{:\texttt{\textit{lib}.so}}
    \newinst{i}{:\texttt{intercept.so}}
    \newthreadShift[gray]{s}{:Server}{2cm}

    %\begin{sdblock}{Normal Call}{}
    %  \begin{call}{p}{read()}{l}{return a}
    %  \end{call}
    %\end{sdblock}

    \begin{sdblock}{Intercepted Call}{}
      \begin{call}{p}{malloc(x)}{i}{return a}
        \mess{i}{{``malloc(x)''}}{s}
        \mess{s}{``ok''}{i}
        \begin{call}{i}{malloc(x)}{l}{return a}
        \end{call}
        \mess{i}{``return a''}{s}
      \end{call}
    \end{sdblock}

    \begin{sdblock}{Modified Call}{}
      \begin{call}{p}{malloc(x)}{i}{return b}
        \mess{i}{{``malloc(x)''}}{s}
        \mess{s}{``modify y''}{i}
        \begin{call}{i}{malloc(y)}{l}{return b}
        \end{call}
        \mess{i}{``return b''}{s}
      \end{call}
    \end{sdblock}

    \begin{sdblock}{Mocked Call}{}
      \begin{call}{p}{malloc(x)}{i}{return c}
        \mess{i}{{``malloc(x)''}}{s}
        \mess{s}{``fail'' / ``return c''}{i}
        \mess{i}{``return c''}{s}
      \end{call}
    \end{sdblock}
  \end{sequencediagram}
  \centering
  \caption{Simplified Control Flow for Function Call Manipulation.}
  \label{fig:control-flow}
\end{figure}


\section{Defining a Protocol}\label{sec:defining-a-protocol}

When using a socket to communicate with another process, a protocol definition is needed.
This work defines a text-based protocol in which line breaks denote the end of a message.
The following subsections describe the defined message types.

\subsection{\textit{Init} Message (Client \textrightarrow{} Server)}\label{subsec:init-message}

This message is the first message sent in a newly established connection.
The client (\texttt{intercept.so}) uses it to identify the running program to the server (PID, path, \dots).

\subsection{\textit{Call} Message (Client \textrightarrow{} Server)}\label{subsec:call-message}

For each function call, the client sends this message to the server and waits for a reply (\textit{Action} message).
The contents of this message type correspond to the first line of an intercepted function call (see Section~\ref{sec:automated-testing-on-intercepted-function-calls}).

\subsection{\textit{Action} Message (Server \textrightarrow{} Client)}\label{subsec:action-message}

After receiving a \textit{Call} message from the client, the server decides what the client should do with this call.
The server responds in one of four possible ways:

\begin{description}
  \item[\texttt{"ok"}] indicates that the function should be called normally.
  \item[\texttt{"modify \textit{ARG...}"}] indicates that the arguments of the function should be changed according to the message before the call to the function.
  \item[\texttt{"fail \textit{ERROR}"}] indicates that the function should not be called and instead should fail with the given error code.
  \item[\texttt{"return \textit{VALUE}"}] indicates that the function should simply return the provided value without calling the real function.
\end{description}

\subsection{\textit{Return} Message (Client \textrightarrow{} Server)}\label{subsec:return-message}

This message informs the server about the resulting return value.
The server does not acknowledge this message.
The contents of this message type correspond to the second line of an intercepted function call (see Section~\ref{sec:automated-testing-on-intercepted-function-calls}).


\section{Automated Testing using Function Call Manipulation}\label{sec:automated-testing-using-function-call-manipulation}

As seen in Figure~\ref{fig:control-flow} function call manipulation allows for mocking individual calls.
Mocking may be used to see how the program behaves when individual calls to a function fail, or return an unusual, but valid, value.
The simplest way to automatically test programs is to run them multiple times, allowing a single function call to fail in each run.
The resulting sequence of function calls now may be put together to a call sequence graph (or tree).
By analyzing this call graph, it is possible to decide if a program correctly terminated, when faced with a failed function call.
This may be the case when the following function calls differ from those which were recorded on a default run (without any mocked function calls).


\subsection{Testing Return Value Checks}\label{subsec:testing-return-value-checks}

Figure~\ref{fig:call-sequence} shows the simplified and collapsed call sequence graph of the prior example in Section~\ref{sec:intercepting-example}.
Each edge between two nodes without any label indicates the next function call on a normal run of the program.
Edges labeled with ``fail'' indicate the next function call after a mocked failed call.
In reality, there are multiple failing paths, one for each possible error return value.
However, in this example they all yield the same resulting path, and have therefore been collapsed.

To test if a programmer always checked the return value of a function and acted accordingly, this resulting call sequence graph now may be analyzed.
At first glance, this test appears trivial.
The simplest approach is to verify that after a failing function call only ``cleanup'' function calls (\texttt{free}, \texttt{close}, \texttt{exit}, \dots) follow.
For simple programs, this assumption may hold, but there are many exceptions.
For example, what if the program recognizes the failed call correctly as failed but recovers and continues to operate normally?
Or what if the ``cleanup'' path is very complex and includes function calls not priorly marked as valid cleanup functions?
However, for simple programs (like those mentioned in Section~\ref{sec:motivation-and-goal}), the simplest approach from above suffices.

\begin{figure}
  \begin{tikzpicture}[node distance=15mm, thick, main/.style = {draw, circle}, text centered]
    \newcommand{\fncall}[2]{\tiny{\begin{tabular}{c}\normalsize{\texttt{#1}}\\\texttt{#2}\end{tabular}}}
    \node[main] (1)[elips] {\fncall{getopt}{client+0x1ac5, client.c:186}};
    \node[main] (2)[elips] [below of=1] {\fncall{getaddrinfo}{client+0x147b, client.c:74}};
    \node[main] (3)[elips] [below of=2] {\fncall{socket}{client+0x14f2, client.c:81}};
    \node[main] (4)[elips] [below of=3] {\fncall{connect}{client+0x15f3, client.c:104}};
    \node[main] (5)[elips] [below of=4] {\fncall{freeaddrinfo}{client+0x1638, client.c:114}};
    \node[main] (6)[elips] [below of=5] {\fncall{send}{client+0x1f5c, client.c:277}};
    \node[main] (7)[elips] [below of=6] {\fncall{recv}{client+0x1fa1, client.c:284}};
    \node[main] (8)[elips] [below of=7] {\fncall{recv}{client+0x2062, client.c:300}};
    \node[main] (9)[elips] [below of=8] {\fncall{recv}{client+0x2442, client.c:360}};
    \node[main] (10)[elips] [below of=9] {\fncall{recv}{client+0x2442, client.c:360}};
    \node[main] (11)[elips] [below of=10] {\fncall{close}{client+0x2489, client.c:375}};
    \node[main] (12)[elips] [below of=11] {\fncall{exit}{sys+0x0}};

    \node[main] (2f1)[elips] [right=10mm of 2] {\fncall{exit}{sys+0x0}};
    \node[main] (3f1)[elips] [right=10mm of 3] {\fncall{freeaddrinfo}{client+0x1638, client.c:114}};
    \node[main] (4f1)[elips] [right=10mm of 4] {\fncall{close}{client+0x1611, client.c:106}};

    \draw[->] (1) -- (2);
    \draw[->] (2) -- (3);
    \draw[->] (2) -- node[midway, above, sloped, pos=0.5] {fail} (2f1);
    \draw[->] (3) -- (4);
    \draw[->] (3) -- node[midway, above, sloped, pos=0.5] {fail} (3f1);
    \draw[->] (3f1) -- (2f1);
    \draw[->] (4) -- (5);
    \draw[->] (4) -- node[midway, above, sloped, pos=0.5] {fail} (4f1);
    \draw[->] (4f1) -- (3f1);
    \draw[->] (5) -- (6);
    \draw[->] (6) -- (7);
    \draw[->] (7) -- (8);
    \draw[->] (8) -- (9);
    \draw[->] (9) -- (10);
    \draw[->] (10) -- (11);
    \draw[->] (11) -- (12);
    \draw[->] (6) to [out=0,in=-4,looseness=2] node[midway, above, pos=0.05] {fail} (11);
    \draw[->] (7) to [out=0,in=-2,looseness=1.75] node[midway, above, pos=0.075] {fail} (11);
    \draw[->] (8) to [out=0,in=0,looseness=1.5] node[midway, above, pos=0.1] {fail} (11);
    \draw[->] (9) to [out=0,in=2,looseness=1.25] node[midway, above, pos=0.1] {fail} (11);
    \draw[->] (10) to [out=0,in=3,looseness=1] node[midway, above, pos=0.1] {fail} (11);
  \end{tikzpicture}
  \centering
  \caption{Simplified Call Sequence Graph of \texttt{./client}.}
  \label{fig:call-sequence}
\end{figure}


\subsection{Testing Correct Handling of Interrupts}\label{subsec:testing-interrupts}

Many functions (like \texttt{read}, \texttt{write}, or \texttt{sem\_wait}) are interruptable by signals.
When this happens, they return a value indicating an error and set \texttt{errno} to \texttt{EINTR}.
Usually, the program is expected to repeat the call until it gets a real return value or error other than \texttt{EINTR}.
Therefore, testing correct handling of interrupts is a different type of test in contrast to general tests on return value checks as seen in Subsection~\ref{subsec:testing-return-value-checks}.

It is relatively simple to test if a program correctly handles interrupts.
On any function call that may yield \texttt{EINTR} mock the call and return exactly that error.
Afterward, check if the same function is called again.
To increase confidence in the result, one may repeat this process multiple times.
As in the test in Subsection~\ref{subsec:testing-return-value-checks}, the handling of the interrupt may involve calls to other functions, so this method is not always the right choice.
But for simple programs, it totally suffices.
