* Copyright (c) 2025 Huawei Device Co., Ltd.
* 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.
*/
#include "predownload_fuzzer.h"
#include <securec.h>
#include <cstddef>
#include <cstdint>
#include <vector>
#include "accesstoken_kit.h"
#include "nativetoken_kit.h"
#include "preload_callback.h"
#include "request_preload.h"
#include "token_setproc.h"
using namespace OHOS::Request;
using namespace OHOS::Security::AccessToken;
namespace OHOS {
constexpr int64_t PRELOAD_UTF8_SIZE_LIMIT = 8192;
constexpr size_t TIMEOUT_PARAM_COUNT = 2;
uint16_t ConvertToUint16(const uint8_t *ptr, size_t size)
{
if (ptr == nullptr || size < sizeof(uint16_t)) {
return 0;
}
uint16_t value;
if (memcpy_s(&value, sizeof(value), ptr, sizeof(uint16_t)) != 0) {
return 0;
}
return value;
}
void ConvertToUTF8(std::string &url)
{
for (size_t i = 0; i < url.size(); i++) {
if (url[i] > 0x7F) {
url[i] = '?';
}
}
}
void GrantNativePermission()
{
const char **perms = new const char *[1];
perms[0] = "ohos.permission.GET_NETWORK_INFO";
TokenInfoParams infoInstance = {
.dcapsNum = 0,
.permsNum = 1,
.aclsNum = 0,
.dcaps = nullptr,
.perms = perms,
.acls = nullptr,
.processName = "preload_info",
.aplStr = "system_core",
};
uint64_t tokenId = GetAccessTokenId(&infoInstance);
SetSelfTokenID(tokenId);
AccessTokenKit::ReloadNativeTokenInfo();
delete[] perms;
}
void GetDownloadInfoFuzzTest(const uint8_t *data, size_t size)
{
if (size <= 0 || data == nullptr) {
return;
}
if (size > PRELOAD_UTF8_SIZE_LIMIT) {
return;
}
std::string url(reinterpret_cast<const char *>(data), size);
ConvertToUTF8(url);
GrantNativePermission();
Preload::GetInstance()->GetDownloadInfo(url);
}
void SetDownloadInfoListSizeFuzzTest(const uint8_t *data, size_t size)
{
uint16_t len = ConvertToUint16(data, size);
GrantNativePermission();
Preload::GetInstance()->SetDownloadInfoListSize(len);
}
void SetGlobalRetryOptionsFuzzTest(const uint8_t *data, size_t size)
{
if (size < sizeof(int32_t)) {
return;
}
int32_t maxRetryCount;
if (memcpy_s(&maxRetryCount, sizeof(maxRetryCount), data, sizeof(int32_t)) != 0) {
return;
}
GrantNativePermission();
RetryOptions retryOptions;
retryOptions.maxRetryCount = maxRetryCount;
Preload::GetInstance()->SetGlobalRetryOptions(retryOptions);
}
void SetGlobalTimeoutOptionsFuzzTest(const uint8_t *data, size_t size)
{
if (size < sizeof(int32_t) * TIMEOUT_PARAM_COUNT) {
return;
}
int32_t networkCheckTimeout;
int32_t httpTotalTimeout;
if (memcpy_s(&networkCheckTimeout, sizeof(networkCheckTimeout), data, sizeof(int32_t)) != 0) {
return;
}
if (memcpy_s(&httpTotalTimeout, sizeof(httpTotalTimeout), data + sizeof(int32_t), sizeof(int32_t)) != 0) {
return;
}
GrantNativePermission();
TimeoutOptions timeoutOptions;
timeoutOptions.networkCheckTimeout = networkCheckTimeout;
timeoutOptions.httpTotalTimeout = httpTotalTimeout;
Preload::GetInstance()->SetGlobalTimeoutOptions(timeoutOptions);
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
OHOS::GetDownloadInfoFuzzTest(data, size);
OHOS::SetDownloadInfoListSizeFuzzTest(data, size);
OHOS::SetGlobalRetryOptionsFuzzTest(data, size);
OHOS::SetGlobalTimeoutOptionsFuzzTest(data, size);
return 0;
}