Coverage Report

Created: 2023-06-07 06:06

/src/open62541/tests/fuzz/fuzz_tcp_message.cc
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2019 (c) fortiss (Author: Stefan Profanter)
6
 */
7
8
9
#include "custom_memory_manager.h"
10
11
#include <pthread.h>
12
13
#include <open62541/plugin/log_stdout.h>
14
#include <open62541/server_config_default.h>
15
#include <open62541/types.h>
16
17
#include "ua_server_internal.h"
18
19
#include "testing_networklayers.h"
20
21
#define RECEIVE_BUFFER_SIZE 65535
22
145
#define SERVER_PORT 4840
23
24
volatile bool running = true;
25
26
63
static void *serverLoop(void *server_ptr) {
27
63
    UA_Server *server = (UA_Server*) server_ptr;
28
29
119
    while (running) {
30
56
        UA_Server_run_iterate(server, false);
31
56
    }
32
63
    return NULL;
33
63
}
34
35
/*
36
** Main entry point.  The fuzzer invokes this function with each
37
** fuzzed input.
38
*/
39
extern "C" int
40
145
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
41
42
    // Allow the fuzzer to at least create all the necessary structs before limiting memory.
43
    // Otherwise fuzzing is useless
44
145
    UA_memoryManager_setLimit((unsigned long long) -1);
45
46
    /* less debug output */
47
145
    UA_ServerConfig initialConfig;
48
145
    memset(&initialConfig, 0, sizeof(UA_ServerConfig));
49
145
    UA_StatusCode retval = UA_ServerConfig_setMinimal(&initialConfig, SERVER_PORT, NULL);
50
145
    initialConfig.allowEmptyVariables = UA_RULEHANDLING_ACCEPT;
51
145
    if(retval != UA_STATUSCODE_GOOD) {
52
0
        UA_ServerConfig_clean(&initialConfig);
53
0
        UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
54
0
                     "Could not generate the server config");
55
0
        return EXIT_FAILURE;
56
0
    }
57
58
145
    UA_Server *server = UA_Server_newWithConfig(&initialConfig);
59
145
    if(!server) {
60
0
        UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
61
0
                     "Could not create server instance using UA_Server_new");
62
0
        return EXIT_FAILURE;
63
0
    }
64
65
145
    UA_ServerConfig *config = UA_Server_getConfig(server);
66
67
    // Enable the mDNS announce and response functionality
68
145
    config->mdnsEnabled = true;
69
145
    config->mdnsConfig.mdnsServerName = UA_String_fromChars("Sample Multicast Server");
70
71
145
    retval = UA_Server_run_startup(server);
72
145
    if(retval != UA_STATUSCODE_GOOD) {
73
0
        UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
74
0
                     "Could not run UA_Server_run_startup. %s", UA_StatusCode_name(retval));
75
0
        UA_Server_delete(server);
76
0
        return EXIT_FAILURE;
77
0
    }
78
79
145
    if (!UA_memoryManager_setLimitFromLast4Bytes(data, size)) {
80
82
        UA_Server_run_shutdown(server);
81
82
        UA_Server_delete(server);
82
82
        return EXIT_SUCCESS;
83
82
    }
84
63
    size -= 4;
85
86
    // Iterate once to initialize the TCP connection. Otherwise the connect below may come before the server is up.
87
63
    UA_Server_run_iterate(server, true);
88
89
63
    pthread_t serverThread;
90
63
    int rc = pthread_create(&serverThread, NULL, serverLoop, (void *)server);
91
63
    if (rc){
92
93
0
        UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
94
0
                     "return code from pthread_create() is %d", rc);
95
96
0
        UA_Server_run_shutdown(server);
97
0
        UA_Server_delete(server);
98
0
        return -1;
99
0
    }
100
101
63
    int retCode = EXIT_SUCCESS;
102
103
63
    int sockfd = 0;
104
63
    {
105
        // create a client and write to localhost TCP server
106
107
63
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
108
0
        {
109
0
            UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
110
0
                         "Could not create socket");
111
0
            retCode = EXIT_FAILURE;
112
63
        } else {
113
114
63
            struct sockaddr_in serv_addr;
115
63
            serv_addr.sin_family = AF_INET;
116
63
            serv_addr.sin_port = htons(SERVER_PORT);
117
63
            serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
118
119
63
            int status = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
120
63
            if (status >= 0) {
121
63
                if (write(sockfd, data, size) != size) {
122
0
                    UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
123
0
                                 "Did not write %lu bytes", (long unsigned)size);
124
0
                    retCode = EXIT_FAILURE;
125
0
                }
126
63
            } else {
127
0
                UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
128
0
                             "Could not connect to server: %s", strerror(errno));
129
0
                retCode = EXIT_FAILURE;
130
0
            }
131
63
        }
132
133
63
    }
134
63
    running = false;
135
63
    void *status;
136
63
    pthread_join(serverThread, &status);
137
138
    // Process any remaining data. Just repeat a few times to empty all the buffered bytes
139
378
    for (size_t i=0; i<5; i++) {
140
315
        UA_Server_run_iterate(server, false);
141
315
    }
142
63
    close(sockfd);
143
144
145
63
    UA_Server_run_shutdown(server);
146
63
    UA_Server_delete(server);
147
148
63
    return retCode;
149
63
}