fix: 临时 SAT 文件名唯一化并修正越界读

- RegionToString/StringToRegion/BodyToString/StringToFace 的临时文件名
  由固定的 Region1/Region2/Region121/Region212/Region312.sat
  改为 x3d_<PID>_<序号>.sat,多 CAD 实例或多线程并发时不再互相覆盖
- 读取缓冲区补 +1 零字节,修复 new char[len] 无结尾 0 导致的越界读
- 检查 file.Read 短读,失败时释放缓冲并返回空
- 用完即 DeleteFile,不残留临时文件
This commit is contained in:
company-desktop-computer committed 2026-10-21 09:06:36 +08:00
1 parent 90f6c115bf
commit 1c8068c8cf
1 file changed
+88 -38
+88 -38
View File
@@ -3034,16 +3034,31 @@ AcDbRegion* CoreTools::createRegion(AcDbEntity *pEnt)
return (AcDbRegion*)segs[0]; return (AcDbRegion*)segs[0];
} }
// 生成唯一的临时 SAT 文件路径。
// 用 PID + 进程内原子序号,避免多个 CAD 实例或多线程互相覆盖同名文件。
// 调用方负责在 acisOut/acisIn 结束后 DeleteFile。
static CString MakeTempSatPath()
{
static LONG s_nSeq = 0;
LONG nSeq = ::InterlockedIncrement(&s_nSeq);
CString sPath = FilePath::getSystemTemporaryFolder();
if (sPath.IsEmpty())
sPath = _T(".");
CString sName;
sName.Format(_T("\\x3d_%lu_%ld.sat"), (unsigned long)::GetCurrentProcessId(), nSeq);
return sPath + sName;
}
Adesk::UInt64 CoreTools::RegionToString(const AcDbRegion *pReg, char *& pszTxt) Adesk::UInt64 CoreTools::RegionToString(const AcDbRegion *pReg, char *& pszTxt)
{ {
Adesk::UInt64 dwFileLength = 0; Adesk::UInt64 dwFileLength = 0;
pszTxt = NULL; pszTxt = NULL;
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return 0;
sFullPath += _T("\\Region121.sat");
CString sLine;
AcDbVoidPtrArray arBodyPtrs; AcDbVoidPtrArray arBodyPtrs;
arBodyPtrs.append((void *)pReg); arBodyPtrs.append((void *)pReg);
@@ -3054,12 +3069,24 @@ Adesk::UInt64 CoreTools::RegionToString(const AcDbRegion *pReg, char *& pszTxt)
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeRead)) if (file.Open(sFullPath, CFile::modeRead))
{ {
dwFileLength = file.GetLength(); ULONGLONG nFileLength = file.GetLength();
pszTxt = new char[dwFileLength]; if (nFileLength > 0 && nFileLength < (ULONGLONG)UINT_MAX)
::memset(pszTxt, 0, sizeof(char) * dwFileLength); {
pszTxt = new char[(size_t)nFileLength + 1];
file.Read(pszTxt, (UINT)dwFileLength); ::memset(pszTxt, 0, (size_t)nFileLength + 1);
UINT nRead = file.Read(pszTxt, (UINT)nFileLength);
if (nRead == (UINT)nFileLength)
{
dwFileLength = nFileLength;
}
else
{
acutPrintf(_T("\nCoreTools::RegionToString short read %u/%I64u."), nRead, nFileLength);
delete[] pszTxt;
pszTxt = NULL;
}
}
file.Close(); file.Close();
} }
else else
@@ -3071,16 +3098,16 @@ Adesk::UInt64 CoreTools::RegionToString(const AcDbRegion *pReg, char *& pszTxt)
{ {
acutPrintf(_T("\nCoreTools::RegionToString::acisOut failure. ERRNO %d."), es); acutPrintf(_T("\nCoreTools::RegionToString::acisOut failure. ERRNO %d."), es);
} }
::DeleteFile(sFullPath);
return dwFileLength; return dwFileLength;
} }
bool CoreTools::RegionToString(const AcDbRegion * pReg, CString & sRegionScrp) bool CoreTools::RegionToString(const AcDbRegion * pReg, CString & sRegionScrp)
{ {
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return false;
sFullPath += _T("\\Region1.sat");
CString sLine;
AcDbVoidPtrArray arBodyPtrs; AcDbVoidPtrArray arBodyPtrs;
arBodyPtrs.append((void*)pReg); arBodyPtrs.append((void*)pReg);
@@ -3091,15 +3118,20 @@ bool CoreTools::RegionToString(const AcDbRegion * pReg, CString & sRegionScrp)
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeRead)) if (file.Open(sFullPath, CFile::modeRead))
{ {
ULONGLONG dwFileLength = file.GetLength(); ULONGLONG nFileLength = file.GetLength();
char* pszTxt = new char[dwFileLength]; if (nFileLength > 0 && nFileLength < (ULONGLONG)UINT_MAX)
::memset(pszTxt, 0, sizeof(char) * dwFileLength); {
char* pszTxt = new char[(size_t)nFileLength + 1];
::memset(pszTxt, 0, (size_t)nFileLength + 1);
file.Read(pszTxt, (UINT)dwFileLength); UINT nRead = file.Read(pszTxt, (UINT)nFileLength);
if (nRead == (UINT)nFileLength)
sRegionScrp = pszTxt; sRegionScrp = pszTxt;
delete[] pszTxt; else
acutPrintf(_T("\nCoreTools::RegionToString short read %u/%I64u."), nRead, nFileLength);
delete[] pszTxt;
}
file.Close(); file.Close();
} }
else else
@@ -3111,6 +3143,8 @@ bool CoreTools::RegionToString(const AcDbRegion * pReg, CString & sRegionScrp)
{ {
acutPrintf(_T("\nCoreTools::RegionToString::acisOut failure. ERRNO %d."), es); acutPrintf(_T("\nCoreTools::RegionToString::acisOut failure. ERRNO %d."), es);
} }
::DeleteFile(sFullPath);
return sRegionScrp.IsEmpty() ? false : true; return sRegionScrp.IsEmpty() ? false : true;
} }
@@ -3481,9 +3515,9 @@ AcDbRegion* CoreTools::StringToRegion(const CString & sRegionScrp)
if (!fixACISFormat(sUtf8.c_str(), sNewSrc)) return NULL; if (!fixACISFormat(sUtf8.c_str(), sNewSrc)) return NULL;
CFile file; CFile file;
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return NULL;
sFullPath += _T("\\Region2.sat");
if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
{ {
file.Write(sNewSrc.c_str(), sizeof(char) * (UINT)sNewSrc.size()); file.Write(sNewSrc.c_str(), sizeof(char) * (UINT)sNewSrc.size());
@@ -3492,6 +3526,7 @@ AcDbRegion* CoreTools::StringToRegion(const CString & sRegionScrp)
else else
{ {
acutPrintf(_T("\nCoreTools::StringToRegion write file failure.")); acutPrintf(_T("\nCoreTools::StringToRegion write file failure."));
::DeleteFile(sFullPath);
return NULL; return NULL;
} }
@@ -3519,6 +3554,7 @@ AcDbRegion* CoreTools::StringToRegion(const CString & sRegionScrp)
for (int i = 0; i < arBodyPtrs.length(); ++i) for (int i = 0; i < arBodyPtrs.length(); ++i)
DELETE_PTR(arBodyPtrs[i]); DELETE_PTR(arBodyPtrs[i]);
::DeleteFile(sFullPath);
return pReg; return pReg;
} }
@@ -3528,9 +3564,8 @@ AcDbRegion *CoreTools::StringToRegion(Adesk::UInt64 nLen, char *pszReg)
if (!fixACISFormat(pszReg, sNewSrc)) return NULL; if (!fixACISFormat(pszReg, sNewSrc)) return NULL;
AcDbRegion *pReg(NULL); AcDbRegion *pReg(NULL);
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return NULL;
sFullPath += _T("\\Region212.sat");
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
@@ -3541,6 +3576,7 @@ AcDbRegion *CoreTools::StringToRegion(Adesk::UInt64 nLen, char *pszReg)
else else
{ {
acutPrintf(_T("\nCoreTools::StringToRegion write file failure.")); acutPrintf(_T("\nCoreTools::StringToRegion write file failure."));
::DeleteFile(sFullPath);
return NULL; return NULL;
} }
@@ -3567,6 +3603,7 @@ AcDbRegion *CoreTools::StringToRegion(Adesk::UInt64 nLen, char *pszReg)
for (int i = 0; i < arBodyPtrs.length(); ++i) for (int i = 0; i < arBodyPtrs.length(); ++i)
DELETE_PTR(arBodyPtrs[i]); DELETE_PTR(arBodyPtrs[i]);
::DeleteFile(sFullPath);
return pReg; return pReg;
} }
@@ -3575,11 +3612,9 @@ Adesk::UInt64 CoreTools::BodyToString(const AcDbBody *pBody, char *&pszOut)
Adesk::UInt64 dwFileLength = 0; Adesk::UInt64 dwFileLength = 0;
pszOut = NULL; pszOut = NULL;
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return 0;
sFullPath += _T("\\Region121.sat");
CString sLine;
AcDbVoidPtrArray arBodyPtrs; AcDbVoidPtrArray arBodyPtrs;
arBodyPtrs.append((void *)pBody); arBodyPtrs.append((void *)pBody);
@@ -3590,12 +3625,24 @@ Adesk::UInt64 CoreTools::BodyToString(const AcDbBody *pBody, char *&pszOut)
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeRead)) if (file.Open(sFullPath, CFile::modeRead))
{ {
dwFileLength = file.GetLength(); ULONGLONG nFileLength = file.GetLength();
pszOut = new char[dwFileLength]; if (nFileLength > 0 && nFileLength < (ULONGLONG)UINT_MAX)
::memset(pszOut, 0, sizeof(char) * dwFileLength); {
pszOut = new char[(size_t)nFileLength + 1];
file.Read(pszOut, (UINT)dwFileLength); ::memset(pszOut, 0, (size_t)nFileLength + 1);
UINT nRead = file.Read(pszOut, (UINT)nFileLength);
if (nRead == (UINT)nFileLength)
{
dwFileLength = nFileLength;
}
else
{
acutPrintf(_T("\nCoreTools::BodyToString short read %u/%I64u."), nRead, nFileLength);
delete[] pszOut;
pszOut = NULL;
}
}
file.Close(); file.Close();
} }
else else
@@ -3607,15 +3654,16 @@ Adesk::UInt64 CoreTools::BodyToString(const AcDbBody *pBody, char *&pszOut)
{ {
acutPrintf(_T("\nCoreTools::BodyToString::acisOut failure. ERRNO %d."), es); acutPrintf(_T("\nCoreTools::BodyToString::acisOut failure. ERRNO %d."), es);
} }
::DeleteFile(sFullPath);
return dwFileLength; return dwFileLength;
} }
AcDbSurface *CoreTools::StringToFace(Adesk::UInt64 nLen, char *pszBody) AcDbSurface *CoreTools::StringToFace(Adesk::UInt64 nLen, char *pszBody)
{ {
AcDbSurface *pFace(NULL); AcDbSurface *pFace(NULL);
CString sFullPath = FilePath::getSystemTemporaryFolder(); CString sFullPath = MakeTempSatPath();
sFullPath.MakeLower(); if (sFullPath.IsEmpty()) return NULL;
sFullPath += _T("\\Region312.sat");
CFile file; CFile file;
if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite)) if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
@@ -3626,6 +3674,7 @@ AcDbSurface *CoreTools::StringToFace(Adesk::UInt64 nLen, char *pszBody)
else else
{ {
acutPrintf(_T("\nCoreTools::StringToBody write file failure.")); acutPrintf(_T("\nCoreTools::StringToBody write file failure."));
::DeleteFile(sFullPath);
return NULL; return NULL;
} }
@@ -3670,6 +3719,7 @@ AcDbSurface *CoreTools::StringToFace(Adesk::UInt64 nLen, char *pszBody)
for (int i = 0; i < arBodyPtrs.length(); ++i) for (int i = 0; i < arBodyPtrs.length(); ++i)
DELETE_PTR(arBodyPtrs[i]); DELETE_PTR(arBodyPtrs[i]);
::DeleteFile(sFullPath);
return pFace; return pFace;
} }