123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /* 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/. */
- #include "custom_memory_manager.h"
- #include <ua_types.h>
- #include "ua_server_internal.h"
- #include "ua_config_default.h"
- #include "ua_log_stdout.h"
- #include "ua_types_encoding_binary.h"
- static UA_Boolean tortureEncoding(const uint8_t *data, size_t size, size_t *newOffset) {
- *newOffset = 0;
- if (size <= 2)
- return UA_FALSE;
- // get some random type
- uint16_t typeIndex = (uint16_t)(data[0] | data[1] << 8);
- data += 2;
- size -= 2;
- if (typeIndex >= UA_TYPES_COUNT)
- return UA_FALSE;
- void *dst = UA_new(&UA_TYPES[typeIndex]);
- if (!dst)
- return UA_FALSE;
- const UA_ByteString binary = {
- size, //length
- (UA_Byte *) (void *) data
- };
- UA_StatusCode ret = UA_decodeBinary(&binary, newOffset, dst, &UA_TYPES[typeIndex], NULL);
- if (ret == UA_STATUSCODE_GOOD) {
- // copy the datatype to test
- void *dstCopy = UA_new(&UA_TYPES[typeIndex]);
- if (!dstCopy)
- return UA_FALSE;
- UA_copy(dst, dstCopy, &UA_TYPES[typeIndex]);
- UA_delete(dstCopy, &UA_TYPES[typeIndex]);
- // now also test encoding
- UA_ByteString encoded;
- UA_ByteString_allocBuffer(&encoded, *newOffset);
- const UA_Byte *end = &encoded.data[*newOffset];
- UA_Byte *pos = encoded.data;
- ret = UA_encodeBinary(dst, &UA_TYPES[typeIndex], &pos, &end, NULL, NULL);
- if (ret == UA_STATUSCODE_GOOD) {
- // do nothing
- }
- UA_ByteString_deleteMembers(&encoded);
- }
- UA_delete(dst, &UA_TYPES[typeIndex]);
- return UA_TRUE;
- }
- static UA_Boolean tortureExtensionObject(const uint8_t *data, size_t size, size_t *newOffset) {
- *newOffset = 0;
- // check if there is still enough data to create an extension object
- // we need at least a nodeid.numeric which equals to 4 bytes
- if (size < 4)
- return UA_FALSE;
- UA_UInt32 identifier = (UA_UInt32)(data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24);
- size-= 4;
- UA_NodeId objectId = UA_NODEID_NUMERIC(0, identifier);
- UA_ExtensionObject obj;
- UA_ExtensionObject_init(&obj);
- obj.encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
- obj.content.encoded.typeId = objectId;
- obj.content.encoded.body.length = size;
- obj.content.encoded.body.data = (UA_Byte*)(void*)data; // discard const. We are sure that we don't change it
- const UA_DataType *type = UA_findDataTypeByBinary(&obj.content.encoded.typeId);
- UA_StatusCode ret = UA_STATUSCODE_GOOD;
- if (type) {
- void *dstCopy = UA_new(type);
- if (!dstCopy)
- return UA_FALSE;
- ret = UA_decodeBinary(&obj.content.encoded.body, newOffset, dstCopy, type, NULL);
- if (ret == UA_STATUSCODE_GOOD) {
- UA_Variant var;
- UA_Variant_init(&var);
- UA_Variant_setScalar(&var, dstCopy, type);
- }
- UA_delete(dstCopy, type);
- }
- return ret==UA_STATUSCODE_GOOD;
- }
- /*
- ** Main entry point. The fuzzer invokes this function with each
- ** fuzzed input.
- */
- extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- if (!UA_memoryManager_setLimitFromLast4Bytes(data, size))
- return 0;
- size -= 4;
- size_t offset;
- if (!tortureEncoding(data, size, &offset)) {
- return 0;
- }
- if (offset >= size)
- return 0;
- tortureExtensionObject(&data[offset], size-offset, &offset);
- return 0;
- }
|