Add policies and enforce overlayable to header
If the fulfilled policies change without the contents of the target
and overlay APKs changing, the idmap for the overlay should be
regenerated. This change adds fulfilled policies and enforce
overlayable to the idmap header so that idmap2d can determine if the
polices or enforce overlayable changed from what was used to generate
the idmap.
Bug: 119328308
Test: idmap2_tests
Test: atest RegenerateIdmapTest
Change-Id: I96f970e82b5243be01b205ac2cb6ab249c6100bc
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index db4778c..5fea7bc 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -48,6 +48,11 @@
ASSERT_TRUE(result2);
const auto idmap2 = std::move(*result2);
+ ASSERT_EQ(idmap1->GetHeader()->GetFulfilledPolicies(),
+ idmap2->GetHeader()->GetFulfilledPolicies());
+ ASSERT_EQ(idmap1->GetHeader()->GetEnforceOverlayable(),
+ idmap2->GetHeader()->GetEnforceOverlayable());
+ ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
ASSERT_EQ(idmap1->GetHeader()->GetTargetCrc(), idmap2->GetHeader()->GetTargetCrc());
ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
ASSERT_EQ(idmap1->GetData().size(), 1U);
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 87da36c..6fab5e0 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -62,9 +62,11 @@
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
- ASSERT_EQ(header->GetVersion(), 0x03U);
+ ASSERT_EQ(header->GetVersion(), 0x04U);
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
+ ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
+ ASSERT_EQ(header->GetEnforceOverlayable(), true);
ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk");
ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk");
ASSERT_EQ(header->GetDebugInfo(), "debug");
@@ -73,7 +75,7 @@
TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
// overwrite the target path string, including the terminating null, with '.'
- for (size_t i = 0x10; i < 0x110; i++) {
+ for (size_t i = 0x15; i < 0x115; i++) {
raw[i] = '.';
}
std::istringstream stream(raw);
@@ -82,7 +84,7 @@
}
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
- const size_t offset = 0x21c;
+ const size_t offset = 0x221;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -94,7 +96,7 @@
}
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
- const size_t offset = 0x21c;
+ const size_t offset = 0x221;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -128,9 +130,11 @@
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
+ ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11);
+ ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk");
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlayX.apk");
@@ -180,9 +184,11 @@
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
+ ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
+ ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
}
@@ -389,7 +395,8 @@
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
- ASSERT_TRUE(header->IsUpToDate());
+ ASSERT_TRUE(header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
// magic: bytes (0x0, 0x03)
std::string bad_magic_string(stream.str());
@@ -402,7 +409,8 @@
IdmapHeader::FromBinaryStream(bad_magic_stream);
ASSERT_THAT(bad_magic_header, NotNull());
ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
- ASSERT_FALSE(bad_magic_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
// version: bytes (0x4, 0x07)
std::string bad_version_string(stream.str());
@@ -415,7 +423,8 @@
IdmapHeader::FromBinaryStream(bad_version_stream);
ASSERT_THAT(bad_version_header, NotNull());
ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
- ASSERT_FALSE(bad_version_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
// target crc: bytes (0x8, 0xb)
std::string bad_target_crc_string(stream.str());
@@ -428,7 +437,8 @@
IdmapHeader::FromBinaryStream(bad_target_crc_stream);
ASSERT_THAT(bad_target_crc_header, NotNull());
ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
- ASSERT_FALSE(bad_target_crc_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
// overlay crc: bytes (0xc, 0xf)
std::string bad_overlay_crc_string(stream.str());
@@ -441,27 +451,55 @@
IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
ASSERT_THAT(bad_overlay_crc_header, NotNull());
ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
- ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
- // target path: bytes (0x10, 0x10f)
+ // fulfilled policy: bytes (0x10, 0x13)
+ std::string bad_policy_string(stream.str());
+ bad_policy_string[0x10] = '.';
+ bad_policy_string[0x11] = '.';
+ bad_policy_string[0x12] = '.';
+ bad_policy_string[0x13] = '.';
+ std::stringstream bad_policy_stream(bad_policy_string);
+ std::unique_ptr<const IdmapHeader> bad_policy_header =
+ IdmapHeader::FromBinaryStream(bad_policy_stream);
+ ASSERT_THAT(bad_policy_header, NotNull());
+ ASSERT_NE(header->GetFulfilledPolicies(), bad_policy_header->GetFulfilledPolicies());
+ ASSERT_FALSE(bad_policy_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
+
+ // enforce overlayable: bytes (0x14)
+ std::string bad_enforce_string(stream.str());
+ bad_enforce_string[0x14] = '\0';
+ std::stringstream bad_enforce_stream(bad_enforce_string);
+ std::unique_ptr<const IdmapHeader> bad_enforce_header =
+ IdmapHeader::FromBinaryStream(bad_enforce_stream);
+ ASSERT_THAT(bad_enforce_header, NotNull());
+ ASSERT_NE(header->GetEnforceOverlayable(), bad_enforce_header->GetEnforceOverlayable());
+ ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
+
+ // target path: bytes (0x15, 0x114)
std::string bad_target_path_string(stream.str());
- bad_target_path_string[0x10] = '\0';
+ bad_target_path_string[0x15] = '\0';
std::stringstream bad_target_path_stream(bad_target_path_string);
std::unique_ptr<const IdmapHeader> bad_target_path_header =
IdmapHeader::FromBinaryStream(bad_target_path_stream);
ASSERT_THAT(bad_target_path_header, NotNull());
ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
- ASSERT_FALSE(bad_target_path_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
- // overlay path: bytes (0x110, 0x20f)
+ // overlay path: bytes (0x115, 0x214)
std::string bad_overlay_path_string(stream.str());
- bad_overlay_path_string[0x110] = '\0';
+ bad_overlay_path_string[0x115] = '\0';
std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
ASSERT_THAT(bad_overlay_path_header, NotNull());
ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
- ASSERT_FALSE(bad_overlay_path_header->IsUpToDate());
+ ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
}
class TestVisitor : public Visitor {
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 5c5c81e..b268d5a 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -43,6 +43,8 @@
<< str << "--------"; \
} while (0)
+#define ADDRESS "[0-9a-f]{8}: "
+
TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
fclose(stderr); // silence expected warnings
@@ -62,15 +64,16 @@
RawPrintVisitor visitor(stream);
(*idmap)->accept(&visitor);
-#define ADDRESS "[0-9a-f]{8}: "
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000003 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
ASSERT_CONTAINS_REGEX(
StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
stream.str());
ASSERT_CONTAINS_REGEX(
StringPrintf(ADDRESS "%s overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING),
stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000001 fulfilled policies: public\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str());
@@ -83,7 +86,6 @@
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 value: integer/int1\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
-#undef ADDRESS
}
TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -99,22 +101,23 @@
RawPrintVisitor visitor(stream);
(*idmap)->accept(&visitor);
- ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000004: 00000003 version\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000008: 00001234 target crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000000c: 00005678 overlay crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021c: 7f target package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021d: 7f overlay package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021e: 00000003 target entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000222: 00000003 overlay entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000226: 00000000 string pool index offset\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000022a: 00000000 string pool byte length\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000022e: 7f020000 target id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000232: 01 type: reference\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000233: 7f020000 value\n"), std::string::npos);
-
- ASSERT_NE(stream.str().find("00000249: 7f020000 overlay id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000024d: 7f020000 target id\n"), std::string::npos);
+ ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool byte length\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 01 type: reference\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 value\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index e899589..b599dcb 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@
0x49, 0x44, 0x4d, 0x50,
// 0x4: version
- 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00,
// 0x8: target crc
0x34, 0x12, 0x00, 0x00,
@@ -38,7 +38,13 @@
// 0xc: overlay crc
0x78, 0x56, 0x00, 0x00,
- // 0x10: target path "targetX.apk"
+ // 0x10: fulfilled policies
+ 0x11, 0x00, 0x00, 0x00,
+
+ // 0x14: enforce overlayable
+ 0x01,
+
+ // 0x15: target path "targetX.apk"
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -56,7 +62,7 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // 0x110: overlay path "overlayX.apk"
+ // 0x115: overlay path "overlayX.apk"
0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -74,7 +80,7 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // 0x210: debug string
+ // 0x215: debug string
// string length, including terminating null
0x08, 0x00, 0x00, 0x00,
@@ -82,63 +88,63 @@
0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
// DATA HEADER
- // 0x21c: target_package_id
+ // 0x221: target_package_id
0x7f,
- // 0x21d: overlay_package_id
+ // 0x222: overlay_package_id
0x7f,
- // 0x21e: target_entry_count
+ // 0x223: target_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x222: overlay_entry_count
+ // 0x227: overlay_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x226: string_pool_offset
+ // 0x22b: string_pool_offset
0x00, 0x00, 0x00, 0x00,
- // 0x22a: string_pool_byte_length
+ // 0x22f: string_pool_byte_length
0x00, 0x00, 0x00, 0x00,
// TARGET ENTRIES
- // 0x22e: 0x7f020000
- 0x00, 0x00, 0x02, 0x7f,
-
- // 0x232: TYPE_REFERENCE
- 0x01,
-
// 0x233: 0x7f020000
0x00, 0x00, 0x02, 0x7f,
- // 0x237: 0x7f030000
- 0x00, 0x00, 0x03, 0x7f,
-
- // 0x23b: TYPE_REFERENCE
+ // 0x237: TYPE_REFERENCE
0x01,
+ // 0x238: 0x7f020000
+ 0x00, 0x00, 0x02, 0x7f,
+
// 0x23c: 0x7f030000
0x00, 0x00, 0x03, 0x7f,
- // 0x240: 0x7f030002
- 0x02, 0x00, 0x03, 0x7f,
-
- // 0x244: TYPE_REFERENCE
+ // 0x240: TYPE_REFERENCE
0x01,
- // 0x245: 0x7f030001
+ // 0x241: 0x7f030000
+ 0x00, 0x00, 0x03, 0x7f,
+
+ // 0x245: 0x7f030002
+ 0x02, 0x00, 0x03, 0x7f,
+
+ // 0x249: TYPE_REFERENCE
+ 0x01,
+
+ // 0x24a: 0x7f030001
0x01, 0x00, 0x03, 0x7f,
// OVERLAY ENTRIES
- // 0x249: 0x7f020000 -> 0x7f020000
+ // 0x24e: 0x7f020000 -> 0x7f020000
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
- // 0x251: 0x7f030000 -> 0x7f030000
+ // 0x256: 0x7f030000 -> 0x7f030000
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
- // 0x259: 0x7f030001 -> 0x7f030002
+ // 0x25e: 0x7f030001 -> 0x7f030002
0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
-const unsigned int idmap_raw_data_len = 0x261;
+const unsigned int idmap_raw_data_len = 0x266;
std::string GetTestDataPath();