Coverage Report

Created: 2026-08-14 07:31

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.41k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
19
7.41k
    if(size <= 6)
20
8
        return 0;
21
22
    // set the available memory
23
7.40k
    if(!UA_memoryManager_setLimitFromLast4Bytes(data, size))
24
0
        return 0;
25
26
7.40k
    data += 4;
27
7.40k
    size -= 4;
28
29
    // get some random type
30
7.40k
    uint16_t typeIndex = (uint16_t)(data[0] | data[1] << 8);
31
7.40k
    data += 2;
32
7.40k
    size -= 2;
33
34
7.40k
    if(typeIndex >= UA_TYPES_COUNT)
35
22
        return UA_FALSE;
36
37
    // For DataValue types, consume 2 extra bytes to construct a
38
    // NumericRange for testing UA_DataValue_copyRange
39
7.38k
    uint8_t rangeMin = 0, rangeMax = 0;
40
7.38k
    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.38k
    void *dst = UA_new(&UA_TYPES[typeIndex]);
48
7.38k
    if(!dst)
49
26
        return 0;
50
51
7.35k
    const UA_ByteString binary = {
52
7.35k
            size, //length
53
7.35k
            (UA_Byte *) (void *) data
54
7.35k
    };
55
56
7.35k
    UA_StatusCode ret = UA_decodeBinary(&binary, dst, &UA_TYPES[typeIndex], NULL);
57
7.35k
    if(ret != UA_STATUSCODE_GOOD) {
58
3.39k
        UA_delete(dst, &UA_TYPES[typeIndex]);
59
3.39k
        return 0;
60
3.39k
    }
61
62
    // copy the datatype to test
63
3.96k
    void *dstCopy = UA_new(&UA_TYPES[typeIndex]);
64
3.96k
    if(!dstCopy) {
65
7
        UA_delete(dst, &UA_TYPES[typeIndex]);
66
7
        return 0;
67
7
    }
68
3.95k
    ret = UA_copy(dst, dstCopy, &UA_TYPES[typeIndex]);
69
3.95k
    if(ret != UA_STATUSCODE_GOOD) {
70
319
        UA_delete(dst, &UA_TYPES[typeIndex]);
71
319
        UA_delete(dstCopy, &UA_TYPES[typeIndex]);
72
319
        return 0;
73
319
    }
74
    
75
    // compare with copy
76
3.63k
    UA_assert(UA_order(dst, dstCopy, &UA_TYPES[typeIndex]) == UA_ORDER_EQ);
77
3.63k
    UA_delete(dstCopy, &UA_TYPES[typeIndex]);
78
    
79
    // now also test encoding
80
3.63k
    size_t encSize = UA_calcSizeBinary(dst, &UA_TYPES[typeIndex], NULL);
81
3.63k
    UA_ByteString encoded;
82
3.63k
    ret = UA_ByteString_allocBuffer(&encoded, encSize);
83
3.63k
    if(ret != UA_STATUSCODE_GOOD) {
84
0
        UA_delete(dst, &UA_TYPES[typeIndex]);
85
0
        return 0;
86
0
    }
87
88
3.63k
    ret = UA_encodeBinary(dst, &UA_TYPES[typeIndex], &encoded, NULL);
89
3.63k
    UA_assert(ret == UA_STATUSCODE_GOOD);
90
91
3.63k
    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.63k
    if(typeIndex == UA_TYPES_DATAVALUE) {
97
953
        UA_NumericRangeDimension dim;
98
953
        dim.min = rangeMin;
99
953
        dim.max = rangeMax;
100
953
        UA_NumericRange range;
101
953
        range.dimensionsSize = 1;
102
953
        range.dimensions = &dim;
103
104
953
        UA_DataValue dstRange;
105
953
        UA_DataValue_init(&dstRange);
106
953
        UA_DataValue_copyRange((UA_DataValue*)dst, &dstRange, range);
107
953
        UA_DataValue_clear(&dstRange);
108
953
    }
109
110
3.63k
    UA_delete(dst, &UA_TYPES[typeIndex]);
111
3.63k
    return 0;
112
3.63k
}