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