summaryrefslogtreecommitdiff
path: root/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
blob: 70d73c8c52bb53f84227934541b6ec7a52b56a33 (plain)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// Authors: corbin.souffrant@leviathansecurity.com
//          dylan.katz@leviathansecurity.com

#include <MediaMuxerFuzzer.h>
#include <cutils/ashmem.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/MediaMuxer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {

// Can't seem to get setBuffer or setString working. It always segfaults on a
// null pointer read or memleaks. So that functionality is missing.
void createMessage(AMessage *msg, FuzzedDataProvider *fdp) {
  size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 32);
  while (fdp->remaining_bytes() > 0 && count > 0) {
    uint8_t function_id =
        fdp->ConsumeIntegralInRange<uint8_t>(0, amessage_setvals.size() - 1);
    amessage_setvals[function_id](msg, fdp);
    count--;
  }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  FuzzedDataProvider fdp = FuzzedDataProvider(data, size);

  size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
  int fd = ashmem_create_region("mediamuxer_fuzz_region", data_size);
  if (fd < 0)
    return 0;

  uint8_t *sh_data = static_cast<uint8_t *>(
      mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
  if (sh_data == MAP_FAILED)
    return 0;

  MediaMuxer::OutputFormat format =
      (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4);
  sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, format);
  if (mMuxer == nullptr) {
    return 0;
  }

  while (fdp.remaining_bytes() > 1) {
    switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) {
    case 0: {
      // For some reason it only likes mp4s here...
      if (format == 1 || format == 4)
        break;

      sp<AMessage> a_format(new AMessage);
      createMessage(a_format.get(), &fdp);
      mMuxer->addTrack(a_format);
      break;
    }
    case 1: {
      mMuxer->start();
      break;
    }
    case 2: {
      int degrees = fdp.ConsumeIntegral<int>();
      mMuxer->setOrientationHint(degrees);
      break;
    }
    case 3: {
      int latitude = fdp.ConsumeIntegral<int>();
      int longitude = fdp.ConsumeIntegral<int>();
      mMuxer->setLocation(latitude, longitude);
      break;
    }
    case 4: {
      size_t buf_size = fdp.ConsumeIntegralInRange<size_t>(0, data_size);
      sp<ABuffer> a_buffer(new ABuffer(buf_size));

      size_t trackIndex = fdp.ConsumeIntegral<size_t>();
      int64_t timeUs = fdp.ConsumeIntegral<int64_t>();
      uint32_t flags = fdp.ConsumeIntegral<uint32_t>();
      mMuxer->writeSampleData(a_buffer, trackIndex, timeUs, flags);
    }
    }
  }

  if (fdp.ConsumeBool())
    mMuxer->stop();

  munmap(sh_data, data_size);
  close(fd);
  return 0;
}
} // namespace android