aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/blockcodecs/fuzz/main.cpp
blob: cddf79f7f62681f0bbb5d9baef457cbc969088e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <contrib/libs/protobuf-mutator/src/libfuzzer/libfuzzer_macro.h> 
#include <google/protobuf/stubs/logging.h>
 
#include <library/cpp/blockcodecs/codecs.h>
#include <library/cpp/blockcodecs/fuzz/proto/case.pb.h>
#include <library/cpp/blockcodecs/stream.h>

#include <util/stream/input.h> 
#include <util/stream/length.h> 
#include <util/stream/mem.h>
#include <util/stream/null.h> 
#include <util/stream/str.h> 

using NBlockCodecs::NFuzz::TPackUnpackCase; 
using NBlockCodecs::TCodedOutput; 
using NBlockCodecs::TDecodedInput; 

static void ValidateBufferSize(const ui32 size) { 
    Y_ENSURE(size > 0 && size <= 16ULL * 1024); 
} 
 
static void DoOnlyDecode(const TPackUnpackCase& case_) { 
    if (!case_.GetPacked()) { 
        return; 
    }

    TMemoryInput mi(case_.GetData().data(), case_.GetData().size()); 
    TDecodedInput di(&mi); 
    TNullOutput no; 
    TCountingOutput cno(&no); 
    TransferData(&di, &cno); 
}
 
static void DoDecodeEncode(const TPackUnpackCase& case_) { 
    auto* const codec = NBlockCodecs::Codec(case_.GetCodecName()); 
    Y_ENSURE(codec); 
 
    TMemoryInput mi(case_.GetData().data(), case_.GetData().size()); 
    TDecodedInput di(&mi, codec); 
    TStringStream decoded; 
    TransferData(&di, &decoded); 
    TNullOutput no; 
    TCountingOutput cno(&no); 
    TCodedOutput co(&cno, codec, case_.GetBufferLength()); 
    TransferData(&decoded, &co); 
    co.Flush(); 
 
    Y_VERIFY((case_.GetData().size() > 0) == (cno.Counter() > 0)); 
    Y_VERIFY((case_.GetData().size() > 0) == (decoded.Str().size() > 0)); 
} 
 
static void DoEncodeDecode(const TPackUnpackCase& case_) { 
    auto* const codec = NBlockCodecs::Codec(case_.GetCodecName()); 
    Y_ENSURE(codec); 
 
    TMemoryInput mi(case_.GetData().data(), case_.GetData().size()); 
    TStringStream encoded; 
    TCodedOutput co(&encoded, codec, case_.GetBufferLength()); 
    TransferData(&mi, &co); 
    co.Flush(); 
    TStringStream decoded; 
    TDecodedInput di(&encoded, codec); 
    TransferData(&di, &decoded); 
 
    Y_VERIFY((case_.GetData().size() > 0) == (encoded.Str().size() > 0)); 
    Y_VERIFY(case_.GetData() == decoded.Str()); 
} 
 
DEFINE_BINARY_PROTO_FUZZER(const TPackUnpackCase& case_) { 
    try { 
        if (!case_.GetCodecName()) { 
            DoOnlyDecode(case_); 
            return; 
        } 
 
        ValidateBufferSize(case_.GetBufferLength()); 
        if (case_.GetPacked()) { 
            DoDecodeEncode(case_); 
        } else { 
            DoEncodeDecode(case_); 
        } 
    } catch (const std::exception&) { 
    } 
}