Coverage Report

Created: 2026-03-31 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/tests/fuzz/fuzz_tcp_message.cc
Line
Count
Source
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
273
#define SERVER_PORT 4840
27
28
volatile bool running = true;
29
30
94
static void *serverLoop(void *server_ptr) {
31
94
    UA_Server *server = (UA_Server*) server_ptr;
32
33
115
    while (running) {
34
21
        UA_Server_run_iterate(server, false);
35
21
    }
36
94
    return NULL;
37
94
}
38
39
/*
40
** Main entry point.  The fuzzer invokes this function with each
41
** fuzzed input.
42
*/
43
extern "C" int
44
273
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
273
    UA_memoryManager_setLimit((unsigned long long) -1);
49
50
    /* less debug output */
51
273
    UA_ServerConfig initialConfig;
52
273
    memset(&initialConfig, 0, sizeof(UA_ServerConfig));
53
273
    UA_StatusCode retval = UA_ServerConfig_setMinimal(&initialConfig, SERVER_PORT, NULL);
54
273
    initialConfig.allowEmptyVariables = UA_RULEHANDLING_ACCEPT;
55
273
    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
273
    UA_Server *server = UA_Server_newWithConfig(&initialConfig);
63
273
    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
273
    UA_ServerConfig *config = UA_Server_getConfig(server);
70
71
    // Enable the mDNS announce and response functionality
72
273
    config->mdnsEnabled = true;
73
273
    config->mdnsConfig.mdnsServerName = UA_String_fromChars("Sample-Multicast-Server");
74
75
273
    retval = UA_Server_run_startup(server);
76
273
    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
273
    if (!UA_memoryManager_setLimitFromLast4Bytes(data, size)) {
84
179
        UA_Server_run_shutdown(server);
85
179
        UA_Server_delete(server);
86
179
        return EXIT_SUCCESS;
87
179
    }
88
94
    size -= 4;
89
90
    // Iterate once to initialize the TCP connection. Otherwise the connect below may come before the server is up.
91
94
    UA_Server_run_iterate(server, true);
92
93
94
    pthread_t serverThread;
94
94
    int rc = pthread_create(&serverThread, NULL, serverLoop, (void *)server);
95
94
    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
94
    int retCode = EXIT_SUCCESS;
106
107
94
    int sockfd = 0;
108
94
    {
109
        // create a client and write to localhost TCP server
110
111
94
        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
94
        } else {
117
118
94
            struct sockaddr_in serv_addr;
119
94
            serv_addr.sin_family = AF_INET;
120
94
            serv_addr.sin_port = htons(SERVER_PORT);
121
94
            serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
122
123
94
            int status = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
124
94
            if (status >= 0) {
125
94
                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
94
            } 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
94
        }
136
137
94
    }
138
94
    running = false;
139
94
    void *status;
140
94
    pthread_join(serverThread, &status);
141
142
    // Process any remaining data. Just repeat a few times to empty all the buffered bytes
143
564
    for (size_t i=0; i<5; i++) {
144
470
        UA_Server_run_iterate(server, false);
145
470
    }
146
94
    close(sockfd);
147
148
149
94
    UA_Server_run_shutdown(server);
150
94
    UA_Server_delete(server);
151
152
94
    return retCode;
153
94
}