Coverage Report

Created: 2026-06-09 06:15

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