fix: fixACISFormat 改为显式长度入参,修正 npos 与越界读

- 签名加 size_t nLen,内部用 std::string(pszReg, nLen) 构造,
  不再依赖调用方 buffer 的结尾 '\0';StringToRegion(nLen, char*)
  传入的 m_pSatBuffer 是 new byte[m_nSatLen],没有终止符,原写法会越界读
- 首行解析改用 substr(0, find('\n')),去掉 stringstream 对终止符的依赖
- pos == npos(数据里没有 '#')时返回 false,原写法 pos+1 溢出为 0,
  substr(0,0) 得到空串却仍返回 true,调用方会写出 0 字节文件且无提示
- countOfRecord <= 0 时提前返回 false
This commit is contained in:
company-desktop-computer committed 2026-10-21 14:15:11 +08:00
1 parent fabaca58df
commit 6e494aeb9e
1 file changed
+23 -15
+23 -15
View File
@@ -3069,35 +3069,43 @@ namespace
return std::string::npos;
}
// 整理sat文件格式,使其符合规范
bool fixACISFormat(const char *pszReg, std::string &sOut)
// 整理sat数据,只保留到第 countOfRecord 条 data record 的结尾。
// 数据尾部可能跟着非 SAT 内容(越界读的残留、旧实现追加的标记等),靠记录数反推真实结尾。
// nLen 必须显式传入:调用方的 buffer 不保证有结尾 '\0'(如 m_pSatBuffer)。
bool fixACISFormat(const char *pszReg, size_t nLen, std::string &sOut)
{
// 先取第一行,得到data record 的数量
std::string ss;
std::stringstream eam(pszReg);
std::getline(eam, ss);
if (ss.empty()) return false;
if (pszReg == NULL || nLen == 0) return false;
const std::string sSrc(pszReg, nLen);
// 先取第一行,得到data record 的数量
const std::string sFirstLine = sSrc.substr(0, sSrc.find('\n'));
if (sFirstLine.empty()) return false;
std::vector<CString> nums;
CoreTools::SplitString(CString(ss.c_str()), _T(" "), nums);
CoreTools::SplitString(CString(sFirstLine.c_str()), _T(" "), nums);
if (nums.size() < 2) return false;
int countOfRecord = _ttoi((LPCTSTR)nums[1]);
if (countOfRecord <= 0) return false;
ss = pszReg;
int sharpCount = std::count(ss.begin() ,ss.end(), '#');
int sharpCount = (int)std::count(sSrc.begin(), sSrc.end(), '#');
size_t pos(std::string::npos);
if (sharpCount > countOfRecord)
{
// 如果 sharpCount 大于 countOfRecord,从头部取到第sharpCount个‘#’位置
pos = find_nth_occurrence_reverse(ss, '#', (sharpCount - countOfRecord + 1));
pos = find_nth_occurrence_reverse(sSrc, '#', (size_t)(sharpCount - countOfRecord + 1));
}
else // <=
{
// 如果 sharpCount 小于等于 countOfRecord,直接从头部取到最后一个‘#’位置
pos = ss.rfind('#');
pos = sSrc.rfind('#');
}
sOut = ss.substr(0, pos + 1);
// 没有记录分隔符,说明数据不可用,不能返回空串让调用方误以为成功
if (pos == std::string::npos) return false;
sOut = sSrc.substr(0, pos + 1);
sOut += "\n\r";
return true;
}
@@ -3512,7 +3520,7 @@ AcDbRegion* CoreTools::StringToRegion(const CString & sRegionScrp)
{
std::string sUtf8 = CoreTools::unicode2Ansii((LPCTSTR)sRegionScrp, CP_UTF8);
std::string sNewSrc;
if (!fixACISFormat(sUtf8.c_str(), sNewSrc)) return NULL;
if (!fixACISFormat(sUtf8.c_str(), sUtf8.size(), sNewSrc)) return NULL;
CFile file;
CString sFullPath = MakeTempSatPath();
@@ -3561,7 +3569,7 @@ AcDbRegion* CoreTools::StringToRegion(const CString & sRegionScrp)
AcDbRegion *CoreTools::StringToRegion(Adesk::UInt64 nLen, char *pszReg)
{
std::string sNewSrc;
if (!fixACISFormat(pszReg, sNewSrc)) return NULL;
if (!fixACISFormat(pszReg, (size_t)nLen, sNewSrc)) return NULL;
AcDbRegion *pReg(NULL);
CString sFullPath = MakeTempSatPath();