1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/stat.h>
21 #include "native_avdemuxer.h"
22 #include "native_avformat.h"
23 #include "native_avsource.h"
24 #include "native_avmemory.h"
25 
26 #define FUZZ_PROJECT_NAME "demuxer_fuzzer"
27 namespace OHOS {
28 static int32_t g_width = 3840;
29 static int32_t g_height = 2160;
GetFileSize(const char *fileName)30 static int64_t GetFileSize(const char *fileName)
31 {
32     int64_t fileSize = 0;
33     if (fileName != nullptr) {
34         struct stat fileStatus {};
35         if (stat(fileName, &fileStatus) == 0) {
36             fileSize = static_cast<int64_t>(fileStatus.st_size);
37         }
38     }
39     return fileSize;
40 }
41 
SetVarValue(OH_AVCodecBufferAttr attr, const int &tarckType, bool &audioIsEnd, bool &videoIsEnd)42 static void SetVarValue(OH_AVCodecBufferAttr attr, const int &tarckType, bool &audioIsEnd, bool &videoIsEnd)
43 {
44     if (tarckType == MEDIA_TYPE_AUD && (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS)) {
45         audioIsEnd = true;
46     }
47 
48     if (tarckType == MEDIA_TYPE_VID && (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS)) {
49         videoIsEnd = true;
50     }
51 }
52 
RunNormalDemuxer()53 void RunNormalDemuxer()
54 {
55     int tarckType = 0;
56     int32_t trackCount;
57     OH_AVCodecBufferAttr attr;
58     bool audioIsEnd = false;
59     bool videoIsEnd = false;
60     const char *file = "/data/test/media/01_video_audio.mp4";
61     int fd = open(file, O_RDONLY);
62     int64_t size = GetFileSize(file);
63     OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, size);
64     if (!source) {
65         close(fd);
66         return;
67     }
68     OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source);
69     if (!demuxer) {
70         close(fd);
71         return;
72     }
73     OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
74     OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount);
75     for (int32_t index = 0; index < trackCount; index++) {
76         OH_AVDemuxer_SelectTrackByID(demuxer, index);
77     }
78     OH_AVMemory *memory = OH_AVMemory_Create(g_width * g_height);
79     while (!audioIsEnd || !videoIsEnd) {
80         for (int32_t index = 0; index < trackCount; index++) {
81             OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
82             OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &tarckType);
83             if ((audioIsEnd && (tarckType == MEDIA_TYPE_AUD)) || (videoIsEnd && (tarckType == MEDIA_TYPE_VID))) {
84                 continue;
85             }
86             if (trackFormat) {
87                 OH_AVFormat_Destroy(trackFormat);
88             }
89             OH_AVDemuxer_ReadSample(demuxer, index, memory, &attr);
90             SetVarValue(attr, tarckType, audioIsEnd, videoIsEnd);
91         }
92     }
93     OH_AVDemuxer_Destroy(demuxer);
94     OH_AVSource_Destroy(source);
95     if (sourceFormat) {
96         OH_AVFormat_Destroy(sourceFormat);
97     }
98     if (memory) {
99         OH_AVMemory_Destroy(memory);
100     }
101     close(fd);
102 }
103 
RunNormalDemuxerApi11()104 void RunNormalDemuxerApi11()
105 {
106     int tarckType = 0;
107     int32_t trackCount;
108     OH_AVCodecBufferAttr attr;
109     bool audioIsEnd = false;
110     bool videoIsEnd = false;
111     const char *file = "/data/test/media/01_video_audio.mp4";
112     int fd = open(file, O_RDONLY);
113     int64_t size = GetFileSize(file);
114     OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, size);
115     if (!source) {
116         close(fd);
117         return;
118     }
119     OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source);
120     if (!demuxer) {
121         close(fd);
122         return;
123     }
124     OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
125     OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount);
126     for (int32_t index = 0; index < trackCount; index++) {
127         OH_AVDemuxer_SelectTrackByID(demuxer, index);
128     }
129     OH_AVBuffer *buffer = OH_AVBuffer_Create(g_width * g_height);
130     while (!audioIsEnd || !videoIsEnd) {
131         for (int32_t index = 0; index < trackCount; index++) {
132             OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
133             OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &tarckType);
134             if ((audioIsEnd && (tarckType == MEDIA_TYPE_AUD)) || (videoIsEnd && (tarckType == MEDIA_TYPE_VID))) {
135                 continue;
136             }
137             if (trackFormat) {
138                 OH_AVFormat_Destroy(trackFormat);
139             }
140             OH_AVDemuxer_ReadSampleBuffer(demuxer, index, buffer);
141             OH_AVBuffer_GetBufferAttr(buffer, &attr);
142             SetVarValue(attr, tarckType, audioIsEnd, videoIsEnd);
143         }
144     }
145     OH_AVDemuxer_Destroy(demuxer);
146     OH_AVSource_Destroy(source);
147     if (sourceFormat) {
148         OH_AVFormat_Destroy(sourceFormat);
149     }
150     if (buffer) {
151         OH_AVBuffer_Destroy(buffer);
152     }
153     close(fd);
154 }
155 
DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)156 bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
157 {
158     if (size < sizeof(int64_t)) {
159         return false;
160     }
161     RunNormalDemuxer();
162     RunNormalDemuxerApi11();
163     // FUZZ CreateFD
164     int32_t fd = *reinterpret_cast<const int32_t *>(data);
165     int64_t offset = *reinterpret_cast<const int64_t *>(data);
166     int64_t fileSize = *reinterpret_cast<const int64_t *>(data);
167     OH_AVSource *source = OH_AVSource_CreateWithFD(fd, offset, fileSize);
168     if (source) {
169         OH_AVSource_Destroy(source);
170     }
171     return true;
172 }
173 } // namespace OHOS
174 
175 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)176 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
177 {
178     /* Run your code on data */
179     OHOS::DoSomethingInterestingWithMyAPI(data, size);
180     return 0;
181 }
182