mirror of
https://github.com/open62541/open62541.git
synced 2026-10-19 14:22:58 +08:00
cee6eb84d0
To accommodate for fuzzing code currently uncovered, e.g. copy operations. Signed-off-by: David Korczynski <david@adalogics.com>
113 lines
3.2 KiB
C++
113 lines
3.2 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 <open62541/plugin/log_stdout.h>
|
|
#include <open62541/server_config_default.h>
|
|
#include <open62541/types.h>
|
|
|
|
/*
|
|
** Main entry point. The fuzzer invokes this function with each
|
|
** fuzzed input.
|
|
*/
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
if(size <= 6)
|
|
return 0;
|
|
|
|
// set the available memory
|
|
if(!UA_memoryManager_setLimitFromLast4Bytes(data, size))
|
|
return 0;
|
|
|
|
data += 4;
|
|
size -= 4;
|
|
|
|
// 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;
|
|
|
|
// For DataValue types, consume 2 extra bytes to construct a
|
|
// NumericRange for testing UA_DataValue_copyRange
|
|
uint8_t rangeMin = 0, rangeMax = 0;
|
|
if(typeIndex == UA_TYPES_DATAVALUE && size >= 2) {
|
|
rangeMin = data[0];
|
|
rangeMax = data[1];
|
|
data += 2;
|
|
size -= 2;
|
|
}
|
|
|
|
void *dst = UA_new(&UA_TYPES[typeIndex]);
|
|
if(!dst)
|
|
return 0;
|
|
|
|
const UA_ByteString binary = {
|
|
size, //length
|
|
(UA_Byte *) (void *) data
|
|
};
|
|
|
|
UA_StatusCode ret = UA_decodeBinary(&binary, dst, &UA_TYPES[typeIndex], NULL);
|
|
if(ret != UA_STATUSCODE_GOOD) {
|
|
UA_delete(dst, &UA_TYPES[typeIndex]);
|
|
return 0;
|
|
}
|
|
|
|
// copy the datatype to test
|
|
void *dstCopy = UA_new(&UA_TYPES[typeIndex]);
|
|
if(!dstCopy) {
|
|
UA_delete(dst, &UA_TYPES[typeIndex]);
|
|
return 0;
|
|
}
|
|
ret = UA_copy(dst, dstCopy, &UA_TYPES[typeIndex]);
|
|
if(ret != UA_STATUSCODE_GOOD) {
|
|
UA_delete(dst, &UA_TYPES[typeIndex]);
|
|
UA_delete(dstCopy, &UA_TYPES[typeIndex]);
|
|
return 0;
|
|
}
|
|
|
|
// compare with copy
|
|
UA_assert(UA_order(dst, dstCopy, &UA_TYPES[typeIndex]) == UA_ORDER_EQ);
|
|
UA_delete(dstCopy, &UA_TYPES[typeIndex]);
|
|
|
|
// now also test encoding
|
|
size_t encSize = UA_calcSizeBinary(dst, &UA_TYPES[typeIndex], NULL);
|
|
UA_ByteString encoded;
|
|
ret = UA_ByteString_allocBuffer(&encoded, encSize);
|
|
if(ret != UA_STATUSCODE_GOOD) {
|
|
UA_delete(dst, &UA_TYPES[typeIndex]);
|
|
return 0;
|
|
}
|
|
|
|
ret = UA_encodeBinary(dst, &UA_TYPES[typeIndex], &encoded, NULL);
|
|
UA_assert(ret == UA_STATUSCODE_GOOD);
|
|
|
|
UA_ByteString_clear(&encoded);
|
|
|
|
// Test UA_DataValue_copyRange with fuzz-derived range parameters.
|
|
// This exercises array sub-range copying where mismatched range
|
|
// dimensions can cause out-of-bounds access.
|
|
if(typeIndex == UA_TYPES_DATAVALUE) {
|
|
UA_NumericRangeDimension dim;
|
|
dim.min = rangeMin;
|
|
dim.max = rangeMax;
|
|
UA_NumericRange range;
|
|
range.dimensionsSize = 1;
|
|
range.dimensions = &dim;
|
|
|
|
UA_DataValue dstRange;
|
|
UA_DataValue_init(&dstRange);
|
|
UA_DataValue_copyRange((UA_DataValue*)dst, &dstRange, range);
|
|
UA_DataValue_clear(&dstRange);
|
|
}
|
|
|
|
UA_delete(dst, &UA_TYPES[typeIndex]);
|
|
return 0;
|
|
}
|