Coverage Report

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