Coverage Report

Created: 2023-06-07 06:02

/src/unrar/arccmt.cpp
Line
Count
Source (jump to first uncovered line)
1
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
2
3
bool Archive::GetComment(Array<wchar> *CmtData)
4
1
{
5
1
  if (!MainComment)
6
1
    return false;
7
0
  int64 SavePos=Tell();
8
0
  bool Success=DoGetComment(CmtData);
9
0
  Seek(SavePos,SEEK_SET);
10
0
  return Success;
11
1
}
12
13
14
bool Archive::DoGetComment(Array<wchar> *CmtData)
15
0
{
16
0
#ifndef SFX_MODULE
17
0
  uint CmtLength;
18
0
  if (Format==RARFMT14)
19
0
  {
20
0
    Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
21
0
    CmtLength=GetByte();
22
0
    CmtLength+=(GetByte()<<8);
23
0
  }
24
0
  else
25
0
#endif
26
0
  {
27
0
    if (MainHead.CommentInHeader)
28
0
    {
29
      // Old style (RAR 2.9) archive comment embedded into the main 
30
      // archive header.
31
0
      Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
32
0
      if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
33
0
        return false;
34
0
    }
35
0
    else
36
0
    {
37
      // Current (RAR 3.0+) version of archive comment.
38
0
      Seek(GetStartPos(),SEEK_SET);
39
0
      return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
40
0
    }
41
0
#ifndef SFX_MODULE
42
    // Old style (RAR 2.9) comment header embedded into the main 
43
    // archive header.
44
0
    if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
45
0
    {
46
0
      uiMsg(UIERROR_CMTBROKEN,FileName);
47
0
      return false;
48
0
    }
49
0
    CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
50
0
#endif
51
0
  }
52
0
#ifndef SFX_MODULE
53
0
  if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
54
0
  {
55
0
    if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
56
0
      return false;
57
0
    ComprDataIO DataIO;
58
0
    DataIO.SetTestMode(true);
59
0
    uint UnpCmtLength;
60
0
    if (Format==RARFMT14)
61
0
    {
62
#ifdef RAR_NOCRYPT
63
      return false;
64
#else
65
0
      UnpCmtLength=GetByte();
66
0
      UnpCmtLength+=(GetByte()<<8);
67
0
      if (CmtLength<2)
68
0
        return false;
69
0
      CmtLength-=2;
70
0
      DataIO.SetCmt13Encryption();
71
0
      CommHead.UnpVer=15;
72
0
#endif
73
0
    }
74
0
    else
75
0
      UnpCmtLength=CommHead.UnpSize;
76
0
    DataIO.SetFiles(this,NULL);
77
0
    DataIO.EnableShowProgress(false);
78
0
    DataIO.SetPackedSizeToRead(CmtLength);
79
0
    DataIO.UnpHash.Init(HASH_CRC32,1);
80
0
    DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
81
82
0
    Unpack CmtUnpack(&DataIO);
83
0
    CmtUnpack.Init(0x10000,false);
84
0
    CmtUnpack.SetDestSize(UnpCmtLength);
85
0
    CmtUnpack.DoUnpack(CommHead.UnpVer,false);
86
87
0
    if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
88
0
    {
89
0
      uiMsg(UIERROR_CMTBROKEN,FileName);
90
0
      return false;
91
0
    }
92
0
    else
93
0
    {
94
0
      byte *UnpData;
95
0
      size_t UnpDataSize;
96
0
      DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
97
0
      if (UnpDataSize>0)
98
0
      {
99
#ifdef _WIN_ALL
100
        // If we ever decide to extend it to Android, we'll need to alloc
101
        // 4x memory for OEM to UTF-8 output here.
102
        OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
103
#endif
104
0
        CmtData->Alloc(UnpDataSize+1);
105
0
        memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
106
0
        CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
107
0
        CmtData->Alloc(wcslen(CmtData->Addr(0)));
108
0
      }
109
0
    }
110
0
  }
111
0
  else
112
0
  {
113
0
    if (CmtLength==0)
114
0
      return false;
115
0
    Array<byte> CmtRaw(CmtLength);
116
0
    int ReadSize=Read(&CmtRaw[0],CmtLength);
117
0
    if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
118
0
    {
119
0
      CmtLength=ReadSize;
120
0
      CmtRaw.Alloc(CmtLength);
121
0
    }
122
123
0
    if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
124
0
    {
125
0
      uiMsg(UIERROR_CMTBROKEN,FileName);
126
0
      return false;
127
0
    }
128
0
    CmtData->Alloc(CmtLength+1);
129
0
    CmtRaw.Push(0);
130
#ifdef _WIN_ALL
131
    // If we ever decide to extend it to Android, we'll need to alloc
132
    // 4x memory for OEM to UTF-8 output here.
133
    OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
134
#endif
135
0
    CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
136
0
    CmtData->Alloc(wcslen(CmtData->Addr(0)));
137
0
  }
138
0
#endif
139
0
  return CmtData->Size() > 0;
140
0
}
141
142
143
bool Archive::ReadCommentData(Array<wchar> *CmtData)
144
0
{
145
0
  Array<byte> CmtRaw;
146
0
  if (!ReadSubData(&CmtRaw,NULL,false))
147
0
    return false;
148
0
  size_t CmtSize=CmtRaw.Size();
149
0
  CmtRaw.Push(0);
150
0
  CmtData->Alloc(CmtSize+1);
151
0
  if (Format==RARFMT50)
152
0
    UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
153
0
  else
154
0
    if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
155
0
    {
156
0
      RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
157
0
      (*CmtData)[CmtSize/2]=0;
158
159
0
    }
160
0
    else
161
0
    {
162
0
      CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
163
0
    }
164
0
  CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
165
0
  return true;
166
0
}
167
168
169
void Archive::ViewComment()
170
1
{
171
1
  if (Cmd->DisableComment)
172
0
    return;
173
1
  Array<wchar> CmtBuf;
174
1
  if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
175
0
  {
176
0
    size_t CmtSize=CmtBuf.Size();
177
0
    wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
178
0
    if (ChPtr!=NULL)
179
0
      CmtSize=ChPtr-&CmtBuf[0];
180
0
    mprintf(L"\n");
181
0
    OutComment(&CmtBuf[0],CmtSize);
182
0
  }
183
1
}
184
185