File: text_codec_fuzzer.cc

package info (click to toggle)
chromium-browser 70.0.3538.110-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,619,476 kB
  • sloc: cpp: 13,024,755; ansic: 1,349,823; python: 916,672; xml: 314,489; java: 280,047; asm: 276,936; perl: 75,771; objc: 66,634; sh: 45,860; cs: 28,354; php: 11,064; makefile: 10,911; yacc: 9,109; tcl: 8,403; ruby: 4,065; lex: 1,779; pascal: 1,411; lisp: 1,055; awk: 41; jsp: 39; sed: 17; sql: 3
file content (92 lines) | stat: -rw-r--r-- 3,600 bytes parent folder | download | duplicates (2)
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
85
86
87
88
89
90
91
92
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"

#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
#include "third_party/blink/renderer/platform/testing/fuzzed_data_provider.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"

using namespace blink;

// TODO(jsbell): This fuzzes code in wtf/ but has dependencies on platform/,
// so it must live in the latter directory. Once wtf/ moves into platform/wtf
// this should move there as well.

WTF::FlushBehavior kFlushBehavior[] = {WTF::FlushBehavior::kDoNotFlush,
                                       WTF::FlushBehavior::kFetchEOF,
                                       WTF::FlushBehavior::kDataEOF};

WTF::UnencodableHandling kUnencodableHandlingOptions[] = {
    WTF::kEntitiesForUnencodables, WTF::kURLEncodedEntitiesForUnencodables,
    WTF::kCSSEncodedEntitiesForUnencodables};

class TextCodecFuzzHarness {};

// Fuzzer for WTF::TextCodec.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport();
  // The fuzzer picks 3 bytes off the end of the data to initialize metadata, so
  // abort if the input is smaller than that.
  if (size < 3)
    return 0;

  // TODO(csharrison): When crbug.com/701825 is resolved, add the rest of the
  // text codecs.

  // Initializes the codec map.
  static const WTF::TextEncoding encoding = WTF::TextEncoding(
#if defined(UTF_8)
      "UTF-8"
#elif defined(WINDOWS_1252)
      "windows-1252"
#endif
      "");

  FuzzedDataProvider fuzzedData(data, size);

  // Initialize metadata using the fuzzed data.
  bool stopOnError = fuzzedData.ConsumeBool();
  WTF::UnencodableHandling unencodableHandling =
      fuzzedData.PickValueInArray(kUnencodableHandlingOptions);
  WTF::FlushBehavior flushBehavior =
      fuzzedData.PickValueInArray(kFlushBehavior);

  // Now, use the rest of the fuzzy data to stress test decoding and encoding.
  const CString byteString = fuzzedData.ConsumeRemainingBytes();
  std::unique_ptr<TextCodec> codec = NewTextCodec(encoding);

  // Treat as bytes-off-the-wire.
  bool sawError;
  const String decoded = codec->Decode(byteString.data(), byteString.length(),
                                       flushBehavior, stopOnError, sawError);

  // Treat as blink 8-bit string (latin1).
  if (size % sizeof(LChar) == 0) {
    std::unique_ptr<TextCodec> codec = NewTextCodec(encoding);
    codec->Encode(reinterpret_cast<const LChar*>(byteString.data()),
                  byteString.length() / sizeof(LChar), unencodableHandling);
  }

  // Treat as blink 16-bit string (utf-16) if there are an even number of bytes.
  if (size % sizeof(UChar) == 0) {
    std::unique_ptr<TextCodec> codec = NewTextCodec(encoding);
    codec->Encode(reinterpret_cast<const UChar*>(byteString.data()),
                  byteString.length() / sizeof(UChar), unencodableHandling);
  }

  if (decoded.IsNull())
    return 0;

  // Round trip the bytes (aka encode the decoded bytes).
  if (decoded.Is8Bit()) {
    codec->Encode(decoded.Characters8(), decoded.length(), unencodableHandling);
  } else {
    codec->Encode(decoded.Characters16(), decoded.length(),
                  unencodableHandling);
  }
  return 0;
}