1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/filter/fuzzed_source_stream.h"
6
7 #include <fuzzer/FuzzedDataProvider.h>
8
9 #include <algorithm>
10 #include <string>
11 #include <utility>
12
13 #include "base/bind.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17
18 namespace net {
19
20 namespace {
21
22 // Common net error codes that can be returned by a SourceStream.
23 const Error kReadErrors[] = {OK, ERR_FAILED, ERR_CONTENT_DECODING_FAILED};
24
25 } // namespace
26
FuzzedSourceStream(FuzzedDataProvider * data_provider)27 FuzzedSourceStream::FuzzedSourceStream(FuzzedDataProvider* data_provider)
28 : SourceStream(SourceStream::TYPE_NONE),
29 data_provider_(data_provider),
30 read_pending_(false),
31 end_returned_(false) {}
32
~FuzzedSourceStream()33 FuzzedSourceStream::~FuzzedSourceStream() {
34 DCHECK(!read_pending_);
35 }
36
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)37 int FuzzedSourceStream::Read(IOBuffer* buf,
38 int buf_len,
39 CompletionOnceCallback callback) {
40 DCHECK(!read_pending_);
41 DCHECK(!end_returned_);
42 DCHECK_LE(0, buf_len);
43
44 bool sync = data_provider_->ConsumeBool();
45 int result = data_provider_->ConsumeIntegralInRange(0, buf_len);
46 std::string data = data_provider_->ConsumeBytesAsString(result);
47 result = data.size();
48
49 if (result <= 0)
50 result = data_provider_->PickValueInArray(kReadErrors);
51
52 if (sync) {
53 if (result > 0) {
54 std::copy(data.data(), data.data() + data.size(), buf->data());
55 } else {
56 end_returned_ = true;
57 }
58 return result;
59 }
60
61 scoped_refptr<IOBuffer> pending_read_buf = buf;
62
63 read_pending_ = true;
64 // |this| is owned by the caller so use base::Unretained is safe.
65 base::ThreadTaskRunnerHandle::Get()->PostTask(
66 FROM_HERE, base::BindOnce(&FuzzedSourceStream::OnReadComplete,
67 base::Unretained(this), std::move(callback),
68 data, pending_read_buf, result));
69 return ERR_IO_PENDING;
70 }
71
Description() const72 std::string FuzzedSourceStream::Description() const {
73 return "";
74 }
75
MayHaveMoreBytes() const76 bool FuzzedSourceStream::MayHaveMoreBytes() const {
77 return !end_returned_;
78 }
79
OnReadComplete(CompletionOnceCallback callback,const std::string & fuzzed_data,scoped_refptr<IOBuffer> read_buf,int result)80 void FuzzedSourceStream::OnReadComplete(CompletionOnceCallback callback,
81 const std::string& fuzzed_data,
82 scoped_refptr<IOBuffer> read_buf,
83 int result) {
84 DCHECK(read_pending_);
85
86 if (result > 0) {
87 std::copy(fuzzed_data.data(), fuzzed_data.data() + result,
88 read_buf->data());
89 } else {
90 end_returned_ = true;
91 }
92 read_pending_ = false;
93 std::move(callback).Run(result);
94 }
95
96 } // namespace net
97