1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "gate/functions.h"
#include "gate/results.h"
#include "gate/console.h"
#include "gate/debugging.h"

static gate_result_t GATE_CALL no_fault_entry(void* arg)
{
    GATE_UNUSED_ARG(arg);
    return GATE_RESULT_OK;
}

static gate_result_t GATE_CALL seg_fault_entry(void* arg)
{
    int volatile* volatile ptr = (int volatile*)arg;
    volatile int n = *ptr;
    *ptr = n;
    return GATE_RESULT_OK;
}
static volatile int zero = 0;
static gate_result_t GATE_CALL div_fault_entry(void* arg)
{
    int volatile value = 42;
    int volatile result;

    (void)arg;
    result = value / zero; // cppcheck-suppress zerodiv<--- Division by zero
    value = result * zero; // cppcheck-suppress unreadVariable<--- Variable 'value' is assigned a value that is never used.<--- Unmatched suppression: zerodiv
    return GATE_RESULT_OK;<--- Unmatched suppression: unreadVariable
}
static volatile float zerof = 0.0f;
static gate_result_t GATE_CALL float_fault_entry(void* arg)
{
    float value = 42.0f;
    float result;

    (void)arg;
    result = value / zerof;
    value = result * zerof; // cppcheck-suppress unreadVariable<--- Variable 'value' is assigned a value that is never used.
    return GATE_RESULT_OK;<--- Unmatched suppression: unreadVariable
}

static gate_result_t GATE_CALL fault_handler(unsigned fault_code, void* fault_arg)
{
    if (fault_arg)
    {
        unsigned* volatile ptr = (unsigned* volatile)fault_arg; // cppcheck-suppress unreadVariable<--- Variable 'ptr' is not assigned a value.<--- Uninitialized variable: ptr
        *ptr = fault_code; // cppcheck-suppress uninitvar<--- Uninitialized variable: ptr<--- Unmatched suppression: unreadVariable
    }<--- Unmatched suppression: uninitvar
    else
    {
        GATE_DEBUG_TRACE("Missing fault_arg");
    }
    return GATE_RESULT_OK;
}

static gate_bool_t test_function_fault_succeed(gate_entrypoint_t entry, void* arg)
{
    gate_result_t ret = true;
    gate_result_t result;
    unsigned fault_code = 0;

    result = gate_function_invoke_guarded(entry, arg, &fault_handler, &fault_code);
    if (GATE_FAILED(result))
    {
        GATE_DEBUG_TRACE("correct function failed to executed with fault guard");
        ret = false;
    }
    if (fault_code != 0)
    {
        GATE_DEBUG_TRACE_MSG_VALUE("unexpected fault code", fault_code);
        ret = false;
    }
    return ret;
}

static gate_bool_t test_function_fault_fail(gate_entrypoint_t entry, void* arg, unsigned expected_fault_code)
{
    gate_bool_t ret = true;
    gate_result_t result;
    unsigned fault_code = 0;

    result = gate_function_invoke_guarded(entry, arg, &fault_handler, &fault_code);
    if (result != GATE_RESULT_BADINSTRUCTION)
    {
        GATE_DEBUG_TRACE_MSG_VALUE("unexpected result of bad-instruction function", result);
        ret = false;
    }

    if (fault_code != expected_fault_code)
    {
        GATE_DEBUG_TRACE_MSG_VALUE("unexpected result of bad-instruction function", fault_code);
        ret = false;
    }

    return ret;
}


gate_bool_t test_fault_guard()
{
    gate_bool_t succeeded = true;
#if !defined(GATE_SYS_BSD)
    GATE_DEBUG_TRACE("Test correct function with fault guard");
    succeeded &= test_function_fault_succeed(&no_fault_entry, NULL);
#if !defined(GATE_SYS_DOS)
    GATE_DEBUG_TRACE("Test bad segfault function with fault guard");
    succeeded &= test_function_fault_fail(&seg_fault_entry, NULL, GATE_FUNCTION_FAULT_ADDRESS);
    GATE_DEBUG_TRACE("Test bad integer-error function with fault guard");
    succeeded &= test_function_fault_fail(&div_fault_entry, NULL, GATE_FUNCTION_FAULT_ARITHMETIC);
#endif

#if defined(GATE_SYS_WIN)
    // floating-point errors are not raised on 
    GATE_DEBUG_TRACE("Test bad floating-point-error function with fault guard");
    succeeded &= test_function_fault_fail(&float_fault_entry, NULL, GATE_FUNCTION_FAULT_FLOAT);
#endif

#endif
    return succeeded;
}