• Bug#1109782: unblock: 7zip/25.00+dfsg-1 (6/13)

    From Bastian Germann@21:1/5 to All on Wed Jul 23 19:40:02 2025
    [continued from previous message]

    + unsigned lfn_RecordIndex = 0;
    + int checkSum = -1;
    + bool is_record_error = false;
    +
    for (UInt32 pos = blockSize;; pos += 32)
    {
    if (pos == blockSize)
    {
    pos = 0;

    - if ((NumDirClusters & 0xFF) == 0)
    - {
    - RINOK(OpenProgress())
    - }
    -
    if (clusterMode)
    {
    if (Header.IsEoc(cluster))
    @@ -514,21 +573,37 @@
    PRF(printf("\nCluster = %4X", cluster));
    RINOK(SeekToCluster(cluster))
    const UInt32 newCluster = Fat[cluster];
    - if ((newCluster & kFatItemUsedByDirMask) != 0)
    + if (newCluster & kFatItemUsedByDirMask)
    return S_FALSE;
    Fat[cluster] |= kFatItemUsedByDirMask;
    cluster = newCluster;
    NumDirClusters++;
    + if ((NumDirClusters & 0xFF) == 0)
    + {
    + RINOK(OpenProgress())
    + }
    NumCurUsedBytes += Header.ClusterSize();
    }
    else if (sectorIndex++ >= Header.NumRootDirSectors)
    break;

    + // if (curDirBytes_read > (1u << 28)) // do we need some relaxed limit for non-MS FATs?
    + if (curDirBytes_read >= (1u << 21)) // 2MB limit from FAT specification. + return S_FALSE;
    RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize))
    + curDirBytes_read += blockSize;
    }

    - const Byte *p = ByteBuf + pos;
    -
    + if (is_record_error)
    + {
    + Header.HeadersWarning = true;
    + num_lfn_records = 0;
    + lfn_RecordIndex = 0;
    + checkSum = -1;
    + }
    +
    + const Byte * const p = ByteBuf + pos;
    +
    if (p[0] == 0)
    {
    /*
    @@ -538,125 +613,191 @@
    */
    break;
    }
    -
    +
    + is_record_error = true;
    +
    if (p[0] == 0xE5)
    {
    - if (numLongRecords > 0)
    - return S_FALSE;
    + // deleted entry
    + if (num_lfn_records == 0)
    + is_record_error = false;
    continue;
    }
    -
    - Byte attrib = p[11];
    - if ((attrib & 0x3F) == 0xF)
    + // else
    {
    - if (p[0] > 0x7F || Get16(p + 26) != 0)
    - return S_FALSE;
    - int longIndex = p[0] & 0x3F;
    - if (longIndex == 0)
    - return S_FALSE;
    - bool isLast = (p[0] & 0x40) != 0;
    - if (numLongRecords < 0)
    + const Byte attrib = p[11];
    + // maybe we can use more strick check : (attrib == 0xF) ?
    + if ((attrib & 0x3F) == 0xF)
    {
    - if (!isLast)
    + // long file name (LFN) entry
    + const unsigned longIndex = p[0] & 0x3F;
    + if (longIndex == 0
    + || longIndex > k_NumLfnRecords_MAX
    + || p[0] > 0x7F
    + || Get16a(p + 26) != 0 // LDIR_FstClusLO
    + )
    + {
    + return S_FALSE;
    + // break;
    + }
    + const bool isLast = (p[0] & 0x40) != 0;
    + if (num_lfn_records == 0)
    + {
    + if (!isLast)
    + continue; // orphan
    + num_lfn_records = longIndex;
    + }
    + else if (isLast || longIndex != lfn_RecordIndex)
    + {
    return S_FALSE;
    - numLongRecords = longIndex;
    + // break;
    + }
    +
    + lfn_RecordIndex = longIndex - 1;
    +
    + if (p[12] == 0)
    + {
    + Byte * const dest = LfnBuf + k_NumLfnBytes_in_Record * lfn_RecordIndex;
    + memcpy(dest, p + 1, 5 * 2);
    + memcpy(dest + 5 * 2, p + 14, 6 * 2);
    + memcpy(dest + 11 * 2, p + 28, 2 * 2);
    + if (isLast)
    + checkSum = p[13];
    + if (checkSum == p[13])
    + is_record_error = false;
    + // else return S_FALSE;
    + continue;
    + }
    + // else
    + checkSum = -1; // we will ignore LfnBuf in this case
    + continue;
    }
    - else if (isLast || numLongRecords != longIndex)
    - return S_FALSE;
    -
    - numLongRecords--;

    - if (p[12] == 0)
    + if (lfn_RecordIndex)
    {
    - wchar_t nameBuf[14];
    - wchar_t *dest;
    -
    - dest = AddSubStringToName(nameBuf, p + 1, 5);
    - dest = AddSubStringToName(dest, p + 14, 6);
    - AddSubStringToName(dest, p + 28, 2);
    - curName = nameBuf + curName;
    - if (isLast)
    - checkSum = p[13];
    - if (checkSum != p[13])
    - return S_FALSE;
    + Header.HeadersWarning = true;
    + // return S_FALSE;
    }
    - }
    - else
    - {
    - if (numLongRecords > 0)
    - return S_FALSE;
    - CItem item;
    - memcpy(item.DosName, p, 11);
    + // lfn_RecordIndex = 0;

    - if (checkSum >= 0)
    + const unsigned type_in_attrib = attrib & 0x18;
    + if (type_in_attrib == 0x18)
    {
    - Byte sum = 0;
    - for (unsigned i = 0; i < 11; i++)
    - sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]);
    - if (sum == checkSum)
    - item.UName = curName;
    + // invalid directory record (both flags are set: dir_flag and volume_flag)
    + return S_FALSE;
    + // break;
    + // continue;
    }
    -
    - if (item.DosName[0] == 5)
    - item.DosName[0] = (char)(Byte)0xE5;
    - item.Attrib = attrib;
    - item.Flags = p[12];
    - item.Size = Get32(p + 28);
    - item.Cluster = Get16(p + 26);
    - if (Header.NumFatBits > 16)
    - item.Cluster |= ((UInt32)Get16(p + 20) << 16);
    - else
    + if (type_in_attrib == 8) // volume_flag
    {
    - // OS/2 and WinNT probably can store EA (extended atributes) in that field.
    + if (!VolItem_Defined && level == 0)
    + {
    + VolItem_Defined = true;
    + memcpy(VolLabel, p, 11);
    + Vol_MTime = Get32(p + 22);
    + is_record_error = false;
    + }
    }
    -
    - item.CTime = Get32(p + 14);
    - item.CTime2 = p[13];
    - item.ADate = Get16(p + 18);
    - item.MTime = Get32(p + 22);
    - item.Parent = parent;
    -
    - if (attrib == 8)
    + else if (memcmp(p, ". ", 11) == 0
    + || memcmp(p, ".. ", 11) == 0)
    {
    - VolItem = item;
    - VolItemDefined = true;
    + if (num_lfn_records == 0 && type_in_attrib == 0x10) // dir_flag
    + is_record_error = false;
    }
    else
    - if (memcmp(item.DosName, ". ", 11) != 0 &&
    - memcmp(item.DosName, ".. ", 11) != 0)
    {
    - if (!item.IsDir())
    - NumCurUsedBytes += Header.GetFilePackSize(item.Size);
    - Items.Add(item);
    - PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); + CItem &item = Items.AddNew();
    + memcpy(item.DosName, p, 11);
    + if (item.DosName[0] == 5)
    + item.DosName[0] = (char)(Byte)0xE5; // 0xE5 is valid KANJI lead byte value.
    + item.Attrib = attrib;
    + item.Flags = p[12];
    + item.Size = Get32a(p + 28);
    + item.Cluster = Get16a(p + 26);
    + if (Header.NumFatBits > 16)
    + item.Cluster |= ((UInt32)Get16a(p + 20) << 16);
    + else
    + {
    + // OS/2 and WinNT probably can store EA (extended atributes) in that field.
    + }
    + item.CTime = Get32(p + 14);
    + item.CTime2 = p[13];
    + item.ADate = Get16a(p + 18);
    + item.MTime = Get32(p + 22);
    + item.Parent = parent;
    + {
    + if (!item.IsDir())
    + NumCurUsedBytes += Header.GetFilePackSize(item.Size);
    + // PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1)));
    + PRF(printf("\n%7d" /* ": %S" */, Items.Size() /* , item.GetShortName() */ );)
    + }
    + if (num_lfn_records == 0)
    + is_record_error = false;
    + else if (checkSum >= 0 && lfn_RecordIndex == 0)
    + {
    + Byte sum = 0;
    + for (unsigned i = 0; i < 11; i++)
    + sum = (Byte)((sum << 7) + (sum >> 1) + (Byte)item.DosName[i]);
    + if (sum == checkSum)
    + {
    + const unsigned numWords = ParseLongName((UInt16 *)(void *)(Byte *)LfnBuf,
    + num_lfn_records * k_NumLfnBytes_in_Record / 2);
    + if (numWords > 1)
    + {
    + // numWords includes NULL terminator
    + item.LongName.CopyFrom(LfnBuf, numWords * 2);
    + is_record_error = false;
    + }
    + }
    + }
    +
    + if (
    + // item.LongName.Size() < 20 || // for debug
    + item.LongName.Size() <= 2 * 1
    + && memcmp(p, " ", 11) == 0)
    + {
    + char s[16 + 16];
    + const size_t numChars = (size_t)(ConvertUInt32ToString(
    + Items.Size() - 1 - startIndex,
    + MyStpCpy(s, "[NONAME]-")) - s) + 1;
    + item.LongName.Alloc(numChars * 2);
    + for (size_t i = 0; i < numChars; i++)
    + {
    + SetUi16a(item.LongName + i * 2, (Byte)s[i])
    + }
    + Header.HeadersWarning = true;
    + }
    }
    - numLongRecords = -1;
    - curName.Empty();
    - checkSum = -1;
    + num_lfn_records = 0;
    }
    }

    - unsigned finishIndex = Items.Size();
    + if (is_record_error)
    + Header.HeadersWarning = true;
    +
    + const unsigned finishIndex = Items.Size();
    for (unsigned i = startIndex; i < finishIndex; i++)
    {
    const CItem &item = Items[i];
    if (item.IsDir())
    {
    - PRF(printf("\n%S", GetItemPath(i)));
    - RINOK(CDatabase::ReadDir((int)i, item.Cluster, level + 1))
    + PRF(printf("\n---- %c%c%c%c%c", item.DosName[0], item.DosName[1], item.DosName[2], item.DosName[3], item.DosName[4]));
    + RINOK(ReadDir((int)i, item.Cluster, level + 1))
    }
    }
    return S_OK;
    }

    +
    +
    HRESULT CDatabase::Open()
    {
    Clear();
    - bool numFreeClustersDefined = false;
    + bool numFreeClusters_Defined = false;
    {
    - Byte buf[kHeaderSize];
    - RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize))
    - if (!Header.Parse(buf))
    + UInt32 buf32[kHeaderSize / 4];
    + RINOK(ReadStream_FALSE(InStream, buf32, kHeaderSize))
    + if (!Header.Parse((Byte *)(void *)buf32))
    return S_FALSE;
    UInt64 fileSize;
    RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize))
    @@ -671,21 +812,21 @@
    {
    if (((UInt32)Header.FsInfoSector << Header.SectorSizeLog) + kHeaderSize <= fileSize
    && SeekToSector(Header.FsInfoSector) == S_OK
    - && ReadStream_FALSE(InStream, buf, kHeaderSize) == S_OK
    - && 0xaa550000 == Get32(buf + 508)
    - && 0x41615252 == Get32(buf)
    - && 0x61417272 == Get32(buf + 484))
    + && ReadStream_FALSE(InStream, buf32, kHeaderSize) == S_OK
    + && 0xaa550000 == Get32a(buf32 + 508 / 4)
    + && 0x41615252 == Get32a(buf32)
    + && 0x61417272 == Get32a(buf32 + 484 / 4))
    {
    - NumFreeClusters = Get32(buf + 488);
    - numFreeClustersDefined = (NumFreeClusters <= Header.FatSize);
    + NumFreeClusters = Get32a(buf32 + 488 / 4);
    + numFreeClusters_Defined = (NumFreeClusters <= Header.FatSize);
    }
    else
    Header.HeadersWarning = true;
    }
    }

    - // numFreeClustersDefined = false; // to recalculate NumFreeClusters
    - if (!numFreeClustersDefined)
    + // numFreeClusters_Defined = false; // to recalculate NumFreeClusters
    + if (!numFreeClusters_Defined)
    NumFreeClusters = 0;

    CByteBuffer byteBuf;
    @@ -695,7 +836,7 @@
    RINOK(SeekToSector(Header.GetFatSector()))
    if (Header.NumFatBits == 32)
    {
    - const UInt32 kBufSize = (1 << 15);
    + const UInt32 kBufSize = 1 << 15;
    byteBuf.Alloc(kBufSize);
    for (UInt32 i = 0;;)
    {
    @@ -712,7 +853,7 @@
    const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf;
    UInt32 *dest = Fat + i;
    const UInt32 *srcLim = src + size;
    - if (numFreeClustersDefined)
    + if (numFreeClusters_Defined)
    do
    *dest++ = Get32a(src) & 0x0FFFFFFF;
    while (++src != srcLim);
    @@ -731,7 +872,7 @@
    i += size;
    if ((i & 0xFFFFF) == 0)
    {
    - RINOK(OpenProgressFat(!numFreeClustersDefined))
    + RINOK(OpenProgressFat(!numFreeClusters_Defined))
    }
    }
    }
    @@ -751,7 +892,7 @@
    for (UInt32 j = 0; j < fatSize; j++)
    fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF;

    - if (!numFreeClustersDefined)
    + if (!numFreeClusters_Defined)
    {
    UInt32 numFreeClusters = 0;
    for (UInt32 i = 0; i < fatSize; i++)
    @@ -781,11 +922,12 @@

    Z7_class_CHandler_final:
    public IInArchive,
    + public IArchiveGetRawProps,
    public IInArchiveGetStream,
    public CMyUnknownImp,
    CDatabase
    {
    - Z7_IFACES_IMP_UNK_2(IInArchive, IInArchiveGetStream)
    + Z7_IFACES_IMP_UNK_3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream)
    };

    Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) @@ -831,6 +973,8 @@
    COM_TRY_END
    }

    +
    +
    static const Byte kProps[] =
    {
    kpidPath,
    @@ -842,6 +986,7 @@
    kpidATime,
    kpidAttrib,
    kpidShortName
    + // , kpidCharacts
    };

    enum
    @@ -922,15 +1067,16 @@
    case kpidPhySize: prop = PhySize; break;
    case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break;
    case kpidHeadersSize: prop = GetHeadersSize(); break;
    - case kpidMTime: if (VolItemDefined) PropVariant_SetFrom_DosTime(prop, VolItem.MTime); break;
    + case kpidMTime: if (VolItem_Defined) PropVariant_SetFrom_DosTime(prop, Vol_MTime); break;
    case kpidShortComment:
    - case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break;
    + case kpidVolumeName: if (VolItem_Defined) GetVolName(VolLabel, prop); break;
    case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break;
    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;
    // case kpidNumHeads: prop = Header.NumHeads; break;
    // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break;
    case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break;
    + case kpidIsTree: prop = true; break;
    // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break;
    // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break;
    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
    @@ -948,6 +1094,52 @@
    COM_TRY_END
    }

    +
    +Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
    +{
    + *numProps = 0;
    + return S_OK;
    +}
    +
    +Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */ , BSTR *name, PROPID *propID))
    +{
    + *name = NULL;
    + *propID = 0;
    + return S_OK;
    +}
    +
    +Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))
    +{
    + *parentType = NParentType::kDir;
    + int par = -1;
    + if (index < Items.Size())
    + par = Items[index].Parent;
    + *parent = (UInt32)(Int32)par;
    + return S_OK;
    +}
    +
    +Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
    +{
    + *data = NULL;
    + *dataSize = 0;
    + *propType = 0;
    +
    + if (index < Items.Size()
    + && propID == kpidName)
    + {
    + CByteBuffer &buf = Items[index].LongName;
    + const UInt32 size = (UInt32)buf.Size();
    + if (size != 0)
    + {
    + *dataSize = size;
    + *propType = NPropDataType::kUtf16z;
    + *data = (const void *)(const Byte *)buf;
    + }
    + }
    + return S_OK;
    +}
    +
    +
    Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
    {
    COM_TRY_BEGIN
    @@ -955,8 +1147,28 @@
    const CItem &item = Items[index];
    switch (propID)
    {
    - case kpidPath: prop = GetItemPath(index); break;
    - case kpidShortName: prop = item.GetShortName(); break;
    + case kpidPath:
    + case kpidName:
    + case kpidShortName:
    + {
    + UString s;
    + if (propID == kpidPath)
    + GetItemPath(index, s);
    + else if (propID == kpidName)
    + item.GetName(s);
    + else
    + item.GetShortName(s);
    + prop = s;
    + break;
    + }
    +/*
    + case kpidCharacts:
    + {
    + if (item.LongName.Size())
    + prop = "LFN";
    + break;
    + }
    +*/
    case kpidIsDir: prop = item.IsDir(); break;
    case kpidMTime: PropVariant_SetFrom_DosTime(prop, item.MTime); break;
    case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break;
    @@ -1004,34 +1216,44 @@
    Int32 testMode, IArchiveExtractCallback *extractCallback))
    {
    COM_TRY_BEGIN
    - const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
    - if (allFilesMode)
    + if (numItems == (UInt32)(Int32)-1)
    + {
    + indices = NULL;
    numItems = Items.Size();
    - if (numItems == 0)
    - return S_OK;
    - UInt32 i;
    + if (numItems == 0)
    + return S_OK;
    + }
    + else
    + {
    + if (numItems == 0)
    + return S_OK;
    + if (!indices)
    + return E_INVALIDARG;
    + }
    UInt64 totalSize = 0;
    - for (i = 0; i < numItems; i++)
    {
    - const CItem &item = Items[allFilesMode ? i : indices[i]];
    - if (!item.IsDir())
    - totalSize += item.Size;
    + UInt32 i = 0;
    + do
    + {
    + UInt32 index = i;
    + if (indices)
    + index = indices[i];
    + const CItem &item = Items[index];
    + if (!item.IsDir())
    + totalSize += item.Size;
    + }
    + while (++i != numItems);
    }
    RINOK(extractCallback->SetTotal(totalSize))

    - UInt64 totalPackSize;
    - totalSize = totalPackSize = 0;
    -
    - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
    - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
    -
    - CLocalProgress *lps = new CLocalProgress;
    - CMyComPtr<ICompressProgressInfo> progress = lps;
    + CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
    lps->Init(extractCallback, false);
    + CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;

    - CDummyOutStream *outStreamSpec = new CDummyOutStream;
    - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
    + UInt64 totalPackSize;
    + totalSize = totalPackSize = 0;

    + UInt32 i;
    for (i = 0;; i++)
    {
    lps->InSize = totalPackSize;
    @@ -1039,46 +1261,45 @@
    RINOK(lps->SetCur())
    if (i == numItems)
    break;
    - CMyComPtr<ISequentialOutStream> realOutStream;
    - const Int32 askMode = testMode ?
    - NExtract::NAskMode::kTest :
    - NExtract::NAskMode::kExtract;
    - const UInt32 index = allFilesMode ? i : indices[i];
    - const CItem &item = Items[index];
    - RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
    -
    - if (item.IsDir())
    + int res;
    {
    + CMyComPtr<ISequentialOutStream> realOutStream;
    + const Int32 askMode = testMode ?
    + NExtract::NAskMode::kTest :
    + NExtract::NAskMode::kExtract;
    + UInt32 index = i;
    + if (indices)
    + index = indices[i];
    + const CItem &item = Items[index];
    + RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
    +
    + if (item.IsDir())
    + {
    + RINOK(extractCallback->PrepareOperation(askMode))
    + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
    + continue;
    + }
    +
    + totalPackSize += Header.GetFilePackSize(item.Size);
    + totalSize += item.Size;
    +
    + if (!testMode && !realOutStream)
    + continue;
    RINOK(extractCallback->PrepareOperation(askMode))
    - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
    - continue;
    - }
    -
    - totalPackSize += Header.GetFilePackSize(item.Size);
    - totalSize += item.Size;
    -
    - if (!testMode && !realOutStream)
    - continue;
    - RINOK(extractCallback->PrepareOperation(askMode))
    -
    - outStreamSpec->SetStream(realOutStream);
    - realOutStream.Release();
    - outStreamSpec->Init();
    -
    - int res = NExtract::NOperationResult::kDataError;
    - CMyComPtr<ISequentialInStream> inStream;
    - HRESULT hres = GetStream(index, &inStream);
    - if (hres != S_FALSE)
    - {
    - RINOK(hres)
    - if (inStream)
    + res = NExtract::NOperationResult::kDataError;
    + CMyComPtr<ISequentialInStream> inStream;
    + const HRESULT hres = GetStream(index, &inStream);
    + if (hres != S_FALSE)
    {
    - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
    - if (copyCoderSpec->TotalSize == item.Size)
    - res = NExtract::NOperationResult::kOK;
    + RINOK(hres)
    + if (inStream)
    + {
    + RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
    + if (copyCoder->TotalSize == item.Size)
    + res = NExtract::NOperationResult::kOK;
    + }
    }
    }
    - outStreamSpec->ReleaseStream();
    RINOK(extractCallback->SetOperationResult(res))
    }
    return S_OK;
    diff -Nru 7zip-24.09+dfsg/CPP/7zip/Archive/Nsis/NsisIn.cpp 7zip-25.00+dfsg/CPP/7zip/Archive/Nsis/NsisIn.cpp
    --- 7zip-24.09+dfsg/CPP/7zip/Archive/Nsis/NsisIn.cpp 2023-12-11 12:00:00.000000000 +0100
    +++ 7zip-25.00+dfsg/CPP/7zip/Archive/Nsis/NsisIn.cpp 2025-06-16 10:00:00.000000000 +0200
    @@ -4005,7 +4005,7 @@
    AddParam_Var(params[0]);
    AString temp;
    ReadString2(temp, params[1]);
    - if (temp != "$TEMP")
    + if (!temp.IsEqualTo("$TEMP"))
    SpaceQuStr(temp);
    break;
    }
    @@ -4410,7 +4410,7 @@
    }
    else
    {
    - if (func == "DllUnregisterServer")
    + if (func.IsEqualTo("DllUnregisterServer"))
    {
    s += "UnRegDLL";
    printFunc = false;
    @@ -4418,7 +4418,7 @@
    else
    {
    s += "RegDLL";
    - if (func == "DllRegisterServer")
    + if (func.IsEqualTo("DllRegisterServer"))
    printFunc = false;
    }
    AddParam(params[0]);
    @@ -4886,7 +4886,7 @@
    AddParam_Var(params[1]);
    AddParam(p