/src/open62541_15/tests/fuzz/fuzz_binary_decode.cc
Line | Count | Source |
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 | | #include "custom_memory_manager.h" |
9 | | |
10 | | #include <open62541/plugin/log_stdout.h> |
11 | | #include <open62541/server_config_default.h> |
12 | | #include <open62541/types.h> |
13 | | |
14 | | /* |
15 | | ** Main entry point. The fuzzer invokes this function with each |
16 | | ** fuzzed input. |
17 | | */ |
18 | 7.36k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
19 | 7.36k | if(size <= 6) |
20 | 8 | return 0; |
21 | | |
22 | | // set the available memory |
23 | 7.35k | if(!UA_memoryManager_setLimitFromLast4Bytes(data, size)) |
24 | 0 | return 0; |
25 | | |
26 | 7.35k | data += 4; |
27 | 7.35k | size -= 4; |
28 | | |
29 | | // get some random type |
30 | 7.35k | uint16_t typeIndex = (uint16_t)(data[0] | data[1] << 8); |
31 | 7.35k | data += 2; |
32 | 7.35k | size -= 2; |
33 | | |
34 | 7.35k | if(typeIndex >= UA_TYPES_COUNT) |
35 | 27 | return UA_FALSE; |
36 | | |
37 | | // For DataValue types, consume 2 extra bytes to construct a |
38 | | // NumericRange for testing UA_DataValue_copyRange |
39 | 7.32k | uint8_t rangeMin = 0, rangeMax = 0; |
40 | 7.32k | if(typeIndex == UA_TYPES_DATAVALUE && size >= 2) { |
41 | 1.07k | rangeMin = data[0]; |
42 | 1.07k | rangeMax = data[1]; |
43 | 1.07k | data += 2; |
44 | 1.07k | size -= 2; |
45 | 1.07k | } |
46 | | |
47 | 7.32k | void *dst = UA_new(&UA_TYPES[typeIndex]); |
48 | 7.32k | if(!dst) |
49 | 27 | return 0; |
50 | | |
51 | 7.30k | const UA_ByteString binary = { |
52 | 7.30k | size, //length |
53 | 7.30k | (UA_Byte *) (void *) data |
54 | 7.30k | }; |
55 | | |
56 | 7.30k | UA_StatusCode ret = UA_decodeBinary(&binary, dst, &UA_TYPES[typeIndex], NULL); |
57 | 7.30k | if(ret != UA_STATUSCODE_GOOD) { |
58 | 3.44k | UA_delete(dst, &UA_TYPES[typeIndex]); |
59 | 3.44k | return 0; |
60 | 3.44k | } |
61 | | |
62 | | // copy the datatype to test |
63 | 3.86k | void *dstCopy = UA_new(&UA_TYPES[typeIndex]); |
64 | 3.86k | if(!dstCopy) { |
65 | 9 | UA_delete(dst, &UA_TYPES[typeIndex]); |
66 | 9 | return 0; |
67 | 9 | } |
68 | 3.85k | ret = UA_copy(dst, dstCopy, &UA_TYPES[typeIndex]); |
69 | 3.85k | if(ret != UA_STATUSCODE_GOOD) { |
70 | 322 | UA_delete(dst, &UA_TYPES[typeIndex]); |
71 | 322 | UA_delete(dstCopy, &UA_TYPES[typeIndex]); |
72 | 322 | return 0; |
73 | 322 | } |
74 | | |
75 | | // compare with copy |
76 | 3.52k | UA_assert(UA_order(dst, dstCopy, &UA_TYPES[typeIndex]) == UA_ORDER_EQ); |
77 | 3.52k | UA_delete(dstCopy, &UA_TYPES[typeIndex]); |
78 | | |
79 | | // now also test encoding |
80 | 3.52k | size_t encSize = UA_calcSizeBinary(dst, &UA_TYPES[typeIndex], NULL); |
81 | 3.52k | UA_ByteString encoded; |
82 | 3.52k | ret = UA_ByteString_allocBuffer(&encoded, encSize); |
83 | 3.52k | if(ret != UA_STATUSCODE_GOOD) { |
84 | 0 | UA_delete(dst, &UA_TYPES[typeIndex]); |
85 | 0 | return 0; |
86 | 0 | } |
87 | | |
88 | 3.52k | ret = UA_encodeBinary(dst, &UA_TYPES[typeIndex], &encoded, NULL); |
89 | 3.52k | UA_assert(ret == UA_STATUSCODE_GOOD); |
90 | | |
91 | 3.52k | UA_ByteString_clear(&encoded); |
92 | | |
93 | | // Test UA_DataValue_copyRange with fuzz-derived range parameters. |
94 | | // This exercises array sub-range copying where mismatched range |
95 | | // dimensions can cause out-of-bounds access. |
96 | 3.52k | if(typeIndex == UA_TYPES_DATAVALUE) { |
97 | 854 | UA_NumericRangeDimension dim; |
98 | 854 | dim.min = rangeMin; |
99 | 854 | dim.max = rangeMax; |
100 | 854 | UA_NumericRange range; |
101 | 854 | range.dimensionsSize = 1; |
102 | 854 | range.dimensions = &dim; |
103 | | |
104 | 854 | UA_DataValue dstRange; |
105 | 854 | UA_DataValue_init(&dstRange); |
106 | 854 | UA_DataValue_copyRange((UA_DataValue*)dst, &dstRange, range); |
107 | 854 | UA_DataValue_clear(&dstRange); |
108 | 854 | } |
109 | | |
110 | 3.52k | UA_delete(dst, &UA_TYPES[typeIndex]); |
111 | 3.52k | return 0; |
112 | 3.52k | } |