/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 | } |