Files
softbus_OPC/third_party/open62541/tests/fuzz/fuzz_tcp_message.cc
2026-06-09 17:27:24 +08:00

154 lines
4.7 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 (c) fortiss (Author: Stefan Profanter)
*/
#include "custom_memory_manager.h"
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <open62541/plugin/log_stdout.h>
#include <open62541/server_config_default.h>
#include <open62541/types.h>
#include "ua_server_internal.h"
#include "testing_networklayers.h"
#define RECEIVE_BUFFER_SIZE 65535
#define SERVER_PORT 4840
volatile bool running = true;
static void *serverLoop(void *server_ptr) {
UA_Server *server = (UA_Server*) server_ptr;
while (running) {
UA_Server_run_iterate(server, false);
}
return NULL;
}
/*
** Main entry point. The fuzzer invokes this function with each
** fuzzed input.
*/
extern "C" int
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Allow the fuzzer to at least create all the necessary structs before limiting memory.
// Otherwise fuzzing is useless
UA_memoryManager_setLimit((unsigned long long) -1);
/* less debug output */
UA_ServerConfig initialConfig;
memset(&initialConfig, 0, sizeof(UA_ServerConfig));
UA_StatusCode retval = UA_ServerConfig_setMinimal(&initialConfig, SERVER_PORT, NULL);
initialConfig.allowEmptyVariables = UA_RULEHANDLING_ACCEPT;
if(retval != UA_STATUSCODE_GOOD) {
UA_ServerConfig_clean(&initialConfig);
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
"Could not generate the server config");
return EXIT_FAILURE;
}
UA_Server *server = UA_Server_newWithConfig(&initialConfig);
if(!server) {
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
"Could not create server instance using UA_Server_new");
return EXIT_FAILURE;
}
UA_ServerConfig *config = UA_Server_getConfig(server);
// Enable the mDNS announce and response functionality
config->mdnsEnabled = true;
config->mdnsConfig.mdnsServerName = UA_String_fromChars("Sample Multicast Server");
retval = UA_Server_run_startup(server);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
"Could not run UA_Server_run_startup. %s", UA_StatusCode_name(retval));
UA_Server_delete(server);
return EXIT_FAILURE;
}
if (!UA_memoryManager_setLimitFromLast4Bytes(data, size)) {
UA_Server_run_shutdown(server);
UA_Server_delete(server);
return EXIT_SUCCESS;
}
size -= 4;
// Iterate once to initialize the TCP connection. Otherwise the connect below may come before the server is up.
UA_Server_run_iterate(server, true);
pthread_t serverThread;
int rc = pthread_create(&serverThread, NULL, serverLoop, (void *)server);
if (rc){
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
"return code from pthread_create() is %d", rc);
UA_Server_run_shutdown(server);
UA_Server_delete(server);
return -1;
}
int retCode = EXIT_SUCCESS;
int sockfd = 0;
{
// create a client and write to localhost TCP server
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
"Could not create socket");
retCode = EXIT_FAILURE;
} else {
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int status = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (status >= 0) {
if (write(sockfd, data, size) != size) {
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
"Did not write %lu bytes", (long unsigned)size);
retCode = EXIT_FAILURE;
}
} else {
UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT,
"Could not connect to server: %s", strerror(errno));
retCode = EXIT_FAILURE;
}
}
}
running = false;
void *status;
pthread_join(serverThread, &status);
// Process any remaining data. Just repeat a few times to empty all the buffered bytes
for (size_t i=0; i<5; i++) {
UA_Server_run_iterate(server, false);
}
close(sockfd);
UA_Server_run_shutdown(server);
UA_Server_delete(server);
return retCode;
}