• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "ecmascript/base/dtoa_helper.h"
16 #include "ecmascript/base/string_helper.h"
17 #include "ecmascript/compiler/aot_file/aot_checksum_helper.h"
18 #include "ecmascript/log.h"
19 #include "ecmascript/log_wrapper.h"
20 #include "macros.h"
21 
22 namespace panda::ecmascript {
23 
SerializeChecksumMapToVector(const std::unordered_map<CString,uint32_t> & fileNameToChecksumMap,std::vector<char> & checksumDataVector)24 bool AOTChecksumHelper::SerializeChecksumMapToVector(const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap,
25                                                      std::vector<char> &checksumDataVector)
26 {
27     // save fileName to checksum relationship as like
28     // pandafileNormalizeDes:checksum
29     // /xxx/yyy/zzz.abc:123456
30     if (fileNameToChecksumMap.empty()) {
31         LOG_COMPILER(ERROR) << "abc file checksum map cant't be empty!";
32         return false;
33     }
34     uint32_t checksumVectorSize = CalculateChecksumVectorSize(fileNameToChecksumMap);
35     checksumDataVector.resize(checksumVectorSize);
36     if (!WriteChecksumInfoToVector(fileNameToChecksumMap, checksumDataVector)) {
37         checksumDataVector.resize(0);
38         LOG_COMPILER(ERROR) << "Serialize checksumMap to .an failed!";
39         return false;
40     }
41     return true;
42 }
43 
CalculateChecksumVectorSize(const std::unordered_map<CString,uint32_t> & fileNameToChecksumMap)44 uint32_t AOTChecksumHelper::CalculateChecksumVectorSize(
45     const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap)
46 {
47     uint32_t size = 0;
48     for (const auto &pair : fileNameToChecksumMap) {
49         // 2 for ':' and '\0'
50         size += pair.first.size() + FastUint32ToDigits(pair.second) + 2;
51     }
52     return size;
53 }
54 
FastUint32ToDigits(uint32_t number)55 uint32_t AOTChecksumHelper::FastUint32ToDigits(uint32_t number)
56 {
57     return (number >= base::DtoaHelper::TEN9POW)   ? 10  // 10 digits
58            : (number >= base::DtoaHelper::TEN8POW) ? 9   // 9 digits
59            : (number >= base::DtoaHelper::TEN7POW) ? 8   // 8 digits
60            : (number >= base::DtoaHelper::TEN6POW) ? 7   // 7 digits
61            : (number >= base::DtoaHelper::TEN5POW) ? 6   // 6 digits
62            : (number >= base::DtoaHelper::TEN4POW) ? 5   // 5 digits
63            : (number >= base::DtoaHelper::TEN3POW) ? 4   // 4 digits
64            : (number >= base::DtoaHelper::TEN2POW) ? 3   // 3 digits
65            : (number >= base::DtoaHelper::TEN)     ? 2   // 2 digits
66                                                    : 1;      // 1 digit
67 }
68 
WriteChecksumInfoToVector(const std::unordered_map<CString,uint32_t> & fileNameToChecksumMap,std::vector<char> & checksumDataVector)69 bool AOTChecksumHelper::WriteChecksumInfoToVector(const std::unordered_map<CString, uint32_t> &fileNameToChecksumMap,
70                                                   std::vector<char> &checksumDataVector)
71 {
72     char *basePtr = checksumDataVector.data();
73     char *endPtr = basePtr + checksumDataVector.size();
74     char *writePtr = basePtr;
75     for (const auto &pair : fileNameToChecksumMap) {
76         size_t remainSize = endPtr - writePtr;
77         int written = snprintf_s(writePtr, remainSize, remainSize - 1, "%s:%u", pair.first.c_str(), pair.second);
78         if (written < 0 || static_cast<size_t>(written) >= remainSize) {
79             LOG_COMPILER(ERROR) << "wirte checksum info to AOT .an file failed!";
80             return false;
81         }
82         // 1 for '\0'
83         writePtr += written + 1;
84     }
85     if (writePtr != endPtr) {
86         LOG_COMPILER(ERROR) << "Checksum vector not fully filled: "
87                             << "expected size=" << checksumDataVector.size()
88                             << ", actual used=" << (writePtr - basePtr);
89         return false;
90     }
91     return true;
92 }
93 
DeserializeChecksumMapFromChar(const char * checksumData,uint32_t checksumDataSize,std::unordered_map<CString,uint32_t> & fileNameToChecksumMap)94 bool AOTChecksumHelper::DeserializeChecksumMapFromChar(const char *checksumData, uint32_t checksumDataSize,
95                                                        std::unordered_map<CString, uint32_t> &fileNameToChecksumMap)
96 {
97     if (checksumData == nullptr || checksumDataSize == 0) {
98         LOG_COMPILER(ERROR) << "Invalid checksum data";
99         return false;
100     }
101 
102     const char *curPtr = checksumData;
103     const char *endPtr = checksumData + checksumDataSize;
104 
105     while (curPtr < endPtr) {
106         const char *entryEnd = static_cast<const char *>(memchr(curPtr, '\0', endPtr - curPtr));
107         if (entryEnd == nullptr || entryEnd >= endPtr) {
108             LOG_COMPILER(ERROR) << "Corrupted checksum data: missing string terminator";
109             return false;
110         }
111 
112         const char *separator = static_cast<const char *>(memchr(curPtr, ':', entryEnd - curPtr));
113         if (separator == nullptr || separator >= entryEnd) {
114             LOG_COMPILER(ERROR) << "Corrupted checksum data: missing separator";
115             return false;
116         }
117 
118         if (separator == curPtr || separator + 1 == entryEnd) {
119             LOG_COMPILER(ERROR) << "Invalid entry format: empty filename or checksum";
120             return false;
121         }
122 
123         CString filename(curPtr, separator - curPtr);
124 
125         uint32_t checksum;
126         if (!base::StringHelper::StrToUInt32(separator + 1, &checksum)) {
127             LOG_COMPILER(ERROR) << "Invalid checksum value";
128             return false;
129         }
130 
131         fileNameToChecksumMap.emplace(std::move(filename), checksum);
132 
133         curPtr = entryEnd + 1;
134     }
135 
136     if (fileNameToChecksumMap.empty()) {
137         LOG_COMPILER(ERROR) << "No valid entries found in checksum data";
138         return false;
139     }
140     return true;
141 }
142 
143 }  // namespace panda::ecmascript
144