Coverage Report

Created: 2026-05-16 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}