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