!800 add stub fuzz testcases

Merge pull request !800 from wangpggg/master
This commit is contained in:
openharmony_ci 2024-03-26 06:29:06 +00:00 committed by Gitee
commit bd00ba2a2b
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 584 additions and 0 deletions

View File

@ -28,5 +28,6 @@ group("user_file_service_fuzz_test") {
"externalfileaccessopenfile_fuzzer:ExternalFileAccessOpenFileFuzzTest",
"externalfileaccessrename_fuzzer:ExternalFileAccessRenameFuzzTest",
"externalfileaccessscanfile_fuzzer:ExternalFileAccessScanFileFuzzTest",
"fileaccessextstub_fuzzer:FileAccessExtStubFuzzTest",
]
}

View File

@ -0,0 +1,58 @@
# Copyright (c) 2024 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.
#####################hydra-fuzz###################
import("//build/config/features.gni")
import("//build/test.gni")
import("//foundation/filemanagement/user_file_service/filemanagement_aafwk.gni")
ohos_fuzztest("FileAccessExtStubFuzzTest") {
module_out_path = "user_file_service/user_file_service"
fuzz_config_file =
"${user_file_service_path}/test/fuzztest/fileaccessextstub_fuzzer"
include_dirs = [
"${ability_runtime_napi_path}/inner/napi_common",
"${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime",
"${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime",
"${user_file_service_path}/interfaces/inner_api/file_access/include",
"${user_file_service_path}/interfaces/kits/js/src/common",
"${user_file_service_path}/utils",
]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"${user_file_service_path}/interfaces/inner_api/file_access/src/file_access_ext_stub.cpp",
"${user_file_service_path}/interfaces/inner_api/file_access/src/file_access_ext_stub_impl.cpp",
"${user_file_service_path}/test/fuzztest/fileaccessextstub_fuzzer/fileaccessextstub_fuzzer.cpp",
]
external_deps = [
"ability_base:want",
"ability_base:zuri",
"ability_runtime:app_context",
"ability_runtime:extensionkit_native",
"ability_runtime:napi_common",
"ability_runtime:runtime",
"access_token:libaccesstoken_sdk",
"c_utils:utils",
"hilog:libhilog",
"hitrace:hitrace_meter",
"ipc:ipc_core",
"napi:ace_napi",
]
defines = [ "private=public" ]
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2024 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.
*/
FUZZ

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2024 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.
*/
#ifndef FILE_ACCESS_EXT_ABILITY_MOCK_H
#define FILE_ACCESS_EXT_ABILITY_MOCK_H
#include "file_access_ext_ability.h"
namespace OHOS {
namespace FileAccessFwk {
using namespace AbilityRuntime;
class FileAccessExtAbilityMock : public FileAccessExtAbility {
public:
void Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord> &record,
const std::shared_ptr<AppExecFwk::OHOSApplication> &application,
std::shared_ptr<AppExecFwk::AbilityHandler> &handler,
const sptr<IRemoteObject> &token) override {};
void OnStart(const AAFwk::Want &want) override {};
sptr<IRemoteObject> OnConnect(const AAFwk::Want &want) override { return 0; };
int OpenFile(const Uri &uri, const int flags, int &fd) override { return 0; };
int CreateFile(const Uri &parent, const std::string &displayName, Uri &newFile) override { return 0; };
int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) override { return 0; };
int Delete(const Uri &sourceFile) override { return 0; };
int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) override { return 0; };
int Copy(const Uri &sourceUri, const Uri &destUri, std::vector<Result> &copyResult, bool force = false) override
{ return 0; };
int CopyFile(const Uri &sourceUri, const Uri &destUri, const std::string &fileName,
Uri &newFileUri) override { return 0; };
int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) override { return 0; };
int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter,
std::vector<FileInfo> &fileInfoVec) override { return 0; };
int ScanFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter,
std::vector<FileInfo> &fileInfoVec) override { return 0; };
int GetFileInfoFromUri(const Uri &selectFile, FileInfo &fileInfo) override { return 0; };
int GetFileInfoFromRelativePath(const std::string &selectFile, FileInfo &fileInfo) override { return 0; };
int GetRoots(std::vector<RootInfo> &rootInfoVec) override { return 0; };
int Access(const Uri &uri, bool &isExist) override { return 0; };
int Query(const Uri &uri, std::vector<std::string> &columns, std::vector<std::string> &results) override
{ return 0; };
int StartWatcher(const Uri &uri) override { return 0; };
int StopWatcher(const Uri &uri) override { return 0; };
int MoveItem(const Uri &sourceFile, const Uri &targetParent, std::vector<Result> &moveResult,
bool force = false) override { return 0; };
int MoveFile(const Uri &sourceFile, const Uri &targetParent, std::string &fileName, Uri &newFile) override
{ return 0; };
int GetFileInfoNum(const std::string &sourceFileUri, const FileFilter &filter, bool recursion,
uint32_t &counts) override { return 0; };
};
} // namespace FileAccessFwk
} // namespace OHOS
#endif // FILE_ACCESS_EXT_ABILITY_MOCK_H

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) 2024 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 "fileaccessextstub_fuzzer.h"
#include <cstring>
#include <memory>
#include "accesstoken_kit.h"
#include "extension_base.h"
#include "extension_context.h"
#include "file_access_ext_stub.h"
#include "file_access_ext_stub_impl.h"
#include "fileaccessextabilitymock.h"
#include "message_parcel.h"
namespace OHOS {
using namespace std;
using namespace FileAccessFwk;
using namespace AbilityRuntime;
template<class T>
T TypeCast(const uint8_t *data, int *pos = nullptr)
{
if (pos) {
*pos += sizeof(T);
}
return *(reinterpret_cast<const T*>(data));
}
bool OnRemoteRequestFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
if (data == nullptr || size < sizeof(uint32_t)) {
return true;
}
uint32_t code = reinterpret_cast<uint32_t>(data);
MessageParcel msg;
msg.WriteInterfaceToken(FileAccessExtStub::GetDescriptor());
MessageParcel reply;
MessageOption option;
fileAccessExtStub->OnRemoteRequest(code, msg, reply, option);
return true;
}
bool CmdOpenFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
if (data == nullptr || size < sizeof(int32_t)) {
return true;
}
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size - sizeof(int32_t)));
msg.WriteInt32(TypeCast<int32_t>(data));
fileAccessExtStub->CmdOpenFile(msg, reply);
return true;
}
bool CmdCreateFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), size - pos));
fileAccessExtStub->CmdCreateFile(msg, reply);
return true;
}
bool CmdMkdirFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), size - pos));
fileAccessExtStub->CmdMkdir(msg, reply);
return true;
}
bool CmdDeleteFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdDelete(msg, reply);
return true;
}
bool CmdMoveFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), size - pos));
fileAccessExtStub->CmdMove(msg, reply);
return true;
}
bool CmdCopyFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
if (data == nullptr || size == 0) {
return true;
}
MessageParcel msg;
MessageParcel reply;
int pos = (size - 1) >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data + 1), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos + 1), size - pos - 1));
msg.WriteBool(TypeCast<bool>(data));
fileAccessExtStub->CmdCopy(msg, reply);
return true;
}
bool CmdCopyFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size / 3;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos + pos), size - pos - pos));
fileAccessExtStub->CmdCopyFile(msg, reply);
return true;
}
bool CmdRenameFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), size - pos));
fileAccessExtStub->CmdRename(msg, reply);
return true;
}
bool CmdListFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
size_t minSize = sizeof(int64_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t) + sizeof(int64_t)
+ sizeof(double) + sizeof(bool) + sizeof(bool);
if (data == nullptr || size < minSize) {
return true;
}
int pos = 0;
int64_t offset = TypeCast<int64_t>(data, &pos);
FileInfo fileInfo;
fileInfo.mode = TypeCast<int32_t>(data + pos, &pos);
fileInfo.size = TypeCast<int64_t>(data + pos, &pos);
fileInfo.mtime = TypeCast<int64_t>(data + pos, &pos);
int64_t fileSizeOver = TypeCast<int64_t>(data + pos, &pos);
double lastModifiedAfter = TypeCast<double>(data + pos, &pos);
bool excludeMedia = TypeCast<bool>(data + pos, &pos);
bool hasFilter = TypeCast<bool>(data + pos, &pos);
int len = (size - pos) / 6;
fileInfo.uri = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
fileInfo.relativePath = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
fileInfo.fileName = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
std::vector<std::string> suffix;
suffix.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
std::vector<std::string> displayName;
displayName.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
std::vector<std::string> mimeType;
mimeType.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
FileFilter fileFilter(suffix, displayName, mimeType, fileSizeOver, lastModifiedAfter, excludeMedia, hasFilter);
SharedMemoryInfo sharedMemoryInfo;
MessageParcel msg;
MessageParcel reply;
msg.WriteParcelable(&fileInfo);
msg.WriteInt64(offset);
msg.WriteParcelable(&fileFilter);
msg.WriteParcelable(&sharedMemoryInfo);
fileAccessExtStub->CmdListFile(msg, reply);
return true;
}
bool CmdScanFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
size_t minSize = sizeof(int64_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t)
+ sizeof(int64_t) + sizeof(double) + sizeof(bool) + sizeof(bool);
if (data == nullptr || size < minSize) {
return true;
}
int pos = 0;
int64_t offset = TypeCast<int64_t>(data, &pos);
int64_t maxCount = TypeCast<int64_t>(data, &pos);
FileInfo fileInfo;
fileInfo.mode = TypeCast<int32_t>(data + pos, &pos);
fileInfo.size = TypeCast<int64_t>(data + pos, &pos);
fileInfo.mtime = TypeCast<int64_t>(data + pos, &pos);
int64_t fileSizeOver = TypeCast<int64_t>(data + pos, &pos);
double lastModifiedAfter = TypeCast<double>(data + pos, &pos);
bool excludeMedia = TypeCast<bool>(data + pos, &pos);
bool hasFilter = TypeCast<bool>(data + pos, &pos);
int len = (size - pos) / 6;
fileInfo.uri = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
fileInfo.relativePath = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
fileInfo.fileName = string(reinterpret_cast<const char*>(data + pos), len);
pos += len;
std::vector<std::string> suffix;
suffix.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
std::vector<std::string> displayName;
displayName.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
std::vector<std::string> mimeType;
mimeType.push_back(string(reinterpret_cast<const char*>(data + pos), len));
pos += len;
FileFilter fileFilter(suffix, displayName, mimeType, fileSizeOver, lastModifiedAfter, excludeMedia, hasFilter);
SharedMemoryInfo sharedMemoryInfo;
MessageParcel msg;
MessageParcel reply;
msg.WriteParcelable(&fileInfo);
msg.WriteInt64(offset);
msg.WriteInt64(maxCount);
msg.WriteParcelable(&fileFilter);
fileAccessExtStub->CmdScanFile(msg, reply);
return true;
}
bool CmdGetRootsFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
fileAccessExtStub->CmdGetRoots(msg, reply);
return true;
}
bool CmdQueryFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
if (data == nullptr || size < sizeof(int64_t)) {
return true;
}
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data + sizeof(int64_t)), size - sizeof(int64_t)));
msg.WriteInt64(TypeCast<int64_t>(data));
fileAccessExtStub->CmdQuery(msg, reply);
return true;
}
bool CmdGetFileInfoFromUriFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdGetFileInfoFromUri(msg, reply);
return true;
}
bool CmdGetFileInfoFromRelativePathFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data,
size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdGetFileInfoFromRelativePath(msg, reply);
return true;
}
bool CmdAccessFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdAccess(msg, reply);
return true;
}
bool CmdStartWatcherFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdStartWatcher(msg, reply);
return true;
}
bool CmdStopWatcherFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
msg.WriteString(string(reinterpret_cast<const char*>(data), size));
fileAccessExtStub->CmdStopWatcher(msg, reply);
return true;
}
bool CmdMoveItemFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
if (data == nullptr || size == 0) {
return true;
}
MessageParcel msg;
MessageParcel reply;
int pos = (size - 1) >> 1;
msg.WriteString(string(reinterpret_cast<const char*>(data + 1), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos + 1), size - pos - 1));
msg.WriteBool(TypeCast<bool>(data));
fileAccessExtStub->CmdMoveItem(msg, reply);
return true;
}
bool CmdMoveFileFuzzTest(shared_ptr<FileAccessExtStub> fileAccessExtStub, const uint8_t *data, size_t size)
{
MessageParcel msg;
MessageParcel reply;
int pos = size / 3;
msg.WriteString(string(reinterpret_cast<const char*>(data), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos), pos));
msg.WriteString(string(reinterpret_cast<const char*>(data + pos + pos), size - pos - pos));
fileAccessExtStub->CmdMoveFile(msg, reply);
return true;
}
} // namespace OHOS
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
auto ability = std::make_shared<OHOS::FileAccessFwk::FileAccessExtAbilityMock>();
auto stub = std::make_shared<OHOS::FileAccessFwk::FileAccessExtStubImpl>(ability, nullptr);
if (stub == nullptr) {
return 0;
}
OHOS::OnRemoteRequestFuzzTest(stub, data, size);
OHOS::CmdOpenFileFuzzTest(stub, data, size);
OHOS::CmdCreateFileFuzzTest(stub, data, size);
OHOS::CmdMkdirFuzzTest(stub, data, size);
OHOS::CmdDeleteFuzzTest(stub, data, size);
OHOS::CmdMoveFuzzTest(stub, data, size);
OHOS::CmdCopyFuzzTest(stub, data, size);
OHOS::CmdCopyFileFuzzTest(stub, data, size);
OHOS::CmdRenameFuzzTest(stub, data, size);
OHOS::CmdListFileFuzzTest(stub, data, size);
OHOS::CmdScanFileFuzzTest(stub, data, size);
OHOS::CmdGetRootsFuzzTest(stub, data, size);
OHOS::CmdQueryFuzzTest(stub, data, size);
OHOS::CmdGetFileInfoFromUriFuzzTest(stub, data, size);
OHOS::CmdGetFileInfoFromRelativePathFuzzTest(stub, data, size);
OHOS::CmdAccessFuzzTest(stub, data, size);
OHOS::CmdStartWatcherFuzzTest(stub, data, size);
OHOS::CmdStopWatcherFuzzTest(stub, data, size);
OHOS::CmdMoveItemFuzzTest(stub, data, size);
OHOS::CmdMoveFileFuzzTest(stub, data, size);
return 0;
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2024 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.
*/
#ifndef FILE_ACCESS_EXT_STUB_FUZZER_H
#define FILE_ACCESS_EXT_STUB_FUZZER_H
#define FUZZ_PROJECT_NAME "fileaccessextstub_fuzzer"
#endif

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2024 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>